0hmX/am3352-ddr-track-a-local-dfm-wip-20261007
Experimental RJ45-corrected board with isolated PG indication. 1005/1005 source joins pass; 15 expanded-guard physical errors, sourcing and qualification gates remain. Not fabrication-ready.
- Version
- 0.0.14
- License
- unset
- Stars
- 0
simulation/coverage.test.ts
import { test, expect } from "bun:test"
import { readFile } from "node:fs/promises"
import { buildCoverage, exportContext, electricalMembership, diskInsidePour, requireQualifiedCoverage, nativeId } from "./context-coverage"
const record = (type: string, id: string, fields: Record<string, unknown> = {}) => ({ type, [`${type}_id`]: id, ...fields })
test("native via ports inherit their explicit net without merging conflicting named nets", () => {
const records = [record("source_net", "g", { name: "GND" }), record("source_net", "s", { name: "SIG" }), record("source_port", "p1"), record("source_port", "p2"),
record("pcb_port", "pp1", { source_port_id: "p1", x: 0, y: 0, layers: ["top"] }), record("pcb_port", "pp2", { source_port_id: "p2", x: 0, y: 0, layers: ["inner1"] }),
record("pcb_via", "v", { source_net_id: "g", x: 0, y: 0, layers: ["top", "inner1"], pcb_port_ids: ["pp1", "pp2"] })]
expect(electricalMembership(records).membership(records.at(-1)!).sourceNetNames).toEqual(["GND"])
expect(electricalMembership(records).membership(records.at(-1)!).status).toBe("resolved_logical_component")
records.push(record("source_trace", "t", { connected_source_port_ids: ["p2"], connected_source_net_ids: ["s"] }))
expect(electricalMembership(records).membership(records.at(-2)!).status).toBe("conflicting_logical_components")
})
test("coincident unassociated copper is not assigned to a nearby net", () => {
const records = [record("source_net", "g", { name: "GND" }), record("pcb_via", "v", { x: 0, y: 0, layers: ["top", "inner1"] })]
expect(electricalMembership(records).membership(records[1]).status).toBe("no_electrical_association")
})
test("reference contact requires copper clearance and respects a cutout", () => {
const ring = (points: number[][]) => ({ vertices: points.map(([x, y]) => ({ x, y })) })
const pour = record("pcb_copper_pour", "p", { shape: "brep", brep_shape: { outer_ring: ring([[0, 0], [10, 0], [10, 10], [0, 10]]), inner_rings: [ring([[4, 4], [6, 4], [6, 6], [4, 6]])] } })
expect(diskInsidePour([2, 2], .1, pour).contained).toBe(true)
expect(diskInsidePour([5, 5], .1, pour).contained).toBe(false)
expect(diskInsidePour([3.95, 5], .1, pour).contained).toBe(false)
})
test("lossless inventory verifies hashes and the board gate cannot be promoted by editing metadata", () => {
const records = [record("pcb_board", "board", { thickness: 1.2 }), record("pcb_stackup", "stack", { layers: [{ thickness: .035 }] }), record("pcb_smtpad", "pad", { x: 0, y: 0, layer: "top", shape: "circle", radius: .2 })]
const coverage = buildCoverage(records, .025), exported = exportContext(records, coverage)
expect(exported.objects).toEqual([records[2]])
const changed = structuredClone(records); changed[2].x = .01
expect(() => exportContext(changed, coverage)).toThrow("hash mismatch")
expect(() => exportContext(records, { ...coverage, objects: [] })).toThrow("coverage incomplete")
expect(() => requireQualifiedCoverage({ status: "solver_context_qualified", objects: [{ plannedPhysicalConductor: "fake" }] })).toThrow("not qualified")
})
if (process.env.SIM_CIRCUIT_JSON) test("public historical integration preserves all 2057 objects and cutouts", async () => {
const records = JSON.parse(await readFile(process.env.SIM_CIRCUIT_JSON!, "utf8")), before = JSON.stringify(records)
const coverage = buildCoverage(records, .025), exported = exportContext(records, coverage)
expect(coverage.summary.counts).toEqual({ pcb_trace: 57, pcb_via: 520, pcb_copper_pour: 4, pcb_smtpad: 1454, pcb_plated_hole: 22 })
expect(exported.objects.length).toBe(2057)
expect(coverage.boundaries.filter(b => b.type === "copper_void")).toHaveLength(314)
for (const object of exported.objects) expect(JSON.stringify(object)).toBe(JSON.stringify(records.find((r: any) => r.type === object.type && nativeId(r) === nativeId(object))))
expect(JSON.stringify(records)).toBe(before)
expect(() => requireQualifiedCoverage(coverage)).toThrow("not qualified")
})