Files
linuxcncWebWASM/web/worker/test_replay.mjs

47 lines
2.1 KiB
JavaScript

import assert from "node:assert/strict";
import { EventLog, ReplayTimeline, SnapshotStore, fnv1a64, REPLAY_SCHEMA } from "./replay.mjs";
function buildTimeline() {
const timeline = new ReplayTimeline();
timeline.appendEvent(1, 0, "SESSION_READY", {});
timeline.appendEvent(2, 5, "SIM_STEP", { cycles: 5 });
timeline.checkpoint(2, 5, { tick: 5, position: 5 });
timeline.appendEvent(3, 9, "SIM_STEP", { cycles: 4 });
const base = timeline.snapshots.latest().snapshot_id;
timeline.checkpoint(3, 9, { tick: 9, position: 9 }, base);
return timeline;
}
const first = buildTimeline();
const second = buildTimeline();
assert.deepEqual(first.export(), second.export());
const replay = first.replay({ tick: 0, position: 0 }, (state, event) => ({
tick: event.tick,
position: state.position + (event.payload.cycles ?? 0),
}));
assert.equal(replay.tick, 9);
assert.equal(replay.state.position, 9);
assert.equal(replay.state_hash, fnv1a64({ tick: 9, position: 9 }));
assert.throws(() => {
const log = new EventLog();
log.append(2, 0, "GAP", {});
}, /event_sequence_gap/);
assert.throws(() => {
const snapshots = new SnapshotStore();
snapshots.create(1, 1, { tick: 1 }, "snap:missing");
}, /snapshot_base_missing/);
const exported = first.export();
assert.equal(exported.schema, REPLAY_SCHEMA);
exported.snapshots.snapshots[0].state_hash = "fnv1a64:0000000000000000";
assert.throws(() => new ReplayTimeline(exported), /snapshot_hash_mismatch/);
assert.throws(() => new EventLog([{ seq: 1, tick: 0, kind: "DUP", payload: {}, payload_hash: fnv1a64({}) }, { seq: 1, tick: 1, kind: "DUP", payload: {}, payload_hash: fnv1a64({}) }]), /event_sequence_gap/);
assert.throws(() => first.checkpoint(3, 8, { tick: 8 }), /checkpoint_cursor_mismatch/);
assert.throws(() => first.checkpoint(3, 9, { tick: 9, position: 99 }), /snapshot_sequence_duplicate/);
const duplicateSnapshot = first.export();
duplicateSnapshot.snapshots.snapshots.push({ ...duplicateSnapshot.snapshots.snapshots[1] });
assert.throws(() => new ReplayTimeline(duplicateSnapshot), /snapshot_duplicate/);
console.log("replay=passed cursor=" + replay.cursor + " tick=" + replay.tick);