95 lines
5.8 KiB
Python
95 lines
5.8 KiB
Python
"""Settings reach the processor atomically and preserve the saved frequency band."""
|
|
|
|
from copy import deepcopy
|
|
import unittest
|
|
from unittest import mock
|
|
|
|
from PyQt6.QtWidgets import QApplication, QComboBox, QDoubleSpinBox, QStackedWidget
|
|
|
|
from python_app.gui.antenna_geometry_editor import AntennaGeometryEditor
|
|
from python_app.gui.controllers.sections.processing_section import build_processing_group
|
|
from python_app.models.gui_profile_schema import GuiStateModel
|
|
from python_app.models.dataset_model import SweepCollection
|
|
from python_app.models.run_config_schema import RunConfigModel
|
|
from python_app.tests.gui_test_support import isolated_window, widget
|
|
|
|
|
|
class LiveSettingsRegressionTest(unittest.TestCase):
|
|
@classmethod
|
|
def setUpClass(cls) -> None:
|
|
cls.app = QApplication.instance() or QApplication([])
|
|
|
|
def test_initial_processing_band_uses_sweep_limits_before_profile_values(self) -> None:
|
|
config, gui = RunConfigModel(), GuiStateModel()
|
|
config.radar.sweep.start_hz, config.radar.sweep.stop_hz = 1e6, 9.5e9
|
|
for settings in (gui.processing.bscan, gui.processing.gpr,
|
|
gui.processing.legacy_gpr, gui.processing.sar3d):
|
|
settings.start_freq_mhz, settings.stop_freq_mhz = 20, 9200
|
|
section = build_processing_group(config, gui)
|
|
self.addCleanup(section.group.deleteLater)
|
|
for mode in ("bscan", "gpr", "legacy_gpr", "sar3d"):
|
|
for bound, expected in (("start", 20), ("stop", 9200)):
|
|
with self.subTest(mode=mode, bound=bound):
|
|
editor = widget(section, f"_{mode}_{bound}_freq_mhz", QDoubleSpinBox)
|
|
self.assertEqual((editor.minimum(), editor.maximum(), editor.value()), (1, 9500, expected))
|
|
|
|
def test_failed_live_write_restores_web_batch_and_desktop_changes(self) -> None:
|
|
window = isolated_window(self.addCleanup)
|
|
window._pipeline.timer.stop()
|
|
mode = window._view.processing.mode
|
|
gain = widget(window._view.processing, "_bscan_gain", QDoubleSpinBox)
|
|
pages = window._view.processing.pages
|
|
live = window._live
|
|
before = (window._profile.build_gui_state(), window._config.geometry(),
|
|
live.active_mode, pages.currentIndex(), window._plots.stack.currentWidget(),
|
|
live.revision, deepcopy(live.processing_settings), window._plots.required_revision,
|
|
live.writer.path.read_bytes())
|
|
for source in ("web", "web_geometry", "desktop_mode", "desktop_value", "desktop_geometry"):
|
|
with self.subTest(source=source), \
|
|
mock.patch.object(live.writer, "write", side_effect=OSError("disk full")), \
|
|
mock.patch.object(window._preprocess, "invalidate_object_calibration_after_geometry_change") as invalidate, \
|
|
mock.patch.object(window._log, "show_exception") as error:
|
|
if source == "web":
|
|
live.apply_web({"processor_mode": "bscan", "bscan_gain": gain.value() + .1})
|
|
elif source in {"web_geometry", "desktop_geometry"}:
|
|
editor = window._view.processing.geometries[0]
|
|
records = editor.records()
|
|
records[0]["x_m"] += .125
|
|
if source == "web_geometry":
|
|
live.apply_web({"tx_geometry": records})
|
|
else:
|
|
editor.set_records(records)
|
|
elif source == "desktop_mode":
|
|
mode.setCurrentText("bscan")
|
|
else:
|
|
widget(window._view.processing, "_gpr_range_comp_power", QDoubleSpinBox).setValue(.4)
|
|
error.assert_called_once()
|
|
invalidate.assert_not_called()
|
|
self.assertEqual((window._profile.build_gui_state(), window._config.geometry(),
|
|
live.active_mode, pages.currentIndex(), window._plots.stack.currentWidget(),
|
|
live.revision, live.processing_settings, window._plots.required_revision,
|
|
live.writer.path.read_bytes()), before)
|
|
with mock.patch.object(window._plots, "draw_bscan", side_effect=ValueError("invalid plot")), \
|
|
mock.patch.object(window._log, "show_exception") as error:
|
|
live.apply_web({"processor_mode": "bscan", "bscan_gain": gain.value() + .1})
|
|
error.assert_called_once()
|
|
self.assertEqual((mode.currentText(), live.active_mode, pages.currentIndex()), ("bscan", "bscan", 1))
|
|
self.assertEqual(live.processing_settings[live.revision]["processor_mode"], "bscan")
|
|
self.assertNotEqual(live.writer.path.read_bytes(), before[-1])
|
|
|
|
def test_mode_publication_selects_replay_from_new_mode_before_changing_the_plot(self) -> None:
|
|
window = isolated_window(self.addCleanup)
|
|
window._pipeline.timer.stop()
|
|
window._history.preprocessed.append(SweepCollection(1, 1, [], capture_start_ns=1, capture_end_ns=2))
|
|
with mock.patch.object(window._pipeline.supervisor, "is_processor_running", return_value=True), \
|
|
mock.patch.object(window._pipeline, "_result_reader"), \
|
|
mock.patch.object(window._pipeline, "drain_results", return_value=None), \
|
|
mock.patch.object(window._pipeline, "schedule_replay"), \
|
|
mock.patch.object(window._plots, "draw_bscan"):
|
|
for mode, reprocess in (("bscan", False), ("pass_through", True)):
|
|
with self.subTest(mode=mode):
|
|
window._live.apply_web({"processor_mode": mode})
|
|
published = window._live.processing_settings[window._live.revision]
|
|
self.assertEqual(published["processor_mode"], mode)
|
|
self.assertEqual(published["reprocess_current_result"], reprocess)
|