aboutsummaryrefslogtreecommitdiffstats
path: root/prototypes/live-rules/adapter.test.mjs
diff options
context:
space:
mode:
Diffstat (limited to 'prototypes/live-rules/adapter.test.mjs')
-rw-r--r--prototypes/live-rules/adapter.test.mjs96
1 files changed, 96 insertions, 0 deletions
diff --git a/prototypes/live-rules/adapter.test.mjs b/prototypes/live-rules/adapter.test.mjs
new file mode 100644
index 0000000..95af13b
--- /dev/null
+++ b/prototypes/live-rules/adapter.test.mjs
@@ -0,0 +1,96 @@
+import { test } from 'node:test';
+import assert from 'node:assert/strict';
+import { loadCore, snapshot, storage, parseCommand, execute } from './runtime.mjs';
+
+test('the actual Wasm preserves airborne state through a rule change, then permits the second jump', async () => {
+ const c = await loadCore();
+ execute(c, parseCommand('jump'));
+ execute(c, parseCommand('step 8'));
+ execute(c, parseCommand('jump'));
+ const before = snapshot(c);
+ assert.equal(before.state.lastReason, 3);
+ const after = execute(c, parseCommand('rules double 12 on'));
+ for (const field of ['tick', 'y', 'vy', 'distance', 'obstacleX', 'jumpsUsed', 'hits', 'passed']) {
+ assert.equal(after.state[field], before.state[field], field);
+ }
+ assert.deepEqual(after.decision, before.decision);
+ assert.equal(after.state.revision, 1);
+ execute(c, parseCommand('jump'));
+ assert.equal(c.get(10), 1);
+ assert.equal(c.get(2), 1200);
+ assert.equal(c.get(7), 2);
+ assert.equal(c.input(2), 0);
+ assert.equal(c.get(10), 4);
+});
+
+test('bad CLI edits and malformed numeric input cannot silently coerce into a different rule', async () => {
+ const c = await loadCore();
+ const before = snapshot(c);
+ for (const command of ['rules double 8.5 on', 'rules double 4294967306 on', 'rules ground 5 on',
+ 'rules other 10 on', 'rules double 10 maybe', 'rules double 10 on extra', 'step 0', 'step 601', 'jump extra']) {
+ assert.throws(() => execute(c, parseCommand(command)), undefined, command);
+ assert.deepEqual(snapshot(c), before);
+ }
+ assert.equal(c.apply_rules(2, 10, 1), 1);
+ assert.deepEqual(snapshot(c), before);
+});
+
+test('keyboard, pointer and terminal requests give the same simulation result', async () => {
+ const states = [];
+ for (const source of [0, 1, 2]) {
+ const c = await loadCore();
+ c.apply_rules(1, 12, 1);
+ c.input(source);
+ for (let i = 0; i < 8; i++) c.step();
+ c.input(source);
+ const { lastSource, ...state } = snapshot(c).state;
+ assert.equal(lastSource, source);
+ states.push(state);
+ }
+ assert.deepEqual(states[0], states[1]);
+ assert.deepEqual(states[1], states[2]);
+});
+
+test('paused input has an inspectable decision; advance cannot move paused state', async () => {
+ const c = await loadCore();
+ assert.equal(snapshot(c).decision, null);
+ assert.equal(c.input(0), 1);
+ assert.equal(c.get(1), 0);
+ assert.equal(c.get(17), 0);
+ const before = snapshot(c);
+ assert.equal(c.advance(60), 0);
+ assert.deepEqual(snapshot(c), before);
+ c.step();
+ assert.equal(c.get(1), 945);
+ assert.equal(c.get(0), 1);
+});
+
+test('bounded history and fixed linear memory survive repeated play and edits', async () => {
+ const c = await loadCore();
+ const before = storage(c);
+ c.set_running(1);
+ for (let i = 0; i < 5000; i++) {
+ c.apply_rules(i % 2, 6 + i % 11, 1);
+ c.input(i % 3);
+ c.advance(8);
+ }
+ assert.equal(c.history_count(), 16);
+ assert.equal(c.history_get(16, 0), -1);
+ assert.equal(c.get(0), 40000);
+ assert.deepEqual(storage(c), before);
+ assert.equal(before.wasmLinearMemoryBytes, 65536);
+ assert.throws(() => c.memory.grow(1), RangeError);
+ const b = before.layoutBytes;
+ assert.equal(b.logicalTotal, b.engine + b.graph);
+ assert.ok(b.engine >= b.rules + b.state + b.decision + b.history);
+});
+
+test('replaying the same CLI operations produces identical snapshots and journal', async () => {
+ const trace = ['jump', 'step 8', 'jump', 'rules double 10 on', 'jump', 'step 60', 'rules ground 8 off', 'jump'];
+ const snapshots = [];
+ for (let i = 0; i < 2; i++) {
+ const c = await loadCore();
+ snapshots.push(trace.map((line) => execute(c, parseCommand(line))));
+ }
+ assert.deepEqual(snapshots[0], snapshots[1]);
+});