xref: /netbsd-src/external/gpl3/gdb.old/dist/gdb/testsuite/gdb.multi/tids.exp (revision 867d70fc718005c0918b8b8b2f9d7f2d52d0a0db)
1# Copyright 2015-2019 Free Software Foundation, Inc.
2
3# This program is free software; you can redistribute it and/or modify
4# it under the terms of the GNU General Public License as published by
5# the Free Software Foundation; either version 3 of the License, or
6# (at your option) any later version.
7#
8# This program is distributed in the hope that it will be useful,
9# but WITHOUT ANY WARRANTY; without even the implied warranty of
10# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11# GNU General Public License for more details.
12#
13# You should have received a copy of the GNU General Public License
14# along with this program.  If not, see <http://www.gnu.org/licenses/>.
15
16# Test thread ID parsing and display.
17
18load_lib gdb-python.exp
19
20standard_testfile
21
22# Multiple inferiors are needed, therefore both native and extended
23# gdbserver modes are supported.  Only non-extended gdbserver is not
24# supported.
25if [use_gdb_stub] {
26    untested "using gdb stub"
27    return
28}
29
30if { [prepare_for_testing "failed to prepare" ${testfile} ${srcfile} {pthreads debug}] } {
31    return -1
32}
33
34clean_restart ${testfile}
35
36if { ![runto_main] } then {
37    return -1
38}
39
40# Issue "thread apply TID_LIST p 1234" and expect EXP_TID_LIST (a list
41# of thread ids) to be displayed.
42proc thread_apply {tid_list exp_tid_list {message ""}} {
43    global decimal
44    set any "\[^\r\n\]*"
45    set expected [string_to_regexp $exp_tid_list]
46
47    set r ""
48    foreach tid $expected {
49	append r "\[\r\n\]+"
50	append r "Thread $tid $any:\r\n"
51	append r "\\$$decimal = 1234"
52    }
53
54    set cmd "thread apply $tid_list"
55    if {$message == ""} {
56	set message $cmd
57    }
58    gdb_test "$cmd p 1234" $r $message
59}
60
61# Issue "info threads TID_LIST" and expect EXP_TID_LIST (a list of
62# thread ids) to be displayed.
63proc info_threads {tid_list exp_tid_list {message ""}} {
64    set any "\[^\r\n\]*"
65    set expected [string_to_regexp $exp_tid_list]
66    set r [join $expected " ${any}\r\n${any} "]
67    set r "${any} $r ${any}"
68    set cmd "info threads $tid_list"
69    if {$message == ""} {
70	set message $cmd
71    }
72    gdb_test $cmd $r $message
73}
74
75# Issue "info threads TID_LIST" and expect INFO_THR output.  Then
76# issue "thread apply TID_LIST" and expect THR_APPLY output.  If
77# THR_APPLY is omitted, INFO_THR is expected instead.
78proc thr_apply_info_thr {tid_list info_thr {thr_apply ""}} {
79    if {$thr_apply == ""} {
80	set thr_apply $info_thr
81    }
82
83    info_threads $tid_list $info_thr
84    thread_apply $tid_list $thr_apply
85}
86
87# Issue both "info threads TID_LIST" and "thread apply TID_LIST" and
88# expect both commands to error out with EXP_ERROR.
89proc thr_apply_info_thr_error {tid_list exp_error}  {
90    gdb_test "info threads $tid_list" \
91	$exp_error
92
93    gdb_test "thread apply $tid_list" \
94	$exp_error \
95	"thread apply $tid_list"
96}
97
98# Issue both "info threads TID_LIST" and "thread apply TID_LIST" and
99# expect the command to error out with "Invalid thread ID: $EXPECTED".
100# EXPECTED is a literal string, not a regexp.  If EXPECTED is omitted,
101# TID_LIST is expected instead.
102proc thr_apply_info_thr_invalid {tid_list {expected ""}} {
103    if {$expected == ""} {
104	set expected $tid_list
105    }
106    set expected [string_to_regexp $expected]
107    gdb_test "info threads $tid_list" \
108	"Invalid thread ID: $expected"
109
110    gdb_test "thread apply $tid_list p 1234" \
111	"Invalid thread ID: $expected p 1234" \
112	"thread apply $tid_list"
113}
114
115# "info threads" while there's only inferior 1 should show
116# single-number thread IDs.
117with_test_prefix "single inferior" {
118    info_threads "" "1"
119
120    gdb_test "thread" "Current thread is 1 .*"
121}
122
123# "info threads" while there are multiple inferiors should show
124# qualified thread IDs.
125with_test_prefix "two inferiors" {
126    # Add another inferior.
127    gdb_test "add-inferior" "Added inferior 2.*" "add empty inferior 2"
128
129    # Now that we've added another inferior, thread IDs now show the
130    # inferior number.
131    info_threads "" "1.1"
132
133    gdb_test "thread" "Current thread is 1\.1 .*"
134
135    gdb_test "inferior 2" "Switching to inferior 2 .*" "switch to inferior 2"
136    gdb_test "file ${binfile}" ".*" "load file in inferior 2"
137
138    runto_main
139
140    # Now that we've added another inferior, thread IDs now show the
141    # inferior number.
142    info_threads "" "1.1 2.1" \
143	"info threads show inferior numbers"
144
145    gdb_test "thread" "Current thread is 2\.1 .*" \
146	"switch to thread using extended thread ID"
147
148    gdb_breakpoint "thread_function1"
149
150    gdb_continue_to_breakpoint "once"
151    gdb_test "inferior 1" "Switching to inferior 1 .*"
152    gdb_continue_to_breakpoint "twice"
153
154    info_threads "" "1.1 1.2 2.1 2.2" \
155	"info threads again"
156
157    # Same, but show the global ID.
158    gdb_test "info threads -gid" \
159	[multi_line \
160	     "  1\.1 +1 +.*" \
161	     "\\* 1\.2 +4 +.* thread_function1 .* at .*$srcfile:.*" \
162	     "  2\.1 +2 +.*" \
163	     "  2\.2 +3 +.* thread_function1 .* at .*$srcfile:.*"]
164
165    # Confirm the convenience variables show the expected numbers.
166    gdb_test "p \$_thread == 2" " = 1"
167    gdb_test "p \$_gthread == 4" " = 1"
168
169    # Without an explicit inferior component, GDB defaults to the
170    # current inferior.  Make sure we don't refer to a thread by
171    # global ID by mistake.
172    gdb_test "thread 4" "Unknown thread 1.4\\."
173
174    # Test thread ID list parsing.  Test qualified and unqualified
175    # IDs; qualified and unqualified ranges; invalid IDs and invalid
176    # ranges.
177
178    # First spawn a couple more threads so ranges includes more than
179    # two threads.
180    with_test_prefix "more threads" {
181	gdb_breakpoint "thread_function2"
182
183	gdb_test "inferior 2" "Switching to inferior 2 .*"
184	gdb_continue_to_breakpoint "once"
185
186	gdb_test "inferior 1" "Switching to inferior 1 .*"
187	gdb_continue_to_breakpoint "twice"
188    }
189
190    thr_apply_info_thr "1" \
191	"1.1"
192
193    thr_apply_info_thr "1.1" \
194	"1.1"
195
196    thr_apply_info_thr "1 2 3" \
197	"1.1 1.2 1.3"
198
199    # Same, but with qualified thread IDs.
200    thr_apply_info_thr "1.1 1.2 1.3 2.1 2.2" \
201	"1.1 1.2 1.3 2.1 2.2"
202
203    # Test a thread number range.
204    thr_apply_info_thr "1-3" \
205	"1.1 1.2 1.3"
206
207    # Same, but using a qualified range.
208    thr_apply_info_thr "1.1-3" \
209	"1.1 1.2 1.3"
210
211    # A mix of qualified and unqualified thread IDs/ranges.
212    thr_apply_info_thr "1.1 2-3" \
213	"1.1 1.2 1.3"
214
215    thr_apply_info_thr "1 1.2-3" \
216	"1.1 1.2 1.3"
217
218    # Likewise, but mix inferiors too.
219    thr_apply_info_thr "2.1 2-3" \
220	"1.2 1.3 2.1" \
221	"2.1 1.2 1.3"
222
223    # Multiple ranges with mixed explicit inferiors.
224    thr_apply_info_thr "1.1-2 2.2-3" \
225	"1.1 1.2 2.2 2.3"
226
227    # All threads.
228    thread_apply "all" \
229	"2.3 2.2 2.1 1.3 1.2 1.1"
230    thread_apply "all -ascending" \
231	"1.1 1.2 1.3 2.1 2.2 2.3"
232
233    # Now test using GDB convenience variables.
234
235    gdb_test "p \$inf = 1" " = 1"
236    gdb_test "p \$thr_start = 2" " = 2"
237    gdb_test "p \$thr_end = 3" " = 3"
238
239    # Convenience variable for the inferior number, only.
240    thr_apply_info_thr "\$inf.2" \
241	"1.2"
242    thr_apply_info_thr "\$inf.2-3" \
243	"1.2 1.3"
244
245    # Convenience variables for thread numbers as well.
246    foreach prefix {"" "1." "\$inf."} {
247	thr_apply_info_thr "${prefix}\$thr_start" \
248	    "1.2"
249	thr_apply_info_thr "${prefix}\$thr_start-\$thr_end" \
250	    "1.2 1.3"
251	thr_apply_info_thr "${prefix}2-\$thr_end" \
252	    "1.2 1.3"
253	thr_apply_info_thr "${prefix}\$thr_start-3" \
254	    "1.2 1.3"
255
256	# Undefined convenience variable.
257	set prefix_re [string_to_regexp $prefix]
258	thr_apply_info_thr_error "${prefix}\$conv123" \
259	    [multi_line \
260		 "Convenience variable must have integer value\." \
261		 "Invalid thread ID: ${prefix_re}\\\$conv123"]
262    }
263
264    # Convenience variables pointing at an inexisting thread and/or
265    # inferior.
266    gdb_test "p \$inf = 30" " = 30"
267    gdb_test "p \$thr = 20" " = 20"
268    # Try both the convenience variable and the literal number.
269    foreach thr {"\$thr" "20" "1.20" "\$inf.1" "30.1" } {
270	set expected [string_to_regexp $thr]
271	gdb_test "info threads $thr" "No threads match '${expected}'."
272	# "info threads" works like a filter.  If there's any other
273	# valid thread in the list, there's no error.
274	info_threads "$thr 1.1" "1.1"
275	info_threads "1.1 $thr" "1.1"
276    }
277
278    gdb_test "thread apply \$thr p 1234" \
279	"warning: Unknown thread 1.20" \
280	"thread apply \$thr"
281
282    gdb_test "thread apply \$inf.1 p 1234" \
283	"warning: Unknown thread 30.1" \
284	"thread apply \$inf.1"
285
286    # Star ranges.
287
288    thr_apply_info_thr "1.*" \
289	"1.1 1.2 1.3"
290
291    thr_apply_info_thr "*" \
292	"1.1 1.2 1.3"
293
294    thr_apply_info_thr "1.* 2.1" \
295	"1.1 1.2 1.3 2.1"
296
297    thr_apply_info_thr "2.1 1.*" \
298	"1.1 1.2 1.3 2.1" \
299	"2.1 1.1 1.2 1.3"
300
301    thr_apply_info_thr "1.* 2.*" \
302	"1.1 1.2 1.3 2.1 2.2 2.3"
303
304    thr_apply_info_thr "2.* 1.*" \
305	"1.1 1.2 1.3 2.1 2.2 2.3" \
306	"2.1 2.2 2.3 1.1 1.2 1.3"
307
308    # There's no inferior 3, but "info threads" treats the thread list
309    # as a filter, so it's OK.  "thread apply" complains about the
310    # unknown inferior through.
311    info_threads "1.1 3.*" \
312	"1.1"
313    gdb_test "thread apply 1.1 3.* p 1" \
314	"Thread 1.1.*warning: Unknown inferior 3"
315
316    # Now test a set of invalid thread IDs/ranges.
317
318    thr_apply_info_thr_invalid "1." \
319	"1."
320
321    thr_apply_info_thr_invalid "1-3 1." \
322	"1."
323
324    thr_apply_info_thr_invalid "1.1.1" \
325	"1.1.1"
326
327    thr_apply_info_thr_invalid "2 1.1.1" \
328	"1.1.1"
329
330    thr_apply_info_thr_invalid "1.1.1 2" \
331	"1.1.1 2"
332
333    thr_apply_info_thr_invalid "1-2.1" \
334	"1-2.1"
335
336    gdb_test "p \$zero = 0" " = 0"
337    gdb_test "p \$one = 1" " = 1"
338    gdb_test "p \$minus_one = -11" " = -11"
339    foreach prefix {"" "1." "$one."} {
340	set prefix_re [string_to_regexp $prefix]
341
342	thr_apply_info_thr_invalid "${prefix}foo"
343	thr_apply_info_thr_invalid "${prefix}1foo"
344	thr_apply_info_thr_invalid "${prefix}foo1"
345
346	thr_apply_info_thr_error "${prefix}1-0" "inverted range"
347	thr_apply_info_thr_error "${prefix}1-\$zero" "inverted range"
348	thr_apply_info_thr_error "${prefix}\$one-0" "inverted range"
349	thr_apply_info_thr_error "${prefix}\$one-\$zero" "inverted range"
350	thr_apply_info_thr_error "${prefix}1-" "inverted range"
351	thr_apply_info_thr_error "${prefix}2-1" "inverted range"
352	thr_apply_info_thr_error "${prefix}2-\$one" "inverted range"
353	thr_apply_info_thr_error "${prefix}-1" "negative value"
354	thr_apply_info_thr_error "${prefix}-\$one" "negative value"
355	thr_apply_info_thr_error "${prefix}\$minus_one" \
356	    "negative value: ${prefix_re}\\\$minus_one"
357
358	thr_apply_info_thr_error "${prefix}1-*" "inverted range"
359	thr_apply_info_thr_invalid "${prefix}*1"
360	thr_apply_info_thr_invalid "${prefix}*foo"
361	thr_apply_info_thr_invalid "${prefix}foo*"
362    }
363
364    # Check that a valid thread ID list with a missing command errors
365    # out.
366    with_test_prefix "missing command" {
367	set output "Please specify a command following the thread ID list"
368	gdb_test "thread apply 1" $output
369	gdb_test "thread apply 1.1" $output
370	gdb_test "thread apply 1.1 1.2" $output
371	gdb_test "thread apply 1-2" $output
372	gdb_test "thread apply 1.1-2" $output
373	gdb_test "thread apply $thr" $output
374	gdb_test "thread apply 1.*" $output
375    }
376
377    # Check that we do parse the inferior number and don't confuse it.
378    gdb_test "info threads 3.1" \
379	"No threads match '3.1'\."
380}
381
382if { ![skip_python_tests] } {
383    with_test_prefix "python" {
384	# Check that InferiorThread.num and InferiorThread.global_num
385	# return the expected numbers.
386	gdb_py_test_silent_cmd "python t0 = gdb.selected_thread ()" \
387	    "test gdb.selected_thread" 1
388	gdb_test "python print ('result = %s' % t0.num)" " = 3" \
389	    "test InferiorThread.num"
390	gdb_test "python print ('result = %s' % t0.global_num)" " = 6" \
391	    "test InferiorThread.global_num"
392
393	# Breakpoint.thread expects global IDs.  Confirm that that
394	# works as expected.
395	delete_breakpoints
396	gdb_breakpoint "thread_function1"
397
398	gdb_py_test_silent_cmd "python bp = gdb.breakpoints()\[0\]" \
399	    "get python breakpoint" 0
400	gdb_test "python bp.thread = 6" "thread = 6" \
401	    "make breakpoint thread-specific with python"
402	# Check that the inferior-qualified ID is correct.
403	gdb_test "info breakpoint" \
404	    "stop only in thread 1.3\r\n.*" \
405	    "thread specific breakpoint right thread"
406    }
407}
408
409# Remove the second inferior and confirm that GDB goes back to showing
410# single-number thread IDs.
411with_test_prefix "back to one inferior" {
412    gdb_test "kill inferior 2" "" "kill inferior 2" "Kill the program being debugged.*" "y"
413    gdb_test "thread 1.1" "Switching to thread 1\.1 .*"
414    gdb_test "remove-inferior 2" ".*" "remove inferior 2"
415
416    # "info threads" while there's only inferior 1 should show
417    # single-number thread IDs.
418    info_threads "" "1 2 3"
419
420    gdb_test "thread" "Current thread is 1 .*"
421}
422
423# Add another inferior and remove inferior 1.  Since even though
424# there's a single inferior, its number is not 1, GDB should show
425# inferior-qualified thread IDs.
426with_test_prefix "single-inferior but not initial" {
427    # Add another inferior.
428    gdb_test "add-inferior" "Added inferior 3.*" "add empty inferior"
429
430    # Now that we'd added another inferior, thread IDs should show the
431    # inferior number.
432    info_threads "" "1.1 1.2 1.3" \
433	"info threads with multiple inferiors"
434
435    gdb_test "thread" "Current thread is 1\.1 .*"
436
437    gdb_test "inferior 3" "Switching to inferior 3 .*" "switch to inferior 3"
438    gdb_test "file ${binfile}" ".*" "load file in inferior 3"
439
440    runto_main
441
442    gdb_test "remove-inferior 1" ".*" "remove inferior 1"
443
444    # Even though we have a single inferior, its number is > 1, so
445    # thread IDs should include the inferior number.
446    info_threads "" "3.1" \
447	"info threads with single inferior"
448
449    gdb_test "thread" "Current thread is 3\.1 .*" "thread again"
450}
451