inire/docs/plans/testing_plan.md

8.4 KiB

Testing Plan (Refined)

This document defines the comprehensive testing strategy for the inire auto-router, ensuring analytic correctness and performance.

1. Unit Tests: Geometry & Components (inire/geometry)

1.1. Primitives (primitives.py)

  • Port Snapping: Verify that Port(x, y, orientation) snaps x and y to the nearest 1nm grid point.
  • Coordinate Transforms:
    • Translate a port by (dx, dy).
    • Rotate a port by 90, 180, 270 degrees around an origin.
    • Verify orientation wrapping (e.g., 270^\circ + 90^\circ \to 0^\circ).
  • Polygon Creation:
    • Generate a polygon from a list of points.
    • Verify bounding box calculation.
  • Property-Based Testing (Hypothesis):
    • Verify that any Port after transformation remains snapped to the 1nm grid.
    • Verify that Rotate(Rotate(Port, 90), -90) returns the original Port (up to snapping).

1.2. Component Generation (components.py)

  • Straight Moves:
    • Generate a Straight(length=10.0, width=2.0) segment.
    • Verify the end port is exactly length away in the correct orientation.
    • Verify the resulting polygon's dimensions.
    • Edge Case: L < 1\mu m (below search grid). Verify it still generates a valid 1nm segment.
  • Bend90:
    • Generate a Bend90(radius=10.0, width=2.0, direction='CW').
    • Verify the end port's orientation is changed by -90^\circ.
    • Verify the end port's position is exactly (R, -R) relative to the start (for 0^\circ \to 270^\circ).
    • Grid Snapping: Verify that if the bend radius results in a non-1µm aligned port, it is snapped to the nearest 1µm search grid point (with a warning).
  • SBend (Small Offset O < 2R):
    • Generate an SBend(offset=5.0, radius=10.0, width=2.0).
    • Verify the total length matches the analytical L = 2\sqrt{O(2R - O/4)} (or equivalent arc-based formula).
    • Verify the tangent continuity at the junction of the two arcs.
    • Edge Case: O = 2R. Verify it either generates two 90-degree bends or fails gracefully with a clear error.
    • Verify it fails/warns if O > 2R.

1.3. Geometric Fidelity

  • Arc Resolution (Sagitta):
    • Verify that Bend90 and SBend polygons are approximated by segments such that the maximum deviation (sagitta) is within a user-defined tolerance (e.g., 10nm).
    • Test with varying radii to ensure segment count scales appropriately.

2. Unit Tests: Collision & Cost (inire/geometry/collision & router/cost)

2.1. Collision Engine

  • Pre-dilation Logic:
    • Verify that an obstacle (polygon) is correctly dilated by (W_{max} + C)/2.
    • Heterogeneous Widths: Verify that a path for Net A (width W_1) is dilated by (W_1 + C)/2, while Net B (width W_2) uses (W_2 + C)/2.
  • Locked Paths:
    • Insert an existing path geometry into the "Static Obstacle" R-Tree.
    • Verify that the router treats it as an unmovable obstacle and avoids it.
  • R-Tree Queries:
    • Test intersection detection between two overlapping polygons.
    • Test non-intersection between adjacent but non-overlapping polygons (exactly C distance apart).
  • Safety Zone (2nm):
    • Create a port exactly on the edge of an obstacle.
    • Verify that a "Move" starting from this port is NOT flagged for collision if the intersection occurs within 2nm of the port.
  • Self-Intersection:
    • Verify that a path consisting of multiple segments is flagged if it loops back on itself.

2.2. Danger Map & Cost Evaluator

  • Danger Map Generation:
    • Initialize a map for a 100\mu m \times 100\mu m area with a single obstacle.
    • Verify the cost g_{proximity} matches k/d^2 for cells near the obstacle.
    • Verify cost is 0 for cells beyond the Safety Threshold.
  • Memory Check:
    • Mock a 20mm \times 20mm grid and verify memory allocation stays within limits (e.g., < 2GB for standard uint8 resolution).
  • Cost Calculation:
    • Verify total cost f(n) correctly sums length, bend penalties (10 \times Manhattan), and proximity costs.

