"""Tests for the inter-module mapper.""" from pathlib import Path from spice2wireviz.filter import FilterConfig from spice2wireviz.mapper.inter_module import map_inter_module from spice2wireviz.parser.netlist import parse_netlist FIXTURES = Path(__file__).parent / "fixtures" class TestInterModuleMapping: def test_multi_board_connectors(self): netlist = parse_netlist(FIXTURES / "multi_board.net") result = map_inter_module(netlist) connectors = result["connectors"] # Should have connectors for each X instance and top-level components assert "X1" in connectors assert "X2" in connectors assert "X3" in connectors assert "J_CHASSIS" in connectors assert "TP_VCC" in connectors def test_instance_connector_type(self): netlist = parse_netlist(FIXTURES / "multi_board.net") result = map_inter_module(netlist) x1 = result["connectors"]["X1"] assert x1["type"] == "power_supply" def test_instance_pinlabels(self): netlist = parse_netlist(FIXTURES / "multi_board.net") result = map_inter_module(netlist) x2 = result["connectors"]["X2"] assert "VIN" in x2["pinlabels"] assert "GND" in x2["pinlabels"] assert "VOUT" in x2["pinlabels"] def test_cables_for_shared_nets(self): netlist = parse_netlist(FIXTURES / "multi_board.net") result = map_inter_module(netlist) # Should have cables connecting modules via shared nets cables = result["cables"] assert len(cables) >= 1 def test_connections_exist(self): netlist = parse_netlist(FIXTURES / "multi_board.net") result = map_inter_module(netlist) connections = result["connections"] assert len(connections) >= 1 def test_traceability_notes(self): netlist = parse_netlist(FIXTURES / "multi_board.net") result = map_inter_module(netlist) x1 = result["connectors"]["X1"] assert "SPICE instance" in x1["notes"] def test_top_level_test_point_style(self): netlist = parse_netlist(FIXTURES / "multi_board.net") result = map_inter_module(netlist) tp = result["connectors"]["TP_VCC"] assert tp.get("style") == "simple" class TestInterModuleFiltering: def test_exclude_instance(self): netlist = parse_netlist(FIXTURES / "multi_board.net") config = FilterConfig(exclude_refs=["X1"]) result = map_inter_module(netlist, config) assert "X1" not in result["connectors"] assert "X2" in result["connectors"] def test_exclude_subcircuit(self): netlist = parse_netlist(FIXTURES / "multi_board.net") config = FilterConfig(exclude_subcircuits=["power_supply"]) result = map_inter_module(netlist, config) assert "X1" not in result["connectors"] def test_no_ground_filter(self): netlist = parse_netlist(FIXTURES / "multi_board.net") config = FilterConfig(show_ground=False) result = map_inter_module(netlist, config) # GND should not appear in any connector's pinlabels for name, conn in result["connectors"].items(): if "pinlabels" in conn: assert "GND" not in conn["pinlabels"], f"GND found in {name}" def test_no_power_filter(self): netlist = parse_netlist(FIXTURES / "multi_board.net") config = FilterConfig(show_power=False) result = map_inter_module(netlist, config) for name, conn in result["connectors"].items(): if "pinlabels" in conn: assert "VCC" not in conn["pinlabels"], f"VCC found in {name}" class TestHierarchicalInterModule: def test_hierarchical_instances(self): netlist = parse_netlist(FIXTURES / "hierarchical.net") result = map_inter_module(netlist) connectors = result["connectors"] assert "X_REG" in connectors assert "X_SENSOR" in connectors assert "X_MAIN" in connectors def test_external_connectors(self): netlist = parse_netlist(FIXTURES / "hierarchical.net") result = map_inter_module(netlist) connectors = result["connectors"] assert "J_PWR" in connectors assert "J_USB" in connectors assert "TP_3V3" in connectors def test_grouped_parallel_wires(self): """Parallel wires between same modules should be grouped.""" netlist = parse_netlist(FIXTURES / "hierarchical.net") config = FilterConfig(group_parallel_wires=True) result = map_inter_module(netlist, config) # With grouping, fewer cables than total net connections cables = result["cables"] connections = result["connections"] assert len(cables) == len(connections) def test_ungrouped_wires(self): """Without grouping, each wire gets its own cable.""" netlist = parse_netlist(FIXTURES / "hierarchical.net") config = FilterConfig(group_parallel_wires=False) result = map_inter_module(netlist, config) # Each cable should have wirecount=1 for cable in result["cables"].values(): assert cable.get("wirecount", 1) == 1 or len(cable.get("colors", [])) == 1