import assert from "node:assert/strict"; import { test } from "node:test"; import { NetworkFaults } from "./network"; import { AssertableState } from "../deterministic-tests/src/utils/assertable-state"; import { TESTS } from "../deterministic-tests/src/test-registry"; import type { ExpectedDocument } from "../deterministic-tests/src/test-definition"; const id = "00000000-0000-4000-8000-000000000001"; function state( files: Record, identities = Object.fromEntries( Object.keys(files).map((path, i) => [ i ? id.replace(/1$/, String(i + 1)) : id, path ]) ) ) { const map = new Map(Object.entries(files)); return new AssertableState({ files: map, clientFiles: [map, new Map(map)], canonical: identities, manifests: [identities, identities], bytes: new Map( [...map].map(([path, text]) => [ path, new TextEncoder().encode(text) ]) ) }); } test("scripted verifiers reject the concrete shared-loss and duplication counterexamples", () => { const cases = [ [ "multi-file-operations", { "B.md": "updated", "C.md": "CORRUPTED", "unexpected.md": "EXTRA" } ], [ "concurrent-edit-exact-same-position", { "doc.md": "slow slow fast brown fox CORRUPTED" } ] ] as const; for (const [name, files] of cases) { const step = TESTS[name]!.steps.filter( (s) => s.type === "assert-consistent" ).at(-1)!; assert.throws(() => step.verify!(state(files))); } const partial = state({ "a.md": "A", "b.md": "B" }); partial.assertContent("a.md", "A"); assert.throws(() => partial.assertComplete(), /complete file set/); }); test("complete document oracles kill lost-byte, duplicate-file and identity-reuse mutations", () => { const expected: ExpectedDocument[] = [ { key: "a", path: "a.md", content: "exact bytes 🦊\r\n" } ]; const identities = new Map(); state({ "a.md": "exact bytes 🦊\r\n" }).assertDocuments( expected, identities ); const corruptions: Record[] = [ { "a.md": "exact bytes 🦊\n" }, { "a.md": "exact bytes 🦊\r\nexact bytes 🦊\r\n" }, { "a.md": "exact bytes 🦊\r\n", "extra.md": "EXTRA" } ]; for (const corrupted of corruptions) assert.throws(() => state(corrupted).assertDocuments(expected, identities) ); assert.throws( () => state( { "a.md": "exact bytes 🦊\r\n" }, { [id.replace(/1$/, "2")]: "a.md" } ).assertDocuments(expected, identities), /identity changed/ ); assert.throws( () => state({ "a.md": "exact bytes 🦊\r\n" }).assertDocuments( [{ ...expected[0], key: "recreated" }], identities ), /reused/ ); }); test("request checkpoints hold the exact boundary and reject unexercised response predicates", async () => { const network = new NetworkFaults(); let sent = 0, completed = false; const input = "http://localhost/vaults/test/documents/document"; const init = { method: "PUT", body: JSON.stringify({ requestId: "one", parentVersionId: 1 }) }; const fetcher = network.wrap(async () => { sent++; return Response.json({ type: "StaleBase" }); }); network.hold({ kind: "content", point: "before" }); assert.throws(() => network.resumeRequest(), /before it is reached/); const request = fetcher(input, init).then(() => { completed = true; }); await network.waitForHeldRequest(); assert.equal(sent, 0); assert.equal(completed, false); assert.throws(() => network.assertConsumed(), /never released/); network.resumeRequest(); await request; network.assertConsumed(); assert.equal(network.requests[0].responseType, "StaleBase"); network.hold({ kind: "content", point: "after", responseType: "Accepted" }); assert.equal( network.requestsSinceCheckpoint().length, 0, "An earlier response must not satisfy a new race assertion" ); await fetcher(input, init); assert.throws(() => network.assertConsumed(), /never reached/); network.releaseRequests(); }); test("scripted races have no sleep steps and the stale-content regression asserts its response", () => { for (const [name, scenario] of Object.entries(TESTS)) assert( !scenario!.steps.some((s) => s.type === "sleep"), `${name} still relies on timing` ); assert( TESTS["merging-update-response-survives-user-rename"]!.steps.some( (s) => s.type === "assert-response" && s.responseType === "StaleBase" ) ); });