import { test } from "node:test"; import assert from "node:assert/strict"; import { parseScenario } from "../src/declaration/parse.ts"; import { planRouters, ttlSeconds } from "../src/lifecycle/router.ts"; test("segments sharing a gateway declaration share ONE router", () => { // That is what a VLAN-capable router is, and two routers sharing an external address // would not work anyway. const scenario = parseScenario(`scenario: x segments: pub: { kind: public, cidr: [192.0.2.0/24] } home: { kind: private, cidr: [192.168.1.0/24], gateway: { to: pub, address: [192.0.2.5], nat: [v4] } } iot: { kind: private, cidr: [192.168.30.0/24], gateway: { to: pub, address: [192.0.2.5], nat: [v4] } } machines: { a: { at: { segment: home, address: [192.168.1.9] } } }`); const plans = planRouters(scenario, "inst"); assert.equal(plans.length, 1, "one gateway declaration, one router"); assert.deepEqual(plans[0]?.inside.sort(), ["home", "iot"]); }); test("different external addresses mean different routers", () => { const scenario = parseScenario(`scenario: x segments: pub: { kind: public, cidr: [192.0.2.0/24] } home: { kind: private, cidr: [192.168.1.0/24], gateway: { to: pub, address: [192.0.2.5], nat: [v4] } } other: { kind: private, cidr: [192.168.30.0/24], gateway: { to: pub, address: [192.0.2.6], nat: [v4] } } machines: { a: { at: { segment: home, address: [192.168.1.9] } } }`); assert.equal(planRouters(scenario, "inst").length, 2); }); test("a scenario with no gateways needs no routers", () => { const scenario = parseScenario(`scenario: x segments: { net: { kind: public, cidr: [192.0.2.0/24] } } machines: { a: { at: { segment: net, address: [192.0.2.1] } } }`); assert.equal(planRouters(scenario, "inst").length, 0); }); test("forwardable and nat carry through to the plan", () => { const scenario = parseScenario(`scenario: x segments: pub: { kind: public, cidr: [192.0.2.0/24] } cafe: { kind: private, cidr: [10.50.0.0/16], gateway: { to: pub, address: [192.0.2.9], nat: [v4], forwardable: false, mapping_ttl: 30s } } machines: { a: { at: { segment: cafe, address: [10.50.0.9] } } }`); const plan = planRouters(scenario, "inst")[0]; assert.equal(plan?.forwardable, false); assert.deepEqual(plan?.nat, ["v4"]); assert.equal(plan?.mappingTtl, "30s"); }); test("mapping ttl parses the forms a declaration uses", () => { assert.equal(ttlSeconds("30s"), 30); assert.equal(ttlSeconds("120s"), 120); assert.equal(ttlSeconds("2m"), 120); assert.equal(ttlSeconds("1h"), 3600); assert.equal(ttlSeconds("90"), 90); assert.equal(ttlSeconds(undefined), undefined); assert.equal(ttlSeconds("soon"), undefined); });