Rework radar system
This commit is contained in:
@@ -0,0 +1,108 @@
|
||||
|
||||
from contextlib import ExitStack
|
||||
"""Plot capture follows client demand and actual Qt scene changes."""
|
||||
|
||||
from collections import deque
|
||||
import unittest
|
||||
from unittest import mock
|
||||
|
||||
import numpy as np
|
||||
from PyQt6.QtCore import QSignalBlocker
|
||||
from PyQt6.QtWidgets import QApplication, QComboBox
|
||||
|
||||
from python_app.tests.gui_test_support import isolated_window
|
||||
|
||||
|
||||
class WebPlotCaptureTest(unittest.TestCase):
|
||||
@classmethod
|
||||
def setUpClass(cls) -> None:
|
||||
cls.app = QApplication.instance() or QApplication([])
|
||||
cls.window = isolated_window(cls.addClassCleanup)
|
||||
cls.window._pipeline.timer.stop()
|
||||
cls.window._pipeline.replay.timer.stop()
|
||||
cls.window.show()
|
||||
|
||||
def setUp(self) -> None:
|
||||
cleanup = ExitStack()
|
||||
self.addCleanup(cleanup.close)
|
||||
self.w = self.window
|
||||
self.web = self.w._web
|
||||
self.web.set_frame_streaming(False)
|
||||
self.grab = cleanup.enter_context(mock.patch.object(self.web, "_grab_png", wraps=self.web._grab_png))
|
||||
|
||||
def settle(self) -> None:
|
||||
# Initial paints can settle the axis layout over several Qt event turns.
|
||||
for _ in range(10):
|
||||
self.app.processEvents()
|
||||
self.web._last_grab_s = 0
|
||||
self.web._grab_frame_if_due()
|
||||
|
||||
def test_no_clients_never_grabs_and_first_client_gets_current_plot(self) -> None:
|
||||
self.w._plots.bscan.widget.plot([0, 1], [1, 2])
|
||||
self.settle()
|
||||
self.grab.assert_not_called()
|
||||
controller = self.web
|
||||
mode = self.w._view.processing.mode
|
||||
with QSignalBlocker(mode):
|
||||
mode.setCurrentText("bscan")
|
||||
self.w._live.active_mode = "bscan"
|
||||
self.w._plots.bscan.history_by_combo = {(2, 3): deque([np.array([1., 2.])])}
|
||||
self.w._plots.sync_display_combos()
|
||||
self.web.refresh_snapshot()
|
||||
self.assertEqual(controller.status()["display_combo"],
|
||||
{"enabled": True, "input": 2, "output": 3, "options": [(2, 3)]})
|
||||
self.grab.assert_not_called()
|
||||
controller.set_frame_streaming(True)
|
||||
self.settle()
|
||||
self.assertGreater(self.grab.call_count, 0)
|
||||
self.assertIsNotNone(self.web._last_png)
|
||||
calls = self.grab.call_count
|
||||
self.settle()
|
||||
self.assertEqual(self.grab.call_count, calls) # grab does not keep itself dirty
|
||||
controller.set_frame_streaming(False)
|
||||
self.w._plots.bscan.widget.clear()
|
||||
self.settle()
|
||||
self.assertEqual(self.grab.call_count, calls)
|
||||
|
||||
def test_data_clear_zoom_resize_and_sar_grid_trigger_capture_after_idle(self) -> None:
|
||||
self.web.set_frame_streaming(True)
|
||||
plot = self.w._plots.bscan.widget
|
||||
item = plot.getPlotItem()
|
||||
assert item is not None
|
||||
view = item.getViewBox()
|
||||
self.w._plots.stack.setCurrentWidget(plot)
|
||||
self.settle()
|
||||
actions = [
|
||||
lambda: plot.plot([0, 1, 2], [1, 4, 2]),
|
||||
lambda: view.setXRange(0.25, 1.5, padding=0),
|
||||
plot.clear,
|
||||
lambda: self.w.resize(self.w.width() + 50, self.w.height() + 50),
|
||||
lambda: self.w._plots.stack.setCurrentWidget(self.w._plots.sar3d.widget),
|
||||
]
|
||||
actions.extend(lambda plot=plot: plot.plot([0, 1], [1, 3]) for plot in self.w._plots.sar3d.plots.values())
|
||||
for action in actions:
|
||||
with self.subTest(action=action):
|
||||
calls = self.grab.call_count
|
||||
action()
|
||||
self.settle()
|
||||
self.assertGreater(self.grab.call_count, calls)
|
||||
calls = self.grab.call_count
|
||||
self.settle()
|
||||
self.assertEqual(self.grab.call_count, calls)
|
||||
|
||||
def test_throttle_keeps_dirty_and_ignores_changes_emitted_during_grab(self) -> None:
|
||||
self.web.set_frame_streaming(True)
|
||||
self.settle()
|
||||
self.web._mark_dirty()
|
||||
self.web._last_grab_s = 100
|
||||
with mock.patch("python_app.gui.controllers.web_controller.time.monotonic", return_value=100.1):
|
||||
self.assertIsNone(self.web._grab_frame_if_due())
|
||||
self.assertTrue(self.web._dirty)
|
||||
self.grab.side_effect = lambda: (self.web._mark_dirty(), "changed-png")[1]
|
||||
with mock.patch("python_app.gui.controllers.web_controller.time.monotonic", return_value=100.3):
|
||||
self.assertIsNotNone(self.web._grab_frame_if_due())
|
||||
self.assertFalse(self.web._dirty)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
Reference in New Issue
Block a user