import pytest from .registry import instances import sys import os sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), '..'))) from slic.utils.marker import * # Dummy class to simulate an adjustable device class DummyDevice: def __init__(self, name="Device", units="V", current=1.23): self.name = name self.units = units self.current = current self.set_calls = [] def get_current_value(self): return self.current def set_target_value(self, value, hold=False): self.set_calls.append((value, hold)) self.current = value return f"Set to {value}{self.units}, hold={hold}" # Test format_value() def test_format_value_with_units(): assert format_value(1.5, "V") == "1.5 V" def test_format_value_without_units(): assert format_value(1.5, None) == "1.5" # Marker class tests def test_marker_name_default(): device = DummyDevice() m = Marker(device, value=2.5) assert m.name == "Device at 2.5 V" def test_marker_name_custom(): device = DummyDevice() m = Marker(device, value=2.5, name="TestName") assert m.name == "TestName" def test_marker_repr_format(): device = DummyDevice(name="Volt", units="mV", current=1.0) m = Marker(device, value=2.5) out = repr(m) assert 'Marker "Volt at 2.5 mV"' in out assert "(currently at 1.0 mV)" in out def test_marker_update_changes_value(): device = DummyDevice(current=4.2) m = Marker(device, value=1.0) assert m.value == 1.0 m.update() assert m.value == 4.2 def test_marker_update_with_explicit_value(): device = DummyDevice() m = Marker(device, value=0.0) m.update(7.7) assert m.value == 7.7 def test_marker_goto_sets_value_and_returns_result(): device = DummyDevice(current=1.0) m = Marker(device, value=3.3) result = m.goto() assert result == "Set to 3.3V, hold=False" assert device.current == 3.3 assert device.set_calls[-1] == (3.3, False) def test_marker_call_is_alias_of_goto(): device = DummyDevice(current=1.0) m = Marker(device, value=3.3) result = m(hold=True) assert result == "Set to 3.3V, hold=True" assert device.set_calls[-1] == (3.3, True) # markers singleton registry # Clean singleton before test session @pytest.fixture(autouse=True) def clean_markers_registry(): # Ensures markers are reset before each test Marker._registry.clear() yield Marker._registry.clear() def test_markers_register_and_access(): d1 = DummyDevice(name="Dev1", current=1.0) d2 = DummyDevice(name="Dev2", current=2.0) m1 = Marker(d1, value=10) m2 = Marker(d2, value=20) all_markers = markers._get() assert isinstance(all_markers, dict) assert m1.name in all_markers assert m2.name in all_markers assert all_markers[m1.name] is m1 assert all_markers[m2.name] is m2 assert markers[m1.name] is m1 assert markers[m2.name] is m2 def test_markers_repr_contains_all(): d1 = DummyDevice(name="Dev1", current=1.0) d2 = DummyDevice(name="Dev2", current=2.0) m1 = Marker(d1, value=10) m2 = Marker(d2, value=20) repr_str = repr(markers) assert "Dev1 at 10 V" in repr_str assert "Dev2 at 20 V" in repr_str assert isinstance(repr_str, str) def test_markers_conflicting_names(): d = DummyDevice(name="DevX", current=5.0) m1 = Marker(d, value=50, name="conflict") m2 = Marker(d, value=60, name="conflict") # same name => overwrite all_markers = markers._get() assert "conflict" in all_markers assert all_markers["conflict"] is m2 # The last one wins def test_marker_registry_dict_is_printable_dict(): d = DummyDevice(name="DevP", current=7.0) m = Marker(d, value=70) ms = markers._get() assert isinstance(ms, dict) assert isinstance(repr(markers), str) assert isinstance(printable_dict(ms), str) def test_markers_getitem_invalid_key_raises(): with pytest.raises(KeyError): _ = markers["this marker does not exist"]