"""Tests for the filter engine.""" from spice2wireviz.filter import FilterConfig, apply_filters, filter_component, filter_instance, filter_net from spice2wireviz.parser.models import ( ParsedNetlist, SpiceComponent, SpicePin, SubcircuitInstance, ) def _make_netlist(**kwargs) -> ParsedNetlist: defaults = { "subcircuit_defs": {}, "instances": [], "top_level_components": [], "all_nets": set(), "global_nets": set(), } defaults.update(kwargs) return ParsedNetlist(**defaults) def _make_component(ref: str, prefix: str, nodes: list[str] | None = None) -> SpiceComponent: nodes = nodes or [] return SpiceComponent( reference=ref, prefix=prefix, nodes=nodes, pins=[SpicePin(name=n, index=i + 1, net_name=n) for i, n in enumerate(nodes)], ) def _make_instance(ref: str, subckt: str, port_to_net: dict[str, str]) -> SubcircuitInstance: return SubcircuitInstance(reference=ref, subcircuit_name=subckt, port_to_net=port_to_net) class TestComponentFilter: def test_default_includes_boundary(self): config = FilterConfig() netlist = _make_netlist() assert filter_component(_make_component("J1", "J"), config, netlist) assert filter_component(_make_component("TP1", "TP"), config, netlist) assert filter_component(_make_component("P1", "P"), config, netlist) def test_exclude_prefix(self): config = FilterConfig(exclude_prefixes=["TP"]) netlist = _make_netlist() assert filter_component(_make_component("J1", "J"), config, netlist) assert not filter_component(_make_component("TP1", "TP"), config, netlist) def test_include_prefix_restricts(self): config = FilterConfig(include_prefixes=["J"]) netlist = _make_netlist() assert filter_component(_make_component("J1", "J"), config, netlist) assert not filter_component(_make_component("TP1", "TP"), config, netlist) def test_exclude_ref(self): config = FilterConfig(exclude_refs=["J2"]) netlist = _make_netlist() assert filter_component(_make_component("J1", "J"), config, netlist) assert not filter_component(_make_component("J2", "J"), config, netlist) def test_include_ref(self): config = FilterConfig(include_refs=["J1"]) netlist = _make_netlist() assert filter_component(_make_component("J1", "J"), config, netlist) assert not filter_component(_make_component("J2", "J"), config, netlist) class TestInstanceFilter: def test_default_includes_x(self): config = FilterConfig() netlist = _make_netlist() inst = _make_instance("X1", "amp", {"VIN": "NET1"}) assert filter_instance(inst, config, netlist) def test_exclude_subcircuit(self): config = FilterConfig(exclude_subcircuits=["power_supply"]) netlist = _make_netlist() assert not filter_instance( _make_instance("X1", "power_supply", {}), config, netlist ) assert filter_instance( _make_instance("X2", "amplifier", {}), config, netlist ) def test_include_subcircuit(self): config = FilterConfig(include_subcircuits=["amplifier"]) netlist = _make_netlist() assert filter_instance( _make_instance("X2", "amplifier", {}), config, netlist ) assert not filter_instance( _make_instance("X1", "power_supply", {}), config, netlist ) def test_exclude_ref(self): config = FilterConfig(exclude_refs=["X3"]) netlist = _make_netlist() assert not filter_instance( _make_instance("X3", "io_board", {}), config, netlist ) class TestNetFilter: def test_default_shows_all(self): config = FilterConfig() netlist = _make_netlist() assert filter_net("VCC", config, netlist) assert filter_net("GND", config, netlist) assert filter_net("SIGNAL", config, netlist) def test_hide_ground(self): config = FilterConfig(show_ground=False) netlist = _make_netlist() assert not filter_net("GND", config, netlist) assert not filter_net("AGND", config, netlist) assert filter_net("VCC", config, netlist) def test_hide_power(self): config = FilterConfig(show_power=False) netlist = _make_netlist() assert not filter_net("VCC", config, netlist) assert not filter_net("VDD", config, netlist) assert filter_net("GND", config, netlist) def test_include_nets_glob(self): config = FilterConfig(include_nets=["SIG_*"]) netlist = _make_netlist() assert filter_net("SIG_IN", config, netlist) assert filter_net("SIG_OUT", config, netlist) assert not filter_net("VCC", config, netlist) def test_exclude_nets_glob(self): config = FilterConfig(exclude_nets=["N0*"]) netlist = _make_netlist() assert not filter_net("N001", config, netlist) assert filter_net("SIGNAL", config, netlist) class TestApplyFilters: def test_filters_components(self): comps = [ _make_component("J1", "J", ["NET1"]), _make_component("TP1", "TP", ["NET2"]), _make_component("R1", "R", ["NET3"]), ] netlist = _make_netlist(top_level_components=comps) config = FilterConfig() # default: J, TP, P, X filtered = apply_filters(netlist, config) refs = [c.reference for c in filtered.top_level_components] assert "J1" in refs assert "TP1" in refs assert "R1" not in refs # R not in default include def test_filters_instances(self): insts = [ _make_instance("X1", "power", {"VCC": "NET1"}), _make_instance("X2", "amp", {"VIN": "NET2"}), ] netlist = _make_netlist(instances=insts) config = FilterConfig(exclude_refs=["X1"]) filtered = apply_filters(netlist, config) refs = [i.reference for i in filtered.instances] assert "X1" not in refs assert "X2" in refs