Skip to content

Commit 25b9e36

Browse files
fix race-condition in tests
1 parent 4881135 commit 25b9e36

2 files changed

Lines changed: 19 additions & 12 deletions

File tree

jig_example/test/helpers.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010

1111
from lifecycle_msgs.srv import ChangeState, GetState
1212

13-
TIMEOUT = 10.0
13+
TIMEOUT = 20.0
1414

1515

1616
def wait_for_node_state(node: Node, name: str, target_state: int, timeout: float = TIMEOUT) -> bool:

jig_example/test/test_sync.py

Lines changed: 18 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
import unittest
44

5-
from helpers import TIMEOUT, wait_for_node_state, wait_for_topic_message
5+
from helpers import TIMEOUT, wait_for_node_state
66
import launch
77
import launch_ros.actions
88
import launch_testing
@@ -96,22 +96,29 @@ def _test_sync_node(self, namespace):
9696
"""Test that a sync node publishes a combined output."""
9797
self._wait_active(f"{namespace}/{namespace}")
9898

99+
# Subscribe to `output` BEFORE publishing the inputs. The sync node fires its sync callback and publishes once
100+
# as soon as both inputs land; under RELIABLE QoS the publisher only buffers for subscribers it already knows
101+
# about, so a sub created after the burst can miss the message on a fast (or cold-discovery) runner.
102+
received = [None]
103+
104+
def on_output(msg):
105+
if received[0] is None and "synced:" in msg.data:
106+
received[0] = msg
107+
108+
sub = self.node.create_subscription(String, f"{namespace}/output", on_output, self.qos)
109+
99110
pub_a, pub_b = self._publish_synced_points(namespace, 1.0, 2.0, 3.0, 4.0)
100111

101-
msg = wait_for_topic_message(
102-
self.node,
103-
f"{namespace}/output",
104-
String,
105-
timeout=TIMEOUT,
106-
qos=self.qos,
107-
predicate=lambda m: "synced:" in m.data,
108-
)
112+
end = self.node.get_clock().now() + rclpy.duration.Duration(seconds=TIMEOUT)
113+
while received[0] is None and self.node.get_clock().now() < end:
114+
rclpy.spin_once(self.node, timeout_sec=0.1)
109115

116+
self.node.destroy_subscription(sub)
110117
self.node.destroy_publisher(pub_a)
111118
self.node.destroy_publisher(pub_b)
112119

113-
self.assertIsNotNone(msg, f"Did not receive synced output from {namespace}")
114-
self.assertIn("synced:", msg.data)
120+
self.assertIsNotNone(received[0], f"Did not receive synced output from {namespace}")
121+
self.assertIn("synced:", received[0].data)
115122

116123
def test_cpp_sync_node(self):
117124
"""C++ sync node delivers paired messages through sync callback."""

0 commit comments

Comments
 (0)