amduat-api/scripts/smoke_v2.sh

130 lines
4.5 KiB
Bash
Raw Normal View History

2026-02-07 20:29:08 +01:00
#!/usr/bin/env bash
set -euo pipefail
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
# Use an isolated cursor file so smoke runs do not mutate normal sync state.
export CURSOR_FILE="${ROOT_DIR}/.cursor.smoke.$$"
# shellcheck source=/dev/null
source "${ROOT_DIR}/src/app_v2.sh"
require_jq() {
if ! command -v jq >/dev/null 2>&1; then
echo "smoke_v2.sh: jq is required" >&2
exit 2
fi
}
fail() {
echo "smoke_v2.sh: FAIL: $1" >&2
exit 1
}
step() {
echo "== $1 =="
}
cleanup() {
if [[ "${smoke_started_daemon:-0}" == "1" && -n "${smoke_daemon_pid:-}" ]]; then
kill "${smoke_daemon_pid}" >/dev/null 2>&1 || true
wait "${smoke_daemon_pid}" >/dev/null 2>&1 || true
fi
2026-02-07 20:29:08 +01:00
rm -f "${CURSOR_FILE}" >/dev/null 2>&1 || true
if [[ "${SMOKE_USE_EXISTING_DAEMON:-0}" != "1" ]]; then
rm -f "${smoke_sock:-}" >/dev/null 2>&1 || true
fi
2026-02-07 20:29:08 +01:00
}
trap cleanup EXIT
require_jq
SMOKE_USE_EXISTING_DAEMON="${SMOKE_USE_EXISTING_DAEMON:-0}"
smoke_started_daemon=0
smoke_daemon_pid=""
smoke_root="${SMOKE_STORE_ROOT:-/tmp/amduat-asl-smoke-${USER:-user}}"
smoke_sock="${SMOKE_SOCK:-/tmp/amduatd-smoke-${USER:-user}.sock}"
smoke_backend="${SMOKE_STORE_BACKEND:-fs}"
smoke_log="${SMOKE_DAEMON_LOG_PATH:-/tmp/smoke-v2-daemon.log}"
if [[ "${SMOKE_USE_EXISTING_DAEMON}" != "1" ]]; then
rm -f "${smoke_sock}" >/dev/null 2>&1 || true
export SOCK="${smoke_sock}"
STORE_BACKEND="${smoke_backend}" STORE_ROOT="${smoke_root}" SOCK="${smoke_sock}" SPACE="${SPACE:-app1}" \
nohup "${ROOT_DIR}/scripts/dev_start_daemon.sh" >"${smoke_log}" 2>&1 &
smoke_daemon_pid="$!"
smoke_started_daemon=1
ready=0
for _ in $(seq 1 120); do
if curl --globoff --silent --show-error --unix-socket "${smoke_sock}" "http://localhost/v2/readyz" >/dev/null 2>&1; then
ready=1
break
fi
sleep 0.1
done
[[ "${ready}" == "1" ]] || fail "isolated daemon did not become ready (log: ${smoke_log})"
fi
2026-02-07 20:29:08 +01:00
app_init
run_id="$(date +%s)"
idempotency_key="smoke-seed-${run_id}"
doc_name="smokedoc${run_id}"
topic_name="smoketopic${run_id}"
2026-02-07 20:29:08 +01:00
goal_pred="ms.within_domain"
step "startup"
startup_out="$(app_startup_checks)" || fail "startup checks failed"
printf '%s' "${startup_out}" | grep -q '"ok":true' || fail "readyz did not report ok=true"
step "ingest"
payload="$(cat <<JSON
{
"idempotency_key":"${idempotency_key}",
"mode":"continue_on_error",
"nodes":[{"name":"${doc_name}"},{"name":"${topic_name}"}],
"edges":[
{
"subject":"${doc_name}",
"predicate":"${goal_pred}",
"object":"${topic_name}",
"provenance":{
"source_uri":"urn:smoke:seed",
"extractor":"smoke-v2",
"observed_at":1,
"ingested_at":2,
"trace_id":"smoke-trace-${run_id}"
}
}
]
}
JSON
)"
ingest_out="$(app_ingest_batch "${payload}")" || fail "batch ingest call failed"
printf '%s' "${ingest_out}" | grep -q '"results"' || fail "batch ingest missing results"
step "sync"
sync_out="$(app_sync_once)" || fail "sync-once failed"
printf '%s' "${sync_out}" | grep -q '"events"' || fail "sync response missing events"
[[ -s "${CURSOR_FILE}" ]] || fail "cursor file was not persisted"
step "retrieve"
retrieve_out="$(app_retrieve_with_fallback "${doc_name}" "${goal_pred}")" || fail "retrieve call failed"
printf '%s' "${retrieve_out}" | grep -q '"edges"' || fail "retrieve response missing edges"
amduat_api_call GET "/v2/graph/subgraph?roots[]=${doc_name}&max_depth=2&dir=outgoing&limit_nodes=200&limit_edges=400&max_result_bytes=1048576" || fail "subgraph call failed"
subgraph_out="${AMDUAT_LAST_BODY}"
edge_ref="$(printf '%s' "${subgraph_out}" | jq -r '.edges[0].edge_ref // empty')"
[[ -n "${edge_ref}" ]] || fail "could not resolve edge_ref from subgraph"
step "tombstone"
app_tombstone_edge "${edge_ref}" >/dev/null || fail "tombstone call failed"
post_retrieve="$(app_retrieve_with_fallback "${doc_name}" "${goal_pred}")" || fail "post-tombstone retrieve failed"
post_edges_count="$(printf '%s' "${post_retrieve}" | jq '.edges | length')"
[[ "${post_edges_count}" == "0" ]] || fail "tombstoned edge still visible in default retrieval"
amduat_api_call GET "/v2/graph/subgraph?roots[]=${doc_name}&max_depth=2&dir=outgoing&limit_nodes=200&limit_edges=400&include_tombstoned=true&max_result_bytes=1048576" || fail "include_tombstoned subgraph failed"
visible_out="${AMDUAT_LAST_BODY}"
visible_has_edge="$(printf '%s' "${visible_out}" | jq --arg edge_ref "${edge_ref}" '[.edges[] | select(.edge_ref == $edge_ref)] | length')"
[[ "${visible_has_edge}" != "0" ]] || fail "tombstoned edge not visible with include_tombstoned=true"
echo "smoke_v2.sh: PASS"