Files
gods-eye-view/src/tooling/trackArrivalObservation.test.mjs
T
Said Turksever d026952397 fix(track): name a measured angle violation in the harness log; docs: nginx Host $http_host keeps the port the Origin check compares
- fmtArr prints reveal-err and flags an angle violation on a timeout result.
- Regression: a late hidden reveal frame records no angle and stays retryable.
- README/SECURITY: $host drops a non-default port, so recommend $http_host.
- requestAdmission tests: say why a new admission test must use freshClock.
2026-10-26 14:19:21 +00:00

375 lines
13 KiB
JavaScript

import test from 'node:test';
import assert from 'node:assert/strict';
import { readFileSync } from 'node:fs';
import * as arrivalModule from './trackArrivalObservation.mjs';
import {
ARRIVAL_OBSERVATION_MS,
arrivalAngleViolated,
arrivalRotationPassed,
observeArrivalRotation,
observeArrivalRotationWithRetry,
} from './trackArrivalObservation.mjs';
function fixture(start = observeArrivalRotation) {
let time = 0;
let state = { shown: true, rotationError: 0 };
const listeners = new Set();
const timers = new Map();
let renders = 0;
let moveEnds = 0;
const observation = start({
scene: {
postRender: {
addEventListener(listener) {
listeners.add(listener);
return () => listeners.delete(listener);
},
},
requestRender() {
renders++;
},
},
startMoveEnd() {
moveEnds++;
state.rotationError = 1.5;
},
startReveal() {
state = { shown: false, rotationError: 1.5 };
},
read: () => ({ ...state }),
now: () => time,
setTimer(callback, delay) {
const handle = {};
timers.set(handle, { callback, at: time + delay });
return handle;
},
clearTimer(handle) {
timers.delete(handle);
},
});
return {
observation,
frame(at, nextState) {
time = at;
state = { ...state, ...nextState };
for (const listener of [...listeners]) listener();
},
expire(at) {
time = at;
for (const timer of [...timers.values()])
if (timer.at <= at) timer.callback();
},
get resources() {
return {
listeners: listeners.size,
timers: timers.size,
renders,
moveEnds,
};
},
};
}
test('80 ms fleet scheduling passes after more than four fast rendered frames', async () => {
const f = fixture();
f.frame(8, { shown: true, rotationError: 0 });
// The forced fleet tick was at 8 ms. A 125 FPS renderer can complete nine
// more frames before the next 80 ms fleet interval becomes eligible.
for (let at = 16; at < 88; at += 8) f.frame(at);
f.frame(88, { shown: true, rotationError: 0 });
const result = await f.observation;
assert.equal(result.flipFrame, 10);
assert.equal(result.moveEndMs, 8);
assert.equal(result.revealMs, 80);
assert.equal(result.elapsedMs, 88);
assert.equal(arrivalRotationPassed(result), true);
assert.equal(f.resources.listeners, 0);
assert.equal(f.resources.timers, 0);
assert.equal(f.resources.moveEnds, 1);
});
test('a wrong first visible angle fails even if the next frame corrects it', async () => {
const f = fixture();
f.frame(8, { shown: true, rotationError: 0 });
f.frame(88, { shown: true, rotationError: 1.5 });
f.frame(96, { shown: true, rotationError: 0 });
const result = await f.observation;
assert.equal(result.dReveal, 1.5);
assert.equal(result.flipFrame, 1);
assert.equal(result.elapsedMs, 88);
assert.equal(arrivalRotationPassed(result), false);
});
test('a wrong first moveEnd angle is retained rather than repaired by reveal', async () => {
const f = fixture();
f.frame(8, { shown: true, rotationError: 1.5 });
f.frame(88, { shown: true, rotationError: 0 });
const result = await f.observation;
assert.equal(result.dMoveEnd, 1.5);
assert.equal(arrivalRotationPassed(result), false);
});
test('no reveal fails at a deadline before the one-second idle catch-up', async () => {
const f = fixture();
assert.equal(ARRIVAL_OBSERVATION_MS, 500);
f.frame(8, { shown: true, rotationError: 0 });
f.frame(480);
// The reveal budget is measured from the 8 ms settle frame.
f.expire(508);
const result = await f.observation;
assert.match(result.error, /reveal.*500 ms/);
assert.equal(arrivalRotationPassed(result), false);
assert.equal(f.resources.listeners, 0);
assert.equal(f.resources.timers, 0);
f.frame(1000, { shown: true, rotationError: 0 });
assert.equal(result.flipFrame, -1);
});
test('a late visible frame fails even if the timeout callback is delayed', async () => {
const f = fixture();
f.frame(8, { shown: true, rotationError: 0 });
f.frame(509, { shown: true, rotationError: 0 });
const result = await f.observation;
assert.match(result.error, /reveal.*500 ms/);
assert.equal(result.elapsedMs, 509);
assert.equal(arrivalRotationPassed(result), false);
});
test('a slow software renderer passes when each frame stays inside its own budget', async () => {
// Headless SwiftShader frames run ~300 ms: settle lands at 300 ms and the
// reveal at 600 ms from moveEnd. Both stay inside the 1 s idle refresh.
const f = fixture();
f.frame(300, { shown: true, rotationError: 0 });
f.expire(500); // the settle frame re-armed the deadline to 800 ms
f.frame(600, { shown: true, rotationError: 0 });
const result = await f.observation;
assert.equal(result.moveEndMs, 300);
assert.equal(result.revealMs, 300);
assert.equal(result.elapsedMs, 600);
assert.equal(result.flipFrame, 1);
assert.equal(arrivalRotationPassed(result), true);
assert.equal(f.resources.timers, 0);
});
test('a settle frame later than its budget fails as a moveEnd timeout', async () => {
const f = fixture();
f.frame(500, { shown: true, rotationError: 0 });
const result = await f.observation;
assert.match(result.error, /moveEnd.*500 ms/);
assert.equal(result.moveEndMs, null);
assert.equal(arrivalRotationPassed(result), false);
});
test('a reveal later than its own budget fails even after a fast settle frame', async () => {
const f = fixture();
f.frame(400, { shown: true, rotationError: 0 });
f.frame(901, { shown: true, rotationError: 0 });
const result = await f.observation;
assert.match(result.error, /reveal.*500 ms/);
assert.equal(result.moveEndMs, 400);
assert.equal(result.elapsedMs, 901);
assert.equal(arrivalRotationPassed(result), false);
});
test('missing moveEnd frames fail without waiting for a render callback', async () => {
const f = fixture();
f.expire(500);
const result = await f.observation;
assert.match(result.error, /moveEnd.*500 ms/);
assert.equal(arrivalRotationPassed(result), false);
assert.equal(f.resources.listeners, 0);
assert.equal(f.resources.timers, 0);
});
// Let a retry's next attempt register its postRender listener.
const settle = () => new Promise((resolve) => setImmediate(resolve));
function retryFixture(extra = {}) {
const counts = { prepares: 0 };
const f = fixture((options) =>
observeArrivalRotationWithRetry({
...options,
...extra,
async prepare() {
counts.prepares++;
},
}),
);
f.counts = counts;
return f;
}
test('a wrong settle angle followed by a reveal timeout is final, not retried into a pass', async () => {
const f = retryFixture();
await settle();
// 0.5 rad ≈ 29°: a real threshold violation on the settle frame.
f.frame(8, { shown: true, rotationError: 0.5 });
f.expire(508); // the reveal never comes inside its budget
await settle();
// An otherwise clean second attempt, which must never be started.
f.frame(516, { shown: true, rotationError: 0 });
f.frame(524, { shown: true, rotationError: 0 });
const result = await f.observation;
assert.match(result.error, /reveal.*500 ms/);
assert.equal(result.dMoveEnd, 0.5, 'the measured settle angle is kept');
assert.equal(arrivalAngleViolated(result), true);
assert.equal(result.attempts, 1);
assert.equal(f.counts.prepares, 1);
assert.equal(f.resources.moveEnds, 1);
assert.equal(arrivalRotationPassed(result), false);
assert.equal(f.resources.listeners, 0);
assert.equal(f.resources.timers, 0);
});
test('an inconclusive reveal timeout after a correct settle earns one more attempt', async () => {
const f = retryFixture();
await settle();
f.frame(8, { shown: true, rotationError: 0 });
f.expire(508);
await settle();
f.frame(516, { shown: true, rotationError: 0 });
f.frame(596, { shown: true, rotationError: 0 });
const result = await f.observation;
assert.equal(result.attempts, 2);
assert.equal(f.counts.prepares, 2);
assert.equal(f.resources.moveEnds, 2);
assert.equal(arrivalRotationPassed(result), true);
});
test('timeouts stop after the attempt limit and still fail', async () => {
const f = retryFixture();
await settle();
f.expire(500);
await settle();
f.expire(1000);
const result = await f.observation;
assert.match(result.error, /moveEnd.*500 ms/);
assert.equal(result.attempts, 2);
assert.equal(arrivalRotationPassed(result), false);
assert.equal(f.resources.listeners, 0);
assert.equal(f.resources.timers, 0);
});
test('a missing or non-finite angle never passes', () => {
const clean = {
shown: true,
moveEndMs: 8,
revealMs: 80,
dMoveEnd: 0,
dReveal: 0,
};
assert.equal(arrivalRotationPassed(clean), true);
for (const field of ['dMoveEnd', 'dReveal']) {
assert.equal(arrivalRotationPassed({ ...clean, [field]: NaN }), false);
assert.equal(
arrivalRotationPassed({ ...clean, [field]: undefined }),
false,
);
}
});
test('a wrong angle on a late reveal frame is final, not retried into a pass', async () => {
const f = retryFixture();
await settle();
f.frame(100, { shown: true, rotationError: 0 });
// Shown at 600 ms (500 ms after settle) still wearing the tampered nose.
f.frame(600, { shown: true, rotationError: 1.5 });
await settle();
f.frame(608, { shown: true, rotationError: 0 });
f.frame(688, { shown: true, rotationError: 0 });
const result = await f.observation;
assert.match(result.error, /reveal.*500 ms/);
assert.equal(result.dReveal, 1.5);
assert.equal(result.attempts, 1);
assert.equal(f.resources.moveEnds, 1);
assert.equal(arrivalRotationPassed(result), false);
});
test('a wrong angle on a late settle frame is final, not retried into a pass', async () => {
const f = retryFixture();
await settle();
f.frame(926, { shown: true, rotationError: 1.5 });
await settle();
f.frame(934, { shown: true, rotationError: 0 });
f.frame(1014, { shown: true, rotationError: 0 });
const result = await f.observation;
assert.match(result.error, /moveEnd.*500 ms/);
assert.equal(result.dMoveEnd, 1.5);
assert.equal(result.attempts, 1);
assert.equal(arrivalRotationPassed(result), false);
});
test('a late hidden reveal frame records no angle and stays retryable', async () => {
const f = retryFixture();
await settle();
f.frame(8, { shown: true, rotationError: 0 });
// Still hidden, still tampered: not a measured reveal angle.
f.frame(600, { shown: false });
const first = f.observation;
await settle();
f.frame(608, { shown: true, rotationError: 0 });
f.frame(688, { shown: true, rotationError: 0 });
const result = await first;
assert.equal(result.attempts, 2);
assert.equal(result.dReveal, 0);
assert.equal(arrivalRotationPassed(result), true);
});
test('a late frame with correct angles stays an inconclusive, retryable timeout', async () => {
const f = retryFixture();
await settle();
f.frame(926, { shown: true, rotationError: 0 });
await settle();
f.frame(934, { shown: true, rotationError: 0 });
f.frame(1014, { shown: true, rotationError: 0 });
const result = await f.observation;
assert.equal(result.attempts, 2);
assert.equal(arrivalRotationPassed(result), true);
});
test('a wrong first reveal on time is final: no retry', async () => {
const f = retryFixture();
await settle();
f.frame(8, { shown: true, rotationError: 0 });
f.frame(88, { shown: true, rotationError: 1.5 });
const result = await f.observation;
assert.equal(result.error, undefined);
assert.equal(result.attempts, 1);
assert.equal(f.resources.moveEnds, 1);
assert.equal(arrivalRotationPassed(result), false);
});
test('maxAttempts bounds inconclusive retries', async () => {
const f = retryFixture({ maxAttempts: 3 });
for (let attempt = 1; attempt <= 3; attempt++) {
await settle();
f.expire(attempt * 500);
}
const result = await f.observation;
assert.equal(result.attempts, 3);
assert.equal(f.counts.prepares, 3);
assert.equal(arrivalRotationPassed(result), false);
});
test('the 10° limit is inclusive', () => {
const limit = Math.PI / 18;
assert.equal(arrivalAngleViolated({ dMoveEnd: limit }), true);
assert.equal(arrivalAngleViolated({ dReveal: limit * 0.999 }), false);
});
test('every name the track harness imports from this module is exported', () => {
const harness = readFileSync(
new URL('../../scripts/track-regression.mjs', import.meta.url),
'utf8',
);
const names = [
...harness.matchAll(
/(?:import|const)\s*\{([^}]+)\}\s*(?:from\s*|=\s*await import\()[^;]*trackArrivalObservation\.mjs/g,
),
].flatMap((match) => match[1].split(',').map((name) => name.trim()));
assert.ok(names.includes('arrivalRotationPassed'));
assert.ok(names.includes('observeArrivalRotationWithRetry'));
for (const name of names)
assert.equal(typeof arrivalModule[name], 'function', name);
});