"""Tests for raw_parser module: run boundaries, variable lookup, run slicing.""" import numpy as np import pytest from mcp_ltspice.raw_parser import _detect_run_boundaries class TestDetectRunBoundaries: def test_single_run(self): """Monotonically increasing time -> single run starting at 0.""" x = np.linspace(0, 1e-3, 500) boundaries = _detect_run_boundaries(x) assert boundaries == [0] def test_multi_run(self): """Three runs: time resets to near-zero at each boundary.""" run1 = np.linspace(0, 1e-3, 100) run2 = np.linspace(0, 1e-3, 100) run3 = np.linspace(0, 1e-3, 100) x = np.concatenate([run1, run2, run3]) boundaries = _detect_run_boundaries(x) assert len(boundaries) == 3 assert boundaries[0] == 0 assert boundaries[1] == 100 assert boundaries[2] == 200 def test_complex_ac(self): """AC analysis with complex frequency axis that resets.""" run1 = np.logspace(0, 6, 50).astype(np.complex128) run2 = np.logspace(0, 6, 50).astype(np.complex128) x = np.concatenate([run1, run2]) boundaries = _detect_run_boundaries(x) assert len(boundaries) == 2 assert boundaries[0] == 0 assert boundaries[1] == 50 def test_single_point(self): """Single data point -> one run.""" boundaries = _detect_run_boundaries(np.array([0.0])) assert boundaries == [0] class TestRawFileGetVariable: def test_exact_match(self, mock_rawfile): """Exact name match returns correct data.""" result = mock_rawfile.get_variable("V(out)") assert result is not None assert len(result) == mock_rawfile.points def test_case_insensitive(self, mock_rawfile): """Variable lookup is case-insensitive (partial match).""" result = mock_rawfile.get_variable("v(out)") assert result is not None def test_partial_match(self, mock_rawfile): """Substring match should work: 'out' matches 'V(out)'.""" result = mock_rawfile.get_variable("out") assert result is not None def test_missing_variable(self, mock_rawfile): """Non-existent variable returns None.""" result = mock_rawfile.get_variable("V(nonexistent)") assert result is None def test_get_time(self, mock_rawfile): result = mock_rawfile.get_time() assert result is not None assert len(result) == mock_rawfile.points class TestRawFileRunData: def test_get_run_data_slicing(self, mock_rawfile_stepped): """Extracting a single run produces correct point count.""" run0 = mock_rawfile_stepped.get_run_data(0) assert run0.points == 100 assert run0.n_runs == 1 assert run0.is_stepped is False def test_get_run_data_values(self, mock_rawfile_stepped): """Each run has the expected amplitude scaling.""" for i in range(3): run = mock_rawfile_stepped.get_run_data(i) sig = run.get_variable("V(out)") # Peak amplitude should be approximately (i+1) assert float(np.max(np.abs(sig))) == pytest.approx(i + 1, rel=0.1) def test_is_stepped(self, mock_rawfile_stepped, mock_rawfile): assert mock_rawfile_stepped.is_stepped is True assert mock_rawfile.is_stepped is False def test_get_variable_with_run(self, mock_rawfile_stepped): """get_variable with run= parameter slices correctly.""" v_run1 = mock_rawfile_stepped.get_variable("V(out)", run=1) assert v_run1 is not None assert len(v_run1) == 100 def test_non_stepped_get_run_data(self, mock_rawfile): """Getting run data from non-stepped file returns self.""" run = mock_rawfile.get_run_data(0) assert run.points == mock_rawfile.points