#!/bin/sh # Stand-in for the packaged client used by script/playable_gate_test.sh. # The fake app's Mach-O execs this file, so it runs as the runner's own child # PID. It never contacts a server; MT_FAKE_SCENARIO picks the behaviour. scenario="${MT_FAKE_SCENARIO:-pass}" write_report() { # $1 = PASS|BLOCKED, $2 = drop-last|evidence-missing|wrong-run|"" node -e ' const fs = require("node:fs"); const path = require("node:path"); const [status, variant] = process.argv.slice(1); const out = process.env.MT_TEST_OUTPUT; const required = JSON.parse(fs.readFileSync(path.join(out, "required-cases.json"), "utf8")).cases; const runId = variant === "wrong-run" ? "previous-run-0000" : process.env.MT_PLAYABLE_RUN_ID; const ids = variant === "drop-last" ? required.slice(0, -1) : required; const cases = ids.map((id) => ({ id, status, duration_ms: 1, reason: status === "PASS" ? "fake" : "fixture_not_ready", evidence: variant === "evidence-missing" && id === "NET-LOGIN-01" ? ["net-login-01.png"] : [] })); const events = ids.map((id, i) => JSON.stringify({ monotonic_us: 1000 + i, run_id: runId, case_id: id, connection_epoch: 1, stage: "LOGIN", kind: "phase_changed", actor_vid: 0, target_vid: 0, payload: { source: "server" } })); fs.writeFileSync(process.env.MT_TEST_EVENTS, events.join("\n") + "\n"); const report = { schema_version: 1, run_id: runId, suite: process.env.MT_PLAYABLE_SUITE || process.env.MT_TEST_MODE, status, build: { engine_sha256: process.env.MT_BUILD_ENGINE_SHA256, extension_sha256: process.env.MT_BUILD_EXTENSION_SHA256, pck_sha256: process.env.MT_BUILD_PCK_SHA256, arch: process.env.MT_BUILD_ARCH }, environment: { os: "macOS", renderer: "fake", resolution: [1280, 720] }, cases, required_cases: ids, events: "events.jsonl", event_count: events.length, failures: [], blocked: status === "BLOCKED" ? ids.map((id) => `${id}: fixture_not_ready`) : [], coverage: { required: cases.length, passed: status === "PASS" ? cases.length : 0 }, exit_gate: { checked: false, process_code: null, errors: [] }, }; fs.writeFileSync(process.env.MT_TEST_REPORT, JSON.stringify(report, null, 2)); ' "$1" "${2:-}" } case "$scenario" in cancel) exec node -e 'require("node:fs").writeFileSync(process.env.MT_TEST_OUTPUT + "/fake-child.pid", String(process.pid)); setInterval(() => {}, 1000)' ;; pass) write_report PASS; echo "PLAYABLE CLIENT: PASS" ;; soak-pass) write_report PASS; if [ "${MT_PLAYABLE_SUITE:-}" = "soak" ]; then sleep 3; fi; echo "PLAYABLE CLIENT: PASS" ;; exit3) write_report PASS; echo "PLAYABLE CLIENT: PASS"; exit 3 ;; signal) write_report PASS; kill -KILL $$ ;; hang) trap '' TERM; echo "ignoring TERM"; while :; do sleep 1; done ;; stale) write_report PASS wrong-run ;; no-report) echo "exited before writing a report" ;; rid) write_report PASS; echo "WARNING: 3 shaders of type CanvasItem were never freed." ;; leak) write_report PASS; echo "WARNING: ObjectDB instances leaked at exit (run with --verbose for details)." ;; missing-case) write_report PASS drop-last ;; missing-evidence) write_report PASS evidence-missing ;; blocked) write_report BLOCKED ;; print-secret) write_report PASS; echo "login request for $MT_ACCOUNT with $MT_PASSWORD" ;; fifo-holder) write_report PASS; sleep 13 & exit 0 ;; no-creds) if [ -n "${MT_ACCOUNT:-}${MT_PASSWORD:-}" ]; then echo "SCRIPT ERROR: credentials reached an offline child"; fi; write_report PASS ;; *) echo "unknown fake scenario" >&2; exit 64 ;; esac exit 0