Skip to content

Commit e2c02af

Browse files
committed
tests: resume and pause transitions tests
1 parent ca87aff commit e2c02af

1 file changed

Lines changed: 205 additions & 0 deletions

File tree

Lines changed: 205 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,205 @@
1+
"""Tests for resume and pause transitions in the Manager."""
2+
3+
import pytest
4+
from transitions import MachineError
5+
import utils as test_utils
6+
from manager.manager.manager import Manager
7+
8+
9+
class DummyConsumer:
10+
"""A dummy consumer to capture messages sent by the Manager."""
11+
12+
def __init__(self):
13+
"""
14+
Initialize the DummyConsumer with empty message storage.
15+
16+
This constructor sets up the messages list and last_message attribute.
17+
"""
18+
self.messages = []
19+
self.last_message = None
20+
21+
def send_message(self, *args, **kwargs):
22+
"""
23+
Capture and store a message sent by the Manager.
24+
25+
Stores the message arguments and updates the last_message attribute.
26+
"""
27+
self.messages.append((args, kwargs))
28+
self.last_message = (args, kwargs)
29+
30+
31+
@pytest.fixture
32+
def manager(monkeypatch):
33+
"""Fixture to provide a Manager instance with patched dependencies for testing."""
34+
35+
# Patch subprocess.check_output for ROS_DISTRO and IMAGE_TAG
36+
def fake_check_output(cmd, *a, **k):
37+
if "ROS_DISTRO" in cmd[-1]:
38+
return b"humble"
39+
if "IMAGE_TAG" in cmd[-1]:
40+
return b"test_image_tag"
41+
return b""
42+
43+
monkeypatch.setattr("subprocess.check_output", fake_check_output)
44+
45+
# Patch check_gpu_acceleration where it is used
46+
monkeypatch.setattr(
47+
"manager.manager.manager.check_gpu_acceleration", lambda x=None: "OFF"
48+
)
49+
50+
# Patch os.makedirs and os.path.isdir to avoid real FS operations
51+
monkeypatch.setattr("os.makedirs", lambda path, exist_ok=False: None)
52+
monkeypatch.setattr("os.path.isdir", lambda path: True)
53+
54+
# Patch LauncherWorld to avoid launching real processes
55+
class DummyLauncherWorld:
56+
def __init__(self, *a, **k):
57+
self.launched = False
58+
59+
def launch(self):
60+
self.launched = True
61+
62+
def run(self):
63+
self.launched = True
64+
# Simulate running the world
65+
return
66+
67+
def terminate(self):
68+
pass
69+
70+
monkeypatch.setattr("manager.manager.manager.LauncherWorld", DummyLauncherWorld)
71+
72+
# Patch Server and FileWatchdog to avoid starting real servers
73+
class DummyServer:
74+
def __init__(self, port, update_callback):
75+
self.port = port
76+
self.update_callback = update_callback
77+
self.started = False
78+
79+
def start(self):
80+
self.started = True
81+
82+
def stop(self):
83+
self.started = False
84+
85+
class DummyFileWatchdog:
86+
def __init__(self, path, update_callback):
87+
self.path = path
88+
self.update_callback = update_callback
89+
self.started = False
90+
91+
def start(self):
92+
self.started = True
93+
94+
def stop(self):
95+
self.started = False
96+
97+
class DummyVisualizationLauncher:
98+
def __init__(self, *args, **kwargs):
99+
self.launchers = []
100+
101+
def run(self):
102+
# Simulate running the visualization launcher
103+
return
104+
105+
def terminate(self):
106+
pass
107+
108+
monkeypatch.setattr(
109+
"manager.manager.manager.LauncherVisualization", DummyVisualizationLauncher
110+
)
111+
monkeypatch.setattr("manager.manager.manager.Server", DummyServer)
112+
monkeypatch.setattr("manager.manager.manager.FileWatchdog", DummyFileWatchdog)
113+
114+
# Setup Manager with dummy consumer
115+
m = Manager(host="localhost", port=12345)
116+
m.consumer = DummyConsumer()
117+
return m
118+
119+
120+
def test_pause_transition_valid(manager, monkeypatch):
121+
"""Test the valid pause transition in the Manager."""
122+
# Ensure the manager is in a state where it can pause
123+
test_utils.setup_manager_to_application_running(manager, monkeypatch)
124+
125+
# Mock needed methods and attributes
126+
class DummyProc:
127+
def suspend(self):
128+
pass
129+
130+
monkeypatch.setattr("psutil.Process", lambda pid: DummyProc())
131+
132+
manager.pause_sim = lambda: None
133+
134+
# Trigger the pause transition
135+
manager.trigger("pause")
136+
# Check that the state has changed to 'paused'
137+
assert manager.state == "paused"
138+
# Verify that the consumer received the correct message
139+
assert manager.consumer.last_message[0][0]['state'] == "paused"
140+
141+
142+
def test_pause_transition_invalid_machine_error(manager, monkeypatch):
143+
"""Test the invalid pause transition in the Manager."""
144+
# Ensure the manager is in a state where it can pause
145+
test_utils.setup_manager_to_visualization_ready(manager, monkeypatch)
146+
147+
# Mock needed methods and attributes
148+
class DummyProc:
149+
def suspend(self):
150+
pass
151+
152+
monkeypatch.setattr("psutil.Process", lambda pid: DummyProc())
153+
154+
# Trigger the pause transition
155+
with pytest.raises(MachineError):
156+
manager.trigger("pause")
157+
# Check that the state has changed to 'paused'
158+
assert manager.state == "visualization_ready"
159+
160+
161+
def test_resume_transition_valid(manager, monkeypatch):
162+
"""Test the valid resume transition in the Manager."""
163+
# Ensure the manager is in a paused state
164+
test_utils.setup_manager_to_application_running(manager, monkeypatch)
165+
166+
# Mock needed methods and attributes
167+
class DummyProc:
168+
def suspend(self):
169+
pass
170+
171+
def resume(self):
172+
pass
173+
174+
monkeypatch.setattr("psutil.Process", lambda pid: DummyProc())
175+
manager.pause_sim = lambda: None
176+
177+
# Move to 'paused' state first
178+
manager.trigger("pause")
179+
assert manager.state == "paused"
180+
181+
# Trigger the resume transition
182+
manager.trigger("resume")
183+
# Check that the state has changed to 'application_running'
184+
assert manager.state == "application_running"
185+
# Verify that the consumer received the correct message
186+
assert manager.consumer.last_message[0][0]['state'] == "application_running"
187+
188+
189+
def test_resume_transition_invalid(manager, monkeypatch):
190+
"""Test the invalid resume transition in the Manager."""
191+
# Ensure the manager is in a state where it can resume
192+
test_utils.setup_manager_to_application_running(manager, monkeypatch)
193+
194+
# Mock needed methods and attributes
195+
class DummyProc:
196+
def resume(self):
197+
pass
198+
199+
monkeypatch.setattr("psutil.Process", lambda pid: DummyProc())
200+
201+
# Trigger the resume transition
202+
with pytest.raises(MachineError):
203+
manager.trigger("resume")
204+
# Check that the state has not changed
205+
assert manager.state == "application_running"

0 commit comments

Comments
 (0)