import assert from "node:assert/strict"; import { spawn } from "node:child_process"; import { once } from "node:events"; import { mkdtemp, rm } from "node:fs/promises"; import { createServer } from "node:net"; import { tmpdir } from "node:os"; import { join } from "node:path"; const root = await mkdtemp(join(tmpdir(), "nodedc-map-gateway-zone-source-smoke-")); const port = await freePort(); let child; try { child = spawn(process.execPath, ["src/server.mjs"], { cwd: new URL("..", import.meta.url), env: { ...process.env, PORT: String(port), MAP_CACHE_DIR: join(root, "cache"), MAP_GATEWAY_ALLOW_ANONYMOUS: "true", MAP_CACHE_MODE: "readwrite", CESIUM_ION_TOKEN: "", }, stdio: ["ignore", "pipe", "pipe"], }); await waitForGateway(port, child); const route = `http://127.0.0.1:${port}/internal/zone-sources/v1/profiles/moscow-pmd-slow-zones/current`; const response = await fetch(route); assert.equal(response.status, 200); assert.match(response.headers.get("etag") || "", /^"sha256:[a-f0-9]{64}"$/); const generation = await response.json(); assert.equal(generation.schemaVersion, "nodedc.zone-source-generation/v2"); assert.equal(generation.authorityId, "moscow-department-of-transport"); assert.equal(generation.datasetId, "pmd-slow-zones"); assert.equal(generation.complete, true); assert.equal(generation.zones.length, 903); assert.equal(generation.metadata.scheduleRowCount, 6335); const head = await fetch(route, { method: "HEAD" }); assert.equal(head.status, 200); assert.equal(await head.text(), ""); const cached = await fetch(route, { headers: { "If-None-Match": response.headers.get("etag") } }); assert.equal(cached.status, 304); console.log("ok: immutable Department zone source is served with stable digest and cache semantics"); } finally { if (child && !child.killed) { child.kill("SIGTERM"); await once(child, "exit").catch(() => undefined); } await rm(root, { recursive: true, force: true }); } async function freePort() { const server = createServer(); server.listen(0, "127.0.0.1"); await once(server, "listening"); const address = server.address(); assert(address && typeof address === "object"); const selected = address.port; server.close(); await once(server, "close"); return selected; } async function waitForGateway(selectedPort, processHandle) { let output = ""; processHandle.stderr.on("data", (chunk) => { output += String(chunk); }); for (let attempt = 0; attempt < 80; attempt += 1) { if (processHandle.exitCode !== null) throw new Error(`gateway_exited:${processHandle.exitCode}:${output}`); try { const response = await fetch(`http://127.0.0.1:${selectedPort}/healthz`); if (response.ok) return; } catch { /* service is still starting */ } await new Promise((resolve) => setTimeout(resolve, 50)); } throw new Error(`gateway_start_timeout:${output}`); }