Support Sapho ordering for shared arrivals
Verify and publish checkpoint container / container (push) Canceled after 0s
Verify and publish checkpoint container / container (push) Canceled after 0s
This commit is contained in:
1 parent
b18a767470
commit
e457478f7d
18 files changed
+808
-23
No files matched your search
@@ -0,0 +1,70 @@
|
||||
import assert from 'node:assert/strict';
|
||||
import test from 'node:test';
|
||||
import {
|
||||
createSaphoArrivalOrder,
|
||||
passSaphoArrivalOrder,
|
||||
quoteSaphoArrivalOrder,
|
||||
reorderSaphoArrivalOrder,
|
||||
validateSaphoArrivalOrder,
|
||||
} from '../game/sapho-arrival-order';
|
||||
|
||||
const owners = ['ecaz', 'moritani'] as const;
|
||||
const initial = () => createSaphoArrivalOrder('arrival:event', owners[0], owners[1]);
|
||||
const request = (player: string, revision: number) => ({ event: 'arrival:event', revision, player });
|
||||
|
||||
void test('both public arrival owners can pass and retain the original storm order', () => {
|
||||
const first = initial();
|
||||
assert.deepEqual(first.frame.holders, owners);
|
||||
validateSaphoArrivalOrder(first, 'arrival:event', owners, 'ecaz');
|
||||
const a = passSaphoArrivalOrder(first, request('ecaz', 0));
|
||||
assert.equal(a.done, false);
|
||||
const b = passSaphoArrivalOrder(a.order, request('moritani', 1));
|
||||
assert.equal(b.done, true);
|
||||
assert.deepEqual(b.order.queue.map(row => row.player), owners);
|
||||
assert.deepEqual(b.order.frame.passed, owners);
|
||||
validateSaphoArrivalOrder(b.order, 'arrival:event', owners, 'ecaz');
|
||||
assert.deepEqual(first.frame.passed, [], 'a later response does not mutate the prior frame');
|
||||
});
|
||||
|
||||
for (const [player, mode] of [['moritani', 'first'], ['ecaz', 'last']] as const) {
|
||||
void test(`${player} can select ${mode} without displacing a prior protected choice`, () => {
|
||||
const start = initial();
|
||||
assert.ok(quoteSaphoArrivalOrder(start, player).modes.includes(mode));
|
||||
const used = reorderSaphoArrivalOrder(start, { ...request(player, 0), mode });
|
||||
assert.equal(used.done, false);
|
||||
assert.deepEqual(used.order.queue.map(row => row.player), ['moritani', 'ecaz']);
|
||||
validateSaphoArrivalOrder(used.order, 'arrival:event', owners, 'moritani');
|
||||
const other = player === 'ecaz' ? 'moritani' : 'ecaz';
|
||||
assert.deepEqual(quoteSaphoArrivalOrder(used.order, other).modes, []);
|
||||
const passed = passSaphoArrivalOrder(used.order, request(other, 1));
|
||||
assert.equal(passed.done, true);
|
||||
validateSaphoArrivalOrder(passed.order, 'arrival:event', owners, 'moritani');
|
||||
assert.deepEqual(start.queue.map(row => row.player), owners);
|
||||
});
|
||||
}
|
||||
|
||||
void test('an arrival frame rejects stale, foreign, duplicate and no-op actions', () => {
|
||||
const start = initial();
|
||||
assert.throws(() => createSaphoArrivalOrder('arrival:event', 'ecaz', 'ecaz'));
|
||||
assert.throws(() => passSaphoArrivalOrder(start, request('outsider', 0)));
|
||||
assert.throws(() => passSaphoArrivalOrder(start, request('ecaz', 1)));
|
||||
assert.throws(() => reorderSaphoArrivalOrder(start, { ...request('ecaz', 0), mode: 'first' }));
|
||||
const passed = passSaphoArrivalOrder(start, request('ecaz', 0));
|
||||
assert.throws(() => passSaphoArrivalOrder(passed.order, request('ecaz', 1)));
|
||||
assert.throws(() => passSaphoArrivalOrder(passed.order, { ...request('moritani', 1), event: 'old' }));
|
||||
});
|
||||
|
||||
void test('an arrival receipt remains bound to the parent owners, event and chosen first reaction', () => {
|
||||
const used = reorderSaphoArrivalOrder(initial(), { ...request('moritani', 0), mode: 'first' }).order;
|
||||
const restored = JSON.parse(JSON.stringify(used)) as typeof used;
|
||||
validateSaphoArrivalOrder(restored, 'arrival:event', owners, 'moritani');
|
||||
assert.throws(() => validateSaphoArrivalOrder(restored, 'other:event', owners, 'moritani'));
|
||||
assert.throws(() => validateSaphoArrivalOrder(restored, 'arrival:event', ['moritani', 'ecaz'], 'moritani'));
|
||||
assert.throws(() => validateSaphoArrivalOrder(restored, 'arrival:event', owners, 'ecaz'));
|
||||
const tampered = structuredClone(restored);
|
||||
delete tampered.frame.protectedFirst;
|
||||
assert.throws(() => validateSaphoArrivalOrder(tampered, 'arrival:event', owners, 'moritani'));
|
||||
const duplicate = structuredClone(restored);
|
||||
duplicate.queue[1].player = duplicate.queue[0].player;
|
||||
assert.throws(() => validateSaphoArrivalOrder(duplicate, 'arrival:event', owners, 'moritani'));
|
||||
});
|
||||
Reference in new issue
Block a user