#!/usr/bin/env node "use strict"; const assert = require("assert"); const fs = require("fs"); const os = require("os"); const path = require("path"); const { zipSync } = require("fflate"); const { importNativeRoadPackage } = require("./lib/native-road-package"); const temp = fs.mkdtempSync(path.join(os.tmpdir(), "native-road-package-")); const area = { id: "fixture", nativeRoadPackage: "", outputs: { pipelineDir: path.join(temp, "pipeline") } }; const layers = ["road_surface", "connectors"]; const manifest = { contract: "native-road-package/v1.1", areaId: "fixture", layers: [ { source: "road_surface", role: "surface", materialLayer: "road_surface" }, { source: "connectors", role: "semantic" }, ] }; function validEntries() { return { "manifest.json": Buffer.from(JSON.stringify(manifest)), "compiled.json": Buffer.from("{}"), "diagnostics.json": Buffer.from("{}"), "comparison.json": Buffer.from("{}"), "traffic-signal-assemblies.json": Buffer.from("{}"), "traffic-signals.json": Buffer.from("{}"), ...Object.fromEntries(layers.map((layer) => [`layers/${layer}.geojson`, Buffer.from('{"type":"FeatureCollection","features":[]}')])), }; } function write(name, entries = validEntries()) { const file = path.join(temp, name); fs.writeFileSync(file, zipSync(entries)); area.nativeRoadPackage = file; return file; } write("valid.zip"); const first = importNativeRoadPackage(area); assert.equal(first.manifest.areaId, "fixture"); assert.equal(Object.keys(first.records).length, 8); assert.ok(first.rootDir.includes(first.zipRecord.sha256)); assert.equal(importNativeRoadPackage(area).rootDir, first.rootDir); assert.throws(() => { area.nativeRoadPackage = path.join(temp, "missing.zip"); importNativeRoadPackage(area); }, /ZIP not found/); write("corrupt.zip", { "manifest.json": Buffer.from("{") }); assert.throws(() => importNativeRoadPackage(area), /ZIP central directory|Invalid ZIP|Invalid native road manifest|Missing native road ZIP entry/); write("nested.zip", { "nested/manifest.json": Buffer.from("{}") }); assert.throws(() => importNativeRoadPackage(area), /root-flat/); write("traversal.zip", { "../manifest.json": Buffer.from("{}") }); assert.throws(() => importNativeRoadPackage(area), /Unsafe ZIP entry/); const wrongContract = validEntries(); wrongContract["manifest.json"] = Buffer.from(JSON.stringify({ ...manifest, contract: "v1" })); write("contract.zip", wrongContract); assert.throws(() => importNativeRoadPackage(area), /Unsupported native road contract/); const wrongArea = validEntries(); wrongArea["manifest.json"] = Buffer.from(JSON.stringify({ ...manifest, areaId: "other" })); write("area.zip", wrongArea); assert.throws(() => importNativeRoadPackage(area), /areaId mismatch/); const mismatch = validEntries(); delete mismatch["layers/connectors.geojson"]; write("mismatch.zip", mismatch); assert.throws(() => importNativeRoadPackage(area), /manifest\/source mismatch/); const symlink = write("symlink.zip"); const data = fs.readFileSync(symlink); const index = data.indexOf(Buffer.from([0x50, 0x4b, 0x01, 0x02])); data.writeUInt32LE((0xa000 << 16) >>> 0, index + 38); fs.writeFileSync(symlink, data); assert.throws(() => importNativeRoadPackage(area), /Symbolic links/); fs.rmSync(temp, { recursive: true, force: true }); console.log("Native road ZIP package tests passed.");