2222
2323
2424SLEEP_TIME = 0.2
25- DDS_STARTUP_TIME = 1.0
25+ DDS_STARTUP_TIME = 1.0 if os . name == 'nt' else 0.2
2626
2727
2828def safe_interrupt (p ):
@@ -74,16 +74,25 @@ def run_dds(self):
7474 @return Returns a subprocess object representing the running DDS publisher.
7575 """
7676 if self .dds :
77- self .command = [self .exec_dds , 'publisher' ] + self .arguments_dds
77+ self .command = [self .exec_dds , 'publisher' ]
78+ env = os .environ .copy ()
79+
80+ # Windows CI is flaky when the helper publisher uses default SHM transport.
81+ # Force plain UDP there, but keep the normal participant construction path so
82+ # tests still observe the expected participant name ("Participant_pub").
83+ if os .name == 'nt' :
84+ self .command .append ('--transport=udp' )
85+
86+ self .command .extend (self .arguments_dds )
7887
7988 proc = subprocess .Popen (self .command ,
80- stdin = subprocess .PIPE ,
81- stdout = subprocess .PIPE ,
82- stderr = subprocess .PIPE )
89+ stdin = subprocess .DEVNULL ,
90+ stdout = subprocess .DEVNULL ,
91+ stderr = subprocess .DEVNULL ,
92+ env = env )
8393
84- # Give the publisher time to initialize its participant and writer
85- # before the spy starts discovery. Windows CI is noticeably slower
86- # than local runs, which makes the one-shot discovery tests flaky.
94+ # Give the helper publisher time to create its participant before the Spy starts
95+ # measuring discovery on slower Windows CI runners.
8796 time .sleep (DDS_STARTUP_TIME )
8897
8998 return proc
@@ -114,18 +123,10 @@ def run_tool(self):
114123 if self .arguments_spy [:2 ] == ['show' , 'all' ]:
115124 safe_interrupt (proc )
116125 try :
117- output , error = proc .communicate (timeout = 10 )
126+ output = proc .communicate (timeout = 10 )[ 0 ]
118127 except subprocess .TimeoutExpired :
119128 proc .kill ()
120- output , error = proc .communicate ()
121- print ('ERROR: Spy process timed out' )
122- if error :
123- print (error )
124- return None
125-
126- if error :
127- print (error )
128-
129+ output = ''
129130 if not self .valid_output (output ):
130131 return None
131132
@@ -188,6 +189,9 @@ def read_command_output(self, proc):
188189
189190 line = proc .stdout .readline ()
190191
192+ if line == '' and proc .poll () is not None :
193+ break
194+
191195 if ('Insert a command for Fast DDS Spy:' in line ):
192196 break
193197
@@ -295,27 +299,27 @@ def valid_output(self, output) -> bool:
295299 """
296300 clean_output = self .extract_cli_output (output )
297301 expected_output = self .output_command ()
298-
299- # Empty outputs can be represented as '' or '\n' depending on the
300- # platform/runtime. Treat both as equivalent to avoid CI-only flakes.
301- if not clean_output .strip () and not expected_output .strip ():
302- return True
303-
304302 if expected_output == clean_output :
305303 return True
306304
307305 lines_expected_output = expected_output .splitlines ()
308306 lines_output = clean_output .splitlines ()
309307
308+ while lines_expected_output and lines_expected_output [- 1 ] == '' :
309+ lines_expected_output .pop ()
310+
311+ while lines_output and lines_output [- 1 ] == '' :
312+ lines_output .pop ()
313+
314+ if len (lines_output ) < len (lines_expected_output ):
315+ print ('Output: ' )
316+ print (clean_output )
317+ print ('Expected output: ' )
318+ print (expected_output )
319+ return False
320+
310321 # TODO (Raul): If guid and rate are on the same line this will not work.
311322 for i in range (len (lines_expected_output )):
312- if i >= len (lines_output ):
313- print ('Output: ' )
314- print (clean_output )
315- print ('Expected output: ' )
316- print (expected_output )
317- return False
318-
319323 if '%%guid%%' in lines_expected_output [i ]:
320324 start_guid_position = lines_expected_output [i ].find ('%%guid%%' )
321325
@@ -335,12 +339,13 @@ def valid_output(self, output) -> bool:
335339 print (expected_output )
336340 return False
337341
338- if len (lines_output ) != len (lines_expected_output ):
339- print ('Output: ' )
340- print (clean_output )
341- print ('Expected output: ' )
342- print (expected_output )
343- return False
342+ for extra_line in lines_output [len (lines_expected_output ):]:
343+ if extra_line != '' :
344+ print ('Output: ' )
345+ print (clean_output )
346+ print ('Expected output: ' )
347+ print (expected_output )
348+ return False
344349
345350 return True
346351
0 commit comments