// The room page's co-performance floor (co.js, `node --test web/room/co.test.mjs`): the turn // running at an instant ends at its segment's boundary, or at the `from` of a later schedule // that replaces its own (co-performance §6.1), whichever comes first; and a performer's page // keeps its guard (§8) before either, so that its last objects reach the relay and the room's // clock, a hop later, under the same schedule. import test from "node:test"; import assert from "node:assert/strict"; import { Co, GUARD_US } from "./co.js"; const A = "aa".repeat(32); const B = "bb".repeat(32); /** A page of `principal`, holding `schedules` in the room's order, with no records else. */ function page(principal, schedules) { const co = new Co({ wai: { coPolicy: () => "{}" }, me: () => ({ principal }), policyBytes: null }); co.schedules = schedules.map((s, i) => ({ digest: `s${i}`, order: i + 1, ...s })); return co; } // Six turns of 5 s from 0, A then B, under mark; then, from 7 s, two turns of 4 s, A then B, // under refuse. B holds the first schedule's second turn, [5 s, 10 s), when the second takes // effect. const MARK = { mode: "mark", from: 0, segments: [{ start: 0, turn_us: 5_000_000, turns: 6, pairs: 0, holders: [A, B] }] }; const REFUSE = { mode: "refuse", from: 7_000_000, segments: [{ start: 7_000_000, turn_us: 4_000_000, turns: 2, pairs: 0, holders: [A, B] }] }; test("a turn a later schedule replaces ends at that schedule's from", () => { const co = page(B, [MARK, REFUSE]); const t = co.turnAt(6_900_000); assert.equal(t.holder, B); assert.equal(t.start, 5_000_000); assert.equal(t.end, 7_000_000); assert.equal(t.mode, "mark"); const u = co.turnAt(7_000_000); assert.equal(u.holder, A); assert.equal(u.mode, "refuse"); assert.equal(u.start, 7_000_000); assert.equal(u.end, 11_000_000); }); test("a turn no later schedule replaces ends at its segment's boundary", () => { const co = page(B, [MARK]); assert.equal(co.turnAt(6_900_000).end, 10_000_000); assert.equal(co.turnAt(1_000_000).end, 5_000_000); }); test("the holder of a replaced turn stops its guard before the next schedule's from", () => { const co = page(B, [MARK, REFUSE]); assert.equal(co.sends(7_000_000 - GUARD_US - 1), true); assert.equal(co.sends(7_000_000 - GUARD_US), false); assert.equal(co.sends(6_999_999), false); // From the from on, B does not hold the floor until its turn of the new schedule, guarded. assert.equal(co.sends(9_000_000), false); assert.equal(co.sends(11_000_000 + GUARD_US - 1), false); assert.equal(co.sends(11_000_000 + GUARD_US), true); }); test("the holder of the next schedule's first turn starts its guard after the from", () => { const co = page(A, [MARK, REFUSE]); assert.equal(co.sends(7_000_000 + GUARD_US - 1), false); assert.equal(co.sends(7_000_000 + GUARD_US), true); }); test("the turns ahead step from the replaced turn to the next schedule's", () => { const co = page(B, [MARK, REFUSE]); const ahead = co.turnsAhead(6_000_000, 3).map((t) => [t.holder, t.start, t.end, t.mode]); assert.deepEqual(ahead, [ [B, 5_000_000, 7_000_000, "mark"], [A, 7_000_000, 11_000_000, "refuse"], [B, 11_000_000, 15_000_000, "refuse"], ]); }); test("a schedule stated later governs even where an earlier-stated one's from is later", () => { // §6.1: the schedule in effect is the last stated of those whose from has come. REFUSE was // stated first; MARK, stated after it, governs from 0 on and nothing replaces it. const co = page(B, [REFUSE, MARK]); const t = co.turnAt(6_900_000); assert.equal(t.mode, "mark"); assert.equal(t.end, 10_000_000); assert.equal(co.turnAt(8_000_000).mode, "mark"); });