]>
Commit | Line | Data |
---|---|---|
5d5658a1 PA |
1 | # Copyright 2015-2016 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 | ||
18 | load_lib gdb-python.exp | |
19 | ||
20 | standard_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. | |
25 | if [target_info exists use_gdb_stub] { | |
26 | untested ${testfile}.exp | |
27 | return | |
28 | } | |
29 | ||
30 | if { [prepare_for_testing "failed to prepare" ${testfile} ${srcfile} {pthreads debug}] } { | |
31 | return -1 | |
32 | } | |
33 | ||
34 | clean_restart ${testfile} | |
35 | ||
36 | if { ![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. | |
42 | proc 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. | |
63 | proc 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. | |
78 | proc 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. | |
89 | proc 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 p 1234" \ | |
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. | |
101 | proc thr_apply_info_thr_invalid {tid_list expected} { | |
102 | set expected [string_to_regexp $expected] | |
103 | gdb_test "info threads $tid_list" \ | |
104 | "Invalid thread ID: $expected" | |
105 | ||
106 | gdb_test "thread apply $tid_list p 1234" \ | |
107 | "Invalid thread ID: $expected p 1234" \ | |
108 | "thread apply $tid_list" | |
109 | } | |
110 | ||
111 | # "info threads" while there's only inferior 1 should show | |
112 | # single-number thread IDs. | |
113 | with_test_prefix "single inferior" { | |
114 | info_threads "" "1" | |
115 | ||
116 | gdb_test "thread" "Current thread is 1 .*" | |
117 | } | |
118 | ||
119 | # "info threads" while there are multiple inferiors should show | |
120 | # qualified thread IDs. | |
121 | with_test_prefix "two inferiors" { | |
122 | # Add another inferior. | |
123 | gdb_test "add-inferior" "Added inferior 2.*" "add empty inferior 2" | |
124 | ||
125 | # Now that we've added another inferior, thread IDs now show the | |
126 | # inferior number. | |
127 | info_threads "" "1.1" | |
128 | ||
129 | gdb_test "thread" "Current thread is 1\.1 .*" | |
130 | ||
131 | gdb_test "inferior 2" "Switching to inferior 2 .*" "switch to inferior 2" | |
132 | gdb_test "file ${binfile}" ".*" "load file in inferior 2" | |
133 | ||
134 | runto_main | |
135 | ||
136 | # Now that we've added another inferior, thread IDs now show the | |
137 | # inferior number. | |
138 | info_threads "" "1.1 2.1" \ | |
139 | "info threads show inferior numbers" | |
140 | ||
141 | gdb_test "thread" "Current thread is 2\.1 .*" \ | |
142 | "switch to thread using extended thread ID" | |
143 | ||
144 | gdb_breakpoint "thread_function1" | |
145 | ||
146 | gdb_continue_to_breakpoint "once" | |
147 | gdb_test "inferior 1" "Switching to inferior 1 .*" | |
148 | gdb_continue_to_breakpoint "twice" | |
149 | ||
150 | info_threads "" "1.1 1.2 2.1 2.2" \ | |
151 | "info threads again" | |
152 | ||
153 | # Confirm the convenience variable show the expected number. | |
154 | gdb_test "p \$_thread == 2" " = 1" | |
155 | ||
156 | # Without an explicit inferior component, GDB defaults to the | |
157 | # current inferior. Make sure we don't refer to a thread by | |
158 | # global ID by mistake. | |
159 | gdb_test "thread 4" "Unknown thread 1.4\\." | |
160 | ||
161 | # Test thread ID list parsing. Test qualified and unqualified | |
162 | # IDs; qualified and unqualified ranges; invalid IDs and invalid | |
163 | # ranges. | |
164 | ||
165 | # First spawn a couple more threads so ranges includes more than | |
166 | # two threads. | |
167 | with_test_prefix "more threads" { | |
168 | gdb_breakpoint "thread_function2" | |
169 | ||
170 | gdb_test "inferior 2" "Switching to inferior 2 .*" | |
171 | gdb_continue_to_breakpoint "once" | |
172 | ||
173 | gdb_test "inferior 1" "Switching to inferior 1 .*" | |
174 | gdb_continue_to_breakpoint "twice" | |
175 | } | |
176 | ||
177 | thr_apply_info_thr "1 2 3" \ | |
178 | "1.1 1.2 1.3" | |
179 | ||
180 | # Same, but with qualified thread IDs. | |
181 | thr_apply_info_thr "1.1 1.2 1.3 2.1 2.2" \ | |
182 | "1.1 1.2 1.3 2.1 2.2" | |
183 | ||
184 | # Test a thread number range. | |
185 | thr_apply_info_thr "1-3" \ | |
186 | "1.1 1.2 1.3" | |
187 | ||
188 | # Same, but using a qualified range. | |
189 | thr_apply_info_thr "1.1-3" \ | |
190 | "1.1 1.2 1.3" | |
191 | ||
192 | # A mix of qualified and unqualified thread IDs/ranges. | |
193 | thr_apply_info_thr "1.1 2-3" \ | |
194 | "1.1 1.2 1.3" | |
195 | ||
196 | thr_apply_info_thr "1 1.2-3" \ | |
197 | "1.1 1.2 1.3" | |
198 | ||
199 | # Likewise, but mix inferiors too. | |
200 | thr_apply_info_thr "2.1 2-3" \ | |
201 | "1.2 1.3 2.1" \ | |
202 | "2.1 1.2 1.3" | |
203 | ||
204 | # Multiple ranges with mixed explicit inferiors. | |
205 | thr_apply_info_thr "1.1-2 2.2-3" \ | |
206 | "1.1 1.2 2.2 2.3" | |
207 | ||
208 | # Now test a set of invalid thread IDs/ranges. | |
209 | ||
210 | thr_apply_info_thr_invalid "1." \ | |
211 | "1." | |
212 | ||
213 | thr_apply_info_thr_invalid "1-3 1." \ | |
214 | "1." | |
215 | ||
216 | thr_apply_info_thr_invalid "1.1.1" \ | |
217 | "1.1.1" | |
218 | ||
219 | thr_apply_info_thr_invalid "2 1.1.1" \ | |
220 | "1.1.1" | |
221 | ||
222 | thr_apply_info_thr_invalid "1.1.1 2" \ | |
223 | "1.1.1 2" | |
224 | ||
225 | thr_apply_info_thr_invalid "1-2.1" \ | |
226 | "1-2.1" | |
227 | ||
228 | thr_apply_info_thr_error "1-0" "inverted range" | |
229 | thr_apply_info_thr_error "1.1-0" "inverted range" | |
230 | ||
231 | thr_apply_info_thr_error "1-" "inverted range" | |
232 | thr_apply_info_thr_error "1.1-" "inverted range" | |
233 | ||
234 | thr_apply_info_thr_error "2-1" "inverted range" | |
235 | thr_apply_info_thr_error "1.2-1" "inverted range" | |
236 | ||
237 | thr_apply_info_thr_error "-1" "negative value" | |
238 | thr_apply_info_thr_error "1.-1" "negative value" | |
239 | ||
240 | # Check that we do parse the inferior number and don't confuse it. | |
241 | gdb_test "info threads 3.1" \ | |
242 | "No threads match '3.1'\." | |
243 | } | |
244 | ||
245 | if { ![skip_python_tests] } { | |
246 | with_test_prefix "python" { | |
247 | # Check that InferiorThread.num returns the expected number. | |
248 | gdb_py_test_silent_cmd "python t0 = gdb.selected_thread ()" \ | |
249 | "test gdb.selected_thread" 1 | |
250 | gdb_test "python print ('result = %s' % t0.num)" " = 3" \ | |
251 | "test InferiorThread.num" | |
252 | } | |
253 | } | |
254 | ||
255 | # Remove the second inferior and confirm that GDB goes back to showing | |
256 | # single-number thread IDs. | |
257 | with_test_prefix "back to one inferior" { | |
258 | gdb_test "kill inferior 2" "" "kill inferior 2" "Kill the program being debugged.*" "y" | |
259 | gdb_test "thread 1.1" "Switching to thread 1\.1 .*" | |
260 | gdb_test "remove-inferior 2" ".*" "remove inferior 2" | |
261 | ||
262 | # "info threads" while there's only inferior 1 should show | |
263 | # single-number thread IDs. | |
264 | info_threads "" "1 2 3" | |
265 | ||
266 | gdb_test "thread" "Current thread is 1 .*" | |
267 | } | |
268 | ||
269 | # Add another inferior and remove inferior 1. Since even though | |
270 | # there's a single inferior, its number is not 1, GDB should show | |
271 | # inferior-qualified thread IDs. | |
272 | with_test_prefix "single-inferior but not initial" { | |
273 | # Add another inferior. | |
274 | gdb_test "add-inferior" "Added inferior 3.*" "add empty inferior" | |
275 | ||
276 | # Now that we'd added another inferior, thread IDs should show the | |
277 | # inferior number. | |
278 | info_threads "" "1.1 1.2 1.3" \ | |
279 | "info threads with multiple inferiors" | |
280 | ||
281 | gdb_test "thread" "Current thread is 1\.1 .*" | |
282 | ||
283 | gdb_test "inferior 3" "Switching to inferior 3 .*" "switch to inferior 3" | |
284 | gdb_test "file ${binfile}" ".*" "load file in inferior 3" | |
285 | ||
286 | runto_main | |
287 | ||
288 | gdb_test "remove-inferior 1" ".*" "remove inferior 1" | |
289 | ||
290 | # Even though we have a single inferior, its number is > 1, so | |
291 | # thread IDs should include the inferior number. | |
292 | info_threads "" "3.1" \ | |
293 | "info threads with single inferior" | |
294 | ||
295 | gdb_test "thread" "Current thread is 3\.1 .*" "thread again" | |
296 | } |