"""Unit-to-millimetre conversion. The reference program carries the bench measurement in a comment:: # 轴0(X)/轴1(Y) 实测: UNITS=10 时 1000用户单位 = 2mm → 每毫米 5000 脉冲 # 当量5 → 1000单位=1mm,不是100单位=1mm These are the assertions that keep that comment honest. """ from __future__ import annotations import math import pytest from orisys_autocal.motion.units import ( PULSES_PER_MM, mm_to_user_units, safe_float, user_units_to_mm, ) @pytest.mark.parametrize( ("units", "user_units", "expected_mm"), [ (10.0, 1000.0, 2.0), # the measured case from the vendor comment (5.0, 1000.0, 1.0), # ...and the second one (10.0, 0.0, 0.0), (10.0, 5000.0, 10.0), (10.0, -1000.0, -2.0), # negative travel must stay negative ], ) def test_conversion_matches_the_bench_measurement(units, user_units, expected_mm): assert user_units_to_mm(user_units, units=units) == pytest.approx(expected_mm) def test_default_units_is_the_platform_value(): assert user_units_to_mm(1000.0) == pytest.approx(2.0) assert PULSES_PER_MM == 5000.0 def test_conversion_round_trips(): for units in (1.0, 5.0, 10.0, 37.5): millimetres = user_units_to_mm(1234.5, units=units) assert mm_to_user_units(millimetres, units=units) == pytest.approx(1234.5) def test_a_zero_or_negative_scale_is_not_a_number(): """A bad constant must be visibly unusable, not a plausible number.""" assert math.isnan(user_units_to_mm(1000.0, pulses_per_mm=0.0)) assert math.isnan(user_units_to_mm(1000.0, pulses_per_mm=-1.0)) assert math.isnan(mm_to_user_units(1.0, units=0.0)) @pytest.mark.parametrize( "text", ["", " ", "abc", "1,5", None, "nan", "inf", "-inf"], ) def test_unusable_entries_fall_back(text): assert safe_float(text, 42.0) == 42.0 @pytest.mark.parametrize("text", ["0", "0.0", " 0 "]) def test_zero_falls_back_because_it_would_divide(text): """A pulse equivalent of zero must never reach the controller.""" assert safe_float(text, 7.0) == 7.0 @pytest.mark.parametrize(("text", "expected"), [("5", 5.0), (" 2.5 ", 2.5), ("-3", -3.0)]) def test_usable_entries_are_parsed(text, expected): assert safe_float(text, 42.0) == expected