# 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 `Bend90`s 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\}$.