This commit is contained in:
Ankle committed 2026-09-10 17:06:56 +08:00
1 parent 714a2e1db2
commit f7a782dcef
5 files changed
+584 -73

No files matched your search

+132
View File
@@ -1,11 +1,16 @@
from __future__ import annotations
import argparse
from contextlib import redirect_stderr
import io
import json
from pathlib import Path
import subprocess
import tempfile
import unittest
from unittest import mock
import interactive_calibrator as wizard
import scan_calibrator as core
@@ -107,5 +112,132 @@ class ApiRecoveryTests(unittest.TestCase):
self.assertEqual(move_mock.call_count, 2)
class InteractiveWizardTests(unittest.TestCase):
def test_manual_ptz_accepts_annotated_display_format(self):
self.assertEqual(
wizard.parse_ptz_input(
"pan=21720 (217.20°), tilt=1268 (12.68°), "
"zoom=4580 (45.80×)"
),
{"pan": 21720, "tilt": 1268, "zoom": 4580},
)
def test_manual_ptz_rejects_incomplete_input(self):
with self.assertRaisesRegex(ValueError, "pan=21720"):
wizard.parse_ptz_input("pan=21720, tilt=1268")
@mock.patch("interactive_calibrator.core.print_ptz")
@mock.patch("interactive_calibrator.camera_ptz")
@mock.patch("interactive_calibrator.read_zoom_after_move")
def test_unreachable_average_uses_nearest_higher_zoom(
self, move_mock, camera_mock, _print_mock
):
origin = {"pan": 23052, "tilt": 1298, "zoom": 4510}
camera_mock.return_value = origin
def quantized(_origin, requested):
return {
**origin,
"zoom": 4550 if requested <= 4565 else 4580,
}
move_mock.side_effect = quantized
actual, average = wizard.move_to_scan_zoom({
"top-left": {**origin, "zoom": 4550},
"bottom-right": {**origin, "zoom": 4580},
})
self.assertEqual(average, 4565)
self.assertEqual(actual["zoom"], 4580)
self.assertEqual(move_mock.call_args_list[0].args[1], 4565)
self.assertEqual(move_mock.call_args_list[-1].args[1], 4580)
@mock.patch("interactive_calibrator.core.print_ptz")
@mock.patch("interactive_calibrator.camera_ptz")
@mock.patch("interactive_calibrator.read_zoom_after_move")
def test_step_four_always_sends_zoom_even_when_already_equal(
self, move_mock, camera_mock, _print_mock
):
origin = {"pan": 100, "tilt": 200, "zoom": 4580}
camera_mock.return_value = origin
move_mock.return_value = origin
actual, _average = wizard.move_to_scan_zoom({
"top-left": origin,
"bottom-right": origin,
})
self.assertEqual(actual["zoom"], 4580)
move_mock.assert_called_once_with(origin, 4580)
def test_partial_session_is_saved_to_history(self):
with tempfile.TemporaryDirectory() as temporary:
root = Path(temporary)
history = root / "history"
state_file = root / "calibration.json"
with (
mock.patch.object(wizard, "HISTORY_DIR", history),
mock.patch.object(wizard, "ACTIVE_HISTORY_FILE", None),
mock.patch.object(core, "STATE_FILE", state_file),
):
state = wizard.start_history_session("hanging", None)
state["points"]["top-left"] = {
"pan": 21720,
"tilt": 1268,
"zoom": 4580,
}
wizard.save_working_state(state)
records = wizard.load_history_records()
self.assertEqual(len(records), 1)
self.assertTrue(
wizard.state_item_exists(records[0][1], "points", "top-left")
)
self.assertFalse(
wizard.state_item_exists(records[0][1], "points", "bottom-right")
)
class GenerateZoomTests(unittest.TestCase):
def test_generate_uses_camera_reachable_scan_zoom(self):
state = {
"points": {
"top-left": {"pan": 1000, "tilt": 200, "zoom": 4550},
"bottom-right": {"pan": 900, "tilt": 100, "zoom": 4580},
},
"steps": {
"pan": {
"value": 50,
"overlap": 0.04,
"target_overlap": 0.04,
"overlap_method": "axis_shift_v1_retargeted",
"inliers": 50,
"visual_direction": "decreasing",
},
"tilt": {
"value": 50,
"overlap": 0.04,
"target_overlap": 0.04,
"overlap_method": "axis_shift_v1_retargeted",
"inliers": 50,
},
},
"scan_zoom": 4580,
}
with tempfile.TemporaryDirectory() as temporary:
root = Path(temporary)
with (
mock.patch.object(core, "ROOT", root),
mock.patch.object(core, "load_state", return_value=state),
):
with mock.patch("sys.stdout", new=io.StringIO()):
core.command_generate(argparse.Namespace(mount="desktop"))
result = next((root / "result").glob("scan_config_*.json"))
generated = json.loads(result.read_text(encoding="utf-8"))
self.assertEqual(generated["scan"]["zoom"], 4580)
if __name__ == "__main__":
unittest.main()