Initial project structure for spice2wireviz
SPICE netlist to WireViz YAML converter with: - Custom lightweight netlist parser (.net/.cir/.sp) - Single-module mapper (subcircuit external interface) - Inter-module mapper (multi-board wiring) - Filter engine with glob patterns - Click CLI with auto-detection, inspection commands - Optional .asc parser via spicelib - Comprehensive test suite with fixtures
This commit is contained in:
commit
e20a956f51
24 changed files with 2630 additions and 0 deletions
104
tests/test_single_module.py
Normal file
104
tests/test_single_module.py
Normal file
|
|
@ -0,0 +1,104 @@
|
|||
"""Tests for the single-module mapper."""
|
||||
|
||||
from pathlib import Path
|
||||
|
||||
import pytest
|
||||
|
||||
from spice2wireviz.filter import FilterConfig
|
||||
from spice2wireviz.mapper.single_module import map_single_module
|
||||
from spice2wireviz.parser.netlist import parse_netlist
|
||||
|
||||
FIXTURES = Path(__file__).parent / "fixtures"
|
||||
|
||||
|
||||
class TestSingleModuleMapping:
|
||||
def test_simple_board_connectors(self):
|
||||
netlist = parse_netlist(FIXTURES / "simple_board.net")
|
||||
result = map_single_module(netlist, "amplifier_board")
|
||||
|
||||
connectors = result["connectors"]
|
||||
assert "amplifier_board" in connectors # module header
|
||||
assert "J1" in connectors
|
||||
assert "J2" in connectors
|
||||
assert "TP1" in connectors
|
||||
|
||||
def test_module_header_pinlabels(self):
|
||||
netlist = parse_netlist(FIXTURES / "simple_board.net")
|
||||
result = map_single_module(netlist, "amplifier_board")
|
||||
|
||||
header = result["connectors"]["amplifier_board"]
|
||||
assert header["pinlabels"] == ["VIN", "GND", "VOUT", "SIGNAL_IN"]
|
||||
assert header["type"] == "Module Interface"
|
||||
|
||||
def test_connector_pinlabels(self):
|
||||
netlist = parse_netlist(FIXTURES / "simple_board.net")
|
||||
result = map_single_module(netlist, "amplifier_board")
|
||||
|
||||
j1 = result["connectors"]["J1"]
|
||||
assert j1["pinlabels"] == ["VIN", "GND"]
|
||||
|
||||
def test_test_point_style(self):
|
||||
netlist = parse_netlist(FIXTURES / "simple_board.net")
|
||||
result = map_single_module(netlist, "amplifier_board")
|
||||
|
||||
tp1 = result["connectors"]["TP1"]
|
||||
assert tp1.get("style") == "simple"
|
||||
|
||||
def test_cables_created(self):
|
||||
netlist = parse_netlist(FIXTURES / "simple_board.net")
|
||||
result = map_single_module(netlist, "amplifier_board")
|
||||
|
||||
cables = result["cables"]
|
||||
assert len(cables) >= 2 # At least cables for J1 and J2 connections
|
||||
|
||||
def test_connections_created(self):
|
||||
netlist = parse_netlist(FIXTURES / "simple_board.net")
|
||||
result = map_single_module(netlist, "amplifier_board")
|
||||
|
||||
connections = result["connections"]
|
||||
assert len(connections) >= 2
|
||||
|
||||
def test_traceability_notes(self):
|
||||
netlist = parse_netlist(FIXTURES / "simple_board.net")
|
||||
result = map_single_module(netlist, "amplifier_board")
|
||||
|
||||
header = result["connectors"]["amplifier_board"]
|
||||
assert "SPICE subcircuit" in header["notes"]
|
||||
|
||||
def test_nonexistent_subcircuit_raises(self):
|
||||
netlist = parse_netlist(FIXTURES / "simple_board.net")
|
||||
with pytest.raises(ValueError, match="not found"):
|
||||
map_single_module(netlist, "nonexistent")
|
||||
|
||||
def test_metadata_passthrough(self):
|
||||
netlist = parse_netlist(FIXTURES / "simple_board.net")
|
||||
meta = {"title": "Test Diagram", "author": "Test"}
|
||||
result = map_single_module(netlist, "amplifier_board", metadata=meta)
|
||||
assert result["metadata"]["title"] == "Test Diagram"
|
||||
|
||||
|
||||
class TestSingleModuleFiltering:
|
||||
def test_no_ground_filter(self):
|
||||
netlist = parse_netlist(FIXTURES / "simple_board.net")
|
||||
config = FilterConfig(show_ground=False)
|
||||
result = map_single_module(netlist, "amplifier_board", config)
|
||||
|
||||
header = result["connectors"]["amplifier_board"]
|
||||
assert "GND" not in header["pinlabels"]
|
||||
|
||||
def test_no_power_filter(self):
|
||||
"""When power is hidden, VIN should still appear as it's a port name, not a power net."""
|
||||
netlist = parse_netlist(FIXTURES / "simple_board.net")
|
||||
config = FilterConfig(show_power=False)
|
||||
result = map_single_module(netlist, "amplifier_board", config)
|
||||
|
||||
# VIN is a port name — it's not VCC/VDD so it stays
|
||||
header = result["connectors"]["amplifier_board"]
|
||||
assert "VIN" in header["pinlabels"]
|
||||
|
||||
def test_exclude_component_ref(self):
|
||||
netlist = parse_netlist(FIXTURES / "simple_board.net")
|
||||
config = FilterConfig(exclude_refs=["TP1"])
|
||||
result = map_single_module(netlist, "amplifier_board", config)
|
||||
|
||||
assert "TP1" not in result["connectors"]
|
||||
Loading…
Add table
Add a link
Reference in a new issue