/** * Every scenario, raised for real, checked against the invariants that hold of all of them. * * The suite next door raises one scenario and asks deep questions of it. This one asks * shallow questions of every scenario, which is the half that was missing: both faults found * by hand so far — two gateways holding one address, and a gateway drawn across an unrelated * network — lived in scenarios nothing ever built. * * The list grows. Each entry costs a boot, so it is added deliberately rather than by * globbing the directory: a scenario that is expensive and adds no new shape is not worth * the wall clock, and one that is cheap and adds a shape is. */ import { test, after } from "node:test"; import { loadScenario } from "../../src/declaration/parse.ts"; import { raise } from "../../src/lifecycle/raise.ts"; import { destroy } from "../../src/lifecycle/operate.ts"; import { labIsUsable, destroyAll, assertUniversalInvariants } from "./harness.ts"; const capability = await labIsUsable(); const skip = capability.usable ? false : `lab not usable: ${capability.why}`; /** Grows one step at a time. Each addition is a boot, and a shape not covered before. */ const SCENARIOS = [ "bootstrap-single", // one machine, one public network — the floor ]; const raised: string[] = []; after(async () => { for (const instanceId of raised) await destroy(instanceId); }, { timeout: 600_000 }); for (const name of SCENARIOS) { test(`${name}: comes up holding what it declared, with no address held twice`, { skip, timeout: 900_000 }, async () => { const scenario = loadScenario(`scenarios/${name}.yml`); const instance = await raise(scenario, {}); raised.push(instance.instanceId); await assertUniversalInvariants(scenario, instance.instanceId); }); } after(async () => { // Anything a failed raise left standing. RaiseError leaves wreckage on purpose, which is // right for a person debugging and wrong for the next run of the suite. for (const name of SCENARIOS) await destroyAll(`${name}-`); }, { timeout: 600_000 });