1
1
import json
2
2
import re
3
+ import time
3
4
4
5
import gdbremote_testcase
5
6
from lldbsuite .test .decorators import *
@@ -13,8 +14,7 @@ def start_threads(self, num):
13
14
# start the process and wait for output
14
15
self .test_sequence .add_log_lines ([
15
16
"read packet: $c#63" ,
16
- {"type" : "output_match" , "regex" : self .maybe_strict_output_regex (
17
- r"@started\r\n" )},
17
+ {"type" : "output_match" , "regex" : r".*@started\r\n.*" },
18
18
], True )
19
19
# then interrupt it
20
20
self .add_interrupt_packets ()
@@ -33,9 +33,8 @@ def send_and_check_signal(self, vCont_data, threads):
33
33
self .test_sequence .add_log_lines ([
34
34
"read packet: $vCont;{0}#00" .format (vCont_data ),
35
35
{"type" : "output_match" ,
36
- "regex" : self .maybe_strict_output_regex (
37
- len (threads ) *
38
- r"received SIGUSR1 on thread id: ([0-9a-f]+)\r\n" ),
36
+ "regex" : len (threads ) *
37
+ r".*received SIGUSR1 on thread id: ([0-9a-f]+)\r\n.*" ,
39
38
"capture" : dict ((i , "tid{0}" .format (i )) for i
40
39
in range (1 , len (threads )+ 1 )),
41
40
},
@@ -243,3 +242,71 @@ def test_signal_two_signals(self):
243
242
244
243
context = self .expect_gdbremote_sequence ()
245
244
self .assertIsNotNone (context )
245
+
246
+ THREAD_MATCH_RE = re .compile (r"thread ([0-9a-f]+) running" )
247
+
248
+ def continue_and_get_threads_running (self , continue_packet ):
249
+ self .test_sequence .add_log_lines (
250
+ ["read packet: ${}#00" .format (continue_packet ),
251
+ ], True )
252
+ self .expect_gdbremote_sequence ()
253
+ self .reset_test_sequence ()
254
+ time .sleep (1 )
255
+ self .add_interrupt_packets ()
256
+ exp = self .expect_gdbremote_sequence ()
257
+ found = set ()
258
+ for line in exp ["O_content" ].decode ().splitlines ():
259
+ m = self .THREAD_MATCH_RE .match (line )
260
+ if m is not None :
261
+ found .add (int (m .group (1 ), 16 ))
262
+ return found
263
+
264
+ @add_test_categories (["llgs" ])
265
+ def test_vCont_run_subset_of_threads (self ):
266
+ self .build ()
267
+ self .set_inferior_startup_launch ()
268
+
269
+ threads = set (self .start_threads (3 ))
270
+ all_subthreads = self .continue_and_get_threads_running ("c" )
271
+ all_subthreads_list = list (all_subthreads )
272
+ self .assertEqual (len (all_subthreads ), 3 )
273
+ self .assertEqual (threads & all_subthreads , all_subthreads )
274
+
275
+ # resume two threads explicitly, stop the third one implicitly
276
+ self .assertEqual (
277
+ self .continue_and_get_threads_running (
278
+ "vCont;c:{:x};c:{:x}" .format (* all_subthreads_list [:2 ])),
279
+ set (all_subthreads_list [:2 ]))
280
+
281
+ # resume two threads explicitly, stop others explicitly
282
+ self .assertEqual (
283
+ self .continue_and_get_threads_running (
284
+ "vCont;c:{:x};c:{:x};t" .format (* all_subthreads_list [:2 ])),
285
+ set (all_subthreads_list [:2 ]))
286
+
287
+ # stop one thread explicitly, resume others
288
+ self .assertEqual (
289
+ self .continue_and_get_threads_running (
290
+ "vCont;t:{:x};c" .format (all_subthreads_list [- 1 ])),
291
+ set (all_subthreads_list [:2 ]))
292
+
293
+ # resume one thread explicitly, stop one explicitly,
294
+ # resume others
295
+ self .assertEqual (
296
+ self .continue_and_get_threads_running (
297
+ "vCont;c:{:x};t:{:x};c" .format (* all_subthreads_list [- 2 :])),
298
+ set (all_subthreads_list [:2 ]))
299
+
300
+ # resume one thread explicitly, stop one explicitly,
301
+ # stop others implicitly
302
+ self .assertEqual (
303
+ self .continue_and_get_threads_running (
304
+ "vCont;t:{:x};c:{:x}" .format (* all_subthreads_list [:2 ])),
305
+ set (all_subthreads_list [1 :2 ]))
306
+
307
+ # resume one thread explicitly, stop one explicitly,
308
+ # stop others explicitly
309
+ self .assertEqual (
310
+ self .continue_and_get_threads_running (
311
+ "vCont;t:{:x};c:{:x};t" .format (* all_subthreads_list [:2 ])),
312
+ set (all_subthreads_list [1 :2 ]))
0 commit comments