2.3. Robustness & Limits

  • Design Bounds:
    • Test routing at the extreme edges of the 20mm \times 20mm coordinate space.
    • Verify that moves extending outside the design bounds are correctly pruned or flagged.
  • Empty/Invalid Inputs:
    • Test with an empty netlist.
    • Test with start and end ports at the exact same location.

3. Integration Tests: Single-Net A* Search (inire/router/astar)

3.1. Open Space Scenarios

  • Straight Line: Route from (0,0,0) to (100,0,0). Verify it uses only Straight moves.
  • Simple Turn: Route from (0,0,0) to (20,20,90). Verify it uses a Bend90 and Straight segments.
  • Small S-Bend: Route with an offset of 5\mu m and radius 10\mu m. Verify it uses the SBend component.
  • Large S-Bend (O \ge 2R): Route with an offset of 50\mu m and radius 10\mu m. Verify it combines two Bend90s and a Straight segment.

3.2. Obstacle Avoidance (The "Maze" Tests)

  • L-Obstacle: Place an obstacle blocking the direct path. Verify the router goes around it.
  • Narrow Channel: Create two obstacles with a gap slightly wider than W_i + C. Verify the router passes through.
  • Dead End: Create a U-shaped obstacle. Verify the search explores alternatives and fails gracefully if no path exists.

3.3. Snapping & Precision

  • Snap-to-Target Lookahead:
    • Route to a target at (100.005, 0, 0) (not on 1µm grid).
    • Verify the search reaches the vicinity via the 1µm grid and the final segment bridges the 5nm gap exactly.
  • Grid Alignment:
    • Start from a port at (0.5, 0.5, 0). Verify it snaps to the 1µm search grid correctly for the first move expansion.

3.4. Failure Modes

  • Unreachable Target: Create a target completely enclosed by obstacles. Verify the search terminates after exploring all options (or hitting the 50,000 node limit) and returns an invalid result.
  • Start/End Collision: Place a port deep inside an obstacle (beyond the 2nm safety zone). Verify the router identifies the immediate collision and fails gracefully.

4. Integration Tests: Multi-Net PathFinder (inire/router/pathfinder)

4.1. Congestion Scenarios

  • Parallel Paths: Route two nets that can both take straight paths. Verify no reroutes occur.
  • The "Cross" Test: Two nets must cross paths in 2D.
    • Since crossings are illegal, verify the second net finds a detour.
    • Verify the Negotiated Congestion loop increases the cost of the shared region.
  • Bottleneck: Force 3 nets through a channel that only fits 2.
    • Verify the router returns 2 valid paths and 1 "least bad" path (with collisions flagged).
    • Verify the is_valid=False attribute is set for the failing net.

4.2. Determinism & Performance

  • Seed Consistency: Run the same multi-net problem twice with the same seed; verify identical results (pixel-perfect).
  • Node Limit Enforcement: Trigger a complex search that exceeds 50,000 nodes. Verify it terminates and returns the best-so-far or failure.
  • Timeout: Verify the session-level timeout stops the process for extremely large problems.

5. Benchmarking & Regression

  • Standard Benchmark Suite: A set of 5-10 layouts with varying net counts (1 to 50).
  • Metrics to Track:
    • Total wire length.
    • Total number of bends.
    • Execution time per net.
    • Success rate (percentage of nets routed without collisions).
    • Node Expansion Rate: Nodes per second.
    • Memory Usage: Peak RSS during 20x20mm routing.
  • Fuzz Testing:
    • Generate random obstacles and ports within a 1mm x 1mm area.
    • Verify that the router never crashes.
    • Verify that every result marked is_valid=True is confirmed collision-free by a high-precision (slow) check.

6. Analytic Correctness Guarantees

  • Post-Route Validation:
    • Implement an independent validate_path(path, obstacles, clearance) function using shapely's most precise intersection tests.
    • Run this on every test result to ensure the CollisionEngine (which uses R-Tree for speed) hasn't missed any edge cases.
  • Orientation Check:
    • Verify that the final port of every path matches the target orientation exactly \{0, 90, 180, 270\}.