From 27cac4500784f154e8f68d64f2d9f2be9424fd37 Mon Sep 17 00:00:00 2001 From: ShiboSoftwareDev Date: Sun, 2 Aug 2026 13:40:31 +0200 Subject: [PATCH 1/2] test: reproduce same-net duplicate port overcount --- ...cate-congested-port-same-net-repro.test.ts | 35 +++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100644 tests/solver/duplicate-congested-port-same-net-repro.test.ts diff --git a/tests/solver/duplicate-congested-port-same-net-repro.test.ts b/tests/solver/duplicate-congested-port-same-net-repro.test.ts new file mode 100644 index 0000000..91f33dd --- /dev/null +++ b/tests/solver/duplicate-congested-port-same-net-repro.test.ts @@ -0,0 +1,35 @@ +import "bun-match-svg" +import { expect, test } from "bun:test" +import { getSvgFromGraphicsObject } from "graphics-debug" +import { + DuplicateCongestedPortSolver, + loadSerializedHyperGraph, + TinyHyperGraphSolver, +} from "lib/index" +import { sameNetSharedBottleneckFixture } from "tests/fixtures/same-net-shared-bottleneck.fixture" + +test("does not duplicate a bottleneck reused by routes on the same net", () => { + const solver = new DuplicateCongestedPortSolver( + sameNetSharedBottleneckFixture, + { + duplicatePortProximity: 0.4, + minimumDuplicatePortSpacing: 0.4, + duplicatePortWidth: 0.2, + }, + ) + solver.solve() + + const output = solver.getOutput() + const { topology, problem } = loadSerializedHyperGraph(output) + const visualizationSolver = new TinyHyperGraphSolver(topology, problem) + + expect( + getSvgFromGraphicsObject(visualizationSolver.visualize()), + ).toMatchSvgSnapshot(import.meta.path) + expect(solver.report.portUseCounts["shared-x"]).toBe(1) + expect( + solver.report.duplicatedPorts.find( + ({ sourcePortId }) => sourcePortId === "shared-x", + ), + ).toBeUndefined() +}) From 76cb1848fb7249fb5f528eeed79ba0de8e98ba75 Mon Sep 17 00:00:00 2001 From: ShiboSoftwareDev Date: Sun, 2 Aug 2026 13:45:39 +0200 Subject: [PATCH 2/2] test: collect same-net duplicate snapshot --- ...ate-congested-port-same-net-repro.snap.svg | 156 ++++++++++++++++++ ...cate-congested-port-same-net-repro.test.ts | 32 +++- 2 files changed, 186 insertions(+), 2 deletions(-) create mode 100644 tests/solver/__snapshots__/duplicate-congested-port-same-net-repro.snap.svg diff --git a/tests/solver/__snapshots__/duplicate-congested-port-same-net-repro.snap.svg b/tests/solver/__snapshots__/duplicate-congested-port-same-net-repro.snap.svg new file mode 100644 index 0000000..394af0b --- /dev/null +++ b/tests/solver/__snapshots__/duplicate-congested-port-same-net-repro.snap.svg @@ -0,0 +1,156 @@ +input: 1 shared bottleneck portprepass output: 2 bottleneck ports \ No newline at end of file diff --git a/tests/solver/duplicate-congested-port-same-net-repro.test.ts b/tests/solver/duplicate-congested-port-same-net-repro.test.ts index 91f33dd..f9c5f33 100644 --- a/tests/solver/duplicate-congested-port-same-net-repro.test.ts +++ b/tests/solver/duplicate-congested-port-same-net-repro.test.ts @@ -1,6 +1,9 @@ import "bun-match-svg" import { expect, test } from "bun:test" -import { getSvgFromGraphicsObject } from "graphics-debug" +import { + getSvgFromGraphicsObject, + stackGraphicsVertically, +} from "graphics-debug" import { DuplicateCongestedPortSolver, loadSerializedHyperGraph, @@ -20,11 +23,36 @@ test("does not duplicate a bottleneck reused by routes on the same net", () => { solver.solve() const output = solver.getOutput() + const input = loadSerializedHyperGraph(sameNetSharedBottleneckFixture) const { topology, problem } = loadSerializedHyperGraph(output) + const inputVisualizationSolver = new TinyHyperGraphSolver( + input.topology, + input.problem, + ) const visualizationSolver = new TinyHyperGraphSolver(topology, problem) + const bottleneckPortCount = output.ports.filter( + (port) => + port.portId === "shared-x" || + port.d?.duplicatedFromPortId === "shared-x", + ).length expect( - getSvgFromGraphicsObject(visualizationSolver.visualize()), + getSvgFromGraphicsObject( + stackGraphicsVertically( + [ + inputVisualizationSolver.visualize(), + visualizationSolver.visualize(), + ], + { + titles: [ + "input: 1 shared bottleneck port", + `prepass output: ${bottleneckPortCount} bottleneck port${ + bottleneckPortCount === 1 ? "" : "s" + }`, + ], + }, + ), + ), ).toMatchSvgSnapshot(import.meta.path) expect(solver.report.portUseCounts["shared-x"]).toBe(1) expect(