user-selected-context-sync.exp revision 1.1.1.7 1 1.1.1.6 christos # Copyright 2016-2024 Free Software Foundation, Inc.
2 1.1 christos
3 1.1 christos # This program is free software; you can redistribute it and/or modify
4 1.1 christos # it under the terms of the GNU General Public License as published by
5 1.1 christos # the Free Software Foundation; either version 3 of the License, or
6 1.1 christos # (at your option) any later version.
7 1.1 christos #
8 1.1 christos # This program is distributed in the hope that it will be useful,
9 1.1 christos # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 1.1 christos # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 1.1 christos # GNU General Public License for more details.
12 1.1 christos #
13 1.1 christos # You should have received a copy of the GNU General Public License
14 1.1 christos # along with this program. If not, see <http://www.gnu.org/licenses/>.
15 1.1 christos
16 1.1 christos # This test checks that the "thread", "select-frame", "frame" and "inferior"
17 1.1 christos # CLI commands, as well as the "-thread-select" and "-stack-select-frame" MI
18 1.1 christos # commands send the appropriate user-selection-change events to all UIs.
19 1.1 christos #
20 1.1 christos # This test considers the case where console and MI are two different UIs,
21 1.1 christos # and MI is created with the new-ui command.
22 1.1 christos #
23 1.1 christos # It also considers the case where the console commands are sent directly in
24 1.1 christos # the MI channel as described in PR 20487.
25 1.1 christos #
26 1.1 christos # It does so by starting 2 inferiors with 3 threads each.
27 1.1 christos # - Thread 1 of each inferior is the main thread, starting the others.
28 1.1 christos # - Thread 2 of each inferior is stopped at /* thread loop line */.
29 1.1 christos # - Thread 3 of each inferior is either stopped at /* thread loop line */, if we
30 1.1 christos # are using all-stop, or running, if we are using non-stop.
31 1.1 christos
32 1.1.1.4 christos # Do not run if gdb debug is enabled as it doesn't work for separate-mi-tty.
33 1.1.1.6 christos require !gdb_debug_enabled
34 1.1.1.4 christos
35 1.1 christos load_lib mi-support.exp
36 1.1 christos
37 1.1 christos standard_testfile
38 1.1 christos
39 1.1 christos # Multiple inferiors are needed, therefore only native gdb and extended
40 1.1 christos # gdbserver modes are supported.
41 1.1.1.6 christos require !use_gdb_stub
42 1.1 christos
43 1.1 christos set compile_options "debug pthreads"
44 1.1 christos if {[build_executable $testfile.exp $testfile ${srcfile} ${compile_options}] == -1} {
45 1.1.1.2 christos untested "failed to compile"
46 1.1 christos return -1
47 1.1 christos }
48 1.1 christos
49 1.1 christos set main_break_line [gdb_get_line_number "main break line"]
50 1.1 christos set thread_loop_line [gdb_get_line_number "thread loop line"]
51 1.1 christos set thread_caller_line [gdb_get_line_number "thread caller line"]
52 1.1 christos
53 1.1 christos # Return whether we expect thread THREAD to be running in mode MODE.
54 1.1 christos #
55 1.1 christos # MODE can be either "all-stop" or "non-stop".
56 1.1 christos # THREAD can be either a CLI thread id (e.g. 2.3) or an MI thread id (e.g. 6).
57 1.1 christos
58 1.1 christos proc thread_is_running { mode thread } {
59 1.1 christos if { $mode != "non-stop" } {
60 1.1 christos return 0
61 1.1 christos }
62 1.1 christos
63 1.1 christos return [expr {
64 1.1 christos $thread == 1.3
65 1.1 christos || $thread == 2.3
66 1.1 christos || $thread == 3
67 1.1 christos || $thread == 6
68 1.1 christos }]
69 1.1 christos }
70 1.1 christos
71 1.1 christos # Make a regular expression to match the various inferior/thread/frame selection
72 1.1 christos # events for CLI.
73 1.1 christos #
74 1.1 christos # MODE can be either "all-stop" or "non-stop", indicating which one is currently
75 1.1 christos # in use.
76 1.1 christos # INF is the inferior number we are expecting GDB to switch to, or -1 if we are
77 1.1 christos # not expecting GDB to announce an inferior switch.
78 1.1 christos # THREAD is the thread number we are expecting GDB to switch to, or -1 if we are
79 1.1 christos # not expecting GDB to announce a thread switch.
80 1.1 christos # FRAME is the frame number we are expecting GDB to switch to, or -1 if we are
81 1.1 christos # not expecting GDB to announce a frame switch. See the FRAME_RE variable for
82 1.1 christos # details.
83 1.1 christos
84 1.1 christos proc make_cli_re { mode inf thread frame } {
85 1.1 christos global srcfile
86 1.1 christos global thread_caller_line
87 1.1 christos global thread_loop_line
88 1.1 christos global main_break_line
89 1.1 christos global decimal
90 1.1 christos
91 1.1 christos set any "\[^\r\n\]*"
92 1.1 christos
93 1.1 christos set cli_re ""
94 1.1 christos
95 1.1 christos set inf_re "\\\[Switching to inferior $inf${any}\\\]"
96 1.1 christos set all_stop_thread_re "\\\[Switching to thread [string_to_regexp $thread]${any}\\\]"
97 1.1 christos
98 1.1 christos set frame_re(0) "#0${any}child_sub_function$any$srcfile:$thread_loop_line\r\n${any}thread loop line \\\*/"
99 1.1 christos set frame_re(1) "#1${any}child_function \\\(args=0x0\\\) at ${any}$srcfile:$thread_caller_line\r\n$thread_caller_line${any}/\\\* thread caller line \\\*/"
100 1.1 christos
101 1.1 christos # Special frame for main thread.
102 1.1 christos set frame_re(2) "#0${any}\r\n${main_break_line}${any}"
103 1.1 christos
104 1.1 christos if { $inf != -1 } {
105 1.1 christos append cli_re $inf_re
106 1.1 christos }
107 1.1 christos
108 1.1 christos if { $thread != -1 } {
109 1.1 christos if { $inf != -1 } {
110 1.1 christos append cli_re "\r\n"
111 1.1 christos }
112 1.1 christos set thread_re $all_stop_thread_re
113 1.1 christos
114 1.1 christos if [thread_is_running $mode $thread] {
115 1.1 christos set thread_re "$thread_re\\\(running\\\)"
116 1.1 christos }
117 1.1 christos
118 1.1 christos append cli_re $thread_re
119 1.1 christos }
120 1.1 christos
121 1.1 christos if { $frame != -1 } {
122 1.1 christos if { $thread != -1 } {
123 1.1 christos append cli_re "\r\n"
124 1.1 christos }
125 1.1 christos append cli_re $frame_re($frame)
126 1.1 christos }
127 1.1 christos
128 1.1 christos return $cli_re
129 1.1 christos }
130 1.1 christos
131 1.1 christos # Make a regular expression to match the various inferior/thread/frame selection
132 1.1 christos # events for MI.
133 1.1 christos #
134 1.1 christos # MODE can be either "all-stop" or "non-stop", indicating which one is currently
135 1.1 christos # in use.
136 1.1 christos # THREAD is the thread number we are expecting GDB to switch to, or -1 if we are
137 1.1 christos # not expecting GDB to announce a thread switch.
138 1.1 christos # If EVENT is 1, build a regex for an "=thread-selected" async event.
139 1.1 christos # Otherwise, build a regex for a response to a command.
140 1.1 christos # FRAME is the frame number we are expecting GDB to switch to, or -1 if we are
141 1.1 christos # not expecting GDB to announce a frame switch. See the FRAME_RE variable for
142 1.1 christos # details.
143 1.1 christos
144 1.1 christos proc make_mi_re { mode thread frame type } {
145 1.1 christos global srcfile
146 1.1 christos global hex
147 1.1 christos global decimal
148 1.1 christos global thread_loop_line
149 1.1 christos global main_break_line
150 1.1 christos global thread_caller_line
151 1.1 christos
152 1.1 christos set any "\[^\r\n\]*"
153 1.1 christos
154 1.1 christos set mi_re ""
155 1.1 christos
156 1.1 christos set thread_event_re "=thread-selected,id=\"$thread\""
157 1.1 christos set thread_answer_re "\\^done,new-thread-id=\"$thread\""
158 1.1 christos
159 1.1.1.3 christos set frame_re(0) ",frame=\{level=\"0\",addr=\"$hex\",func=\"child_sub_function\",args=\\\[\\\],file=\"${any}${srcfile}\",fullname=\"${any}${srcfile}\",line=\"$thread_loop_line\",arch=\"$any\"\}"
160 1.1.1.3 christos set frame_re(1) ",frame=\{level=\"1\",addr=\"$hex\",func=\"child_function\",args=\\\[\{name=\"args\",value=\"0x0\"\}\\\],file=\"${any}${srcfile}\",fullname=\"${any}${srcfile}\",line=\"$thread_caller_line\",arch=\"$any\"\}"
161 1.1 christos
162 1.1 christos # Special frame for main thread.
163 1.1.1.3 christos set frame_re(2) ",frame=\{level=\"0\",addr=\"$hex\",func=\"main\",args=\\\[\\\],file=\"${any}${srcfile}\",fullname=\"${any}${srcfile}\",line=\"${main_break_line}\",arch=\"$any\"\}"
164 1.1 christos
165 1.1 christos if { $thread != -1 } {
166 1.1 christos if { $type == "event" } {
167 1.1 christos append mi_re $thread_event_re
168 1.1 christos } elseif { $type == "response" } {
169 1.1 christos append mi_re $thread_answer_re
170 1.1 christos } else {
171 1.1 christos error "Invalid value for EVENT."
172 1.1 christos }
173 1.1 christos }
174 1.1 christos
175 1.1 christos if { $frame != -1 } {
176 1.1 christos append mi_re $frame_re($frame)
177 1.1 christos }
178 1.1 christos
179 1.1 christos if { $type == "event" } {
180 1.1 christos append mi_re "\r\n"
181 1.1 christos }
182 1.1 christos
183 1.1 christos return $mi_re
184 1.1 christos }
185 1.1 christos
186 1.1 christos # Make a regular expression to match the various inferior/thread/frame selection
187 1.1 christos # events when issuing CLI commands inside MI.
188 1.1 christos #
189 1.1 christos # COMMAND is the CLI command that was sent to GDB, which will be output in the
190 1.1 christos # console output stream.
191 1.1 christos # CLI_IN_MI_MODE indicates which method of CLI-in-MI command is used. It can be
192 1.1 christos # either "direct" of "interpreter-exec".
193 1.1 christos # MODE can be either "all-stop" or "non-stop", indicating which one is currently
194 1.1 christos # in use.
195 1.1 christos # If EVENT is 1, expect a =thread-select MI event.
196 1.1 christos # INF is the inferior number we are expecting GDB to switch to, or -1 if we are
197 1.1 christos # not expecting GDB to announce an inferior switch.
198 1.1 christos # CLI_THREAD is the thread number as seen in the CLI (inferior-qualified) we are
199 1.1 christos # expecting GDB to switch to, or -1 if we are not expecting GDB to announce a
200 1.1 christos # thread switch.
201 1.1 christos # MI_THREAD is the thread number as seen in the MI (global number) we are
202 1.1 christos # expecting GDB to switch to, or -1 if we are not expecting GDB to announce a
203 1.1 christos # thread switch.
204 1.1 christos # FRAME is the frame number we are expecting GDB to switch to, or -1 if we are
205 1.1 christos # not expecting GDB to announce a frame switch. See the FRAME_RE variable for
206 1.1 christos # details.
207 1.1 christos
208 1.1 christos proc make_cli_in_mi_re { command cli_in_mi_mode mode event inf cli_thread
209 1.1 christos mi_thread frame } {
210 1.1 christos global srcfile
211 1.1 christos global thread_loop_line
212 1.1 christos global main_break_line
213 1.1 christos global thread_caller_line
214 1.1 christos
215 1.1 christos set any "\[^\r\n\]*"
216 1.1 christos
217 1.1 christos set command_re [string_to_regexp $command]
218 1.1 christos set cli_in_mi_re "$command_re\r\n"
219 1.1 christos
220 1.1 christos if { $cli_in_mi_mode == "direct" } {
221 1.1 christos append cli_in_mi_re "&\"$command_re\\\\n\"\r\n"
222 1.1 christos }
223 1.1 christos
224 1.1 christos set frame_re(0) "~\"#0${any}child_sub_function${any}$srcfile:$thread_loop_line\\\\n\"\r\n~\"${thread_loop_line}${any}thread loop line \\\*/\\\\n\"\r\n"
225 1.1 christos set frame_re(1) "~\"#1${any}child_function \\\(args=0x0\\\) at ${any}$srcfile:$thread_caller_line\\\\n\"\r\n~\"$thread_caller_line${any}thread caller line \\\*/\\\\n\"\r\n"
226 1.1 christos
227 1.1 christos # Special frame for main thread.
228 1.1 christos set frame_re(2) "~\"#0${any}main${any}\\\\n\"\r\n~\"${main_break_line}${any}\"\r\n"
229 1.1 christos
230 1.1 christos if { $inf != -1 } {
231 1.1 christos append cli_in_mi_re "~\""
232 1.1 christos append cli_in_mi_re [make_cli_re $mode $inf -1 -1]
233 1.1 christos append cli_in_mi_re "\\\\n\"\r\n"
234 1.1 christos }
235 1.1 christos
236 1.1 christos if { $cli_thread != "-1" } {
237 1.1 christos append cli_in_mi_re "~\""
238 1.1 christos append cli_in_mi_re [make_cli_re $mode -1 $cli_thread -1]
239 1.1 christos append cli_in_mi_re "\\\\n\"\r\n"
240 1.1 christos }
241 1.1 christos
242 1.1 christos if { $frame != -1 } {
243 1.1 christos append cli_in_mi_re $frame_re($frame)
244 1.1 christos }
245 1.1 christos
246 1.1 christos if { $event == 1 } {
247 1.1 christos append cli_in_mi_re [make_mi_re $mode $mi_thread $frame event]
248 1.1 christos }
249 1.1 christos
250 1.1 christos append cli_in_mi_re "\\^done"
251 1.1 christos
252 1.1 christos return $cli_in_mi_re
253 1.1 christos }
254 1.1 christos
255 1.1 christos # Return the current value of the "scheduler-locking" parameter.
256 1.1 christos
257 1.1 christos proc show_scheduler_locking { } {
258 1.1 christos global gdb_prompt
259 1.1 christos global expect_out
260 1.1 christos
261 1.1 christos set any "\[^\r\n\]*"
262 1.1 christos
263 1.1 christos set test "show scheduler-locking"
264 1.1 christos gdb_test_multiple $test $test {
265 1.1 christos -re ".*Mode for locking scheduler during execution is \"(${any})\".\r\n$gdb_prompt " {
266 1.1 christos pass $test
267 1.1 christos return $expect_out(1,string)
268 1.1 christos }
269 1.1 christos }
270 1.1 christos
271 1.1 christos error "Couldn't get current scheduler-locking value."
272 1.1 christos }
273 1.1 christos
274 1.1 christos # Prepare inferior INF so it is in the state we expect (see comment at the top).
275 1.1 christos
276 1.1 christos proc test_continue_to_start { mode inf } {
277 1.1 christos global gdb_spawn_id
278 1.1 christos global mi_spawn_id
279 1.1 christos global gdb_main_spawn_id
280 1.1 christos global srcfile
281 1.1 christos global main_break_line
282 1.1 christos global thread_loop_line
283 1.1 christos global decimal
284 1.1 christos global gdb_prompt
285 1.1 christos
286 1.1 christos set any "\[^\r\n\]*"
287 1.1 christos
288 1.1 christos if { $gdb_spawn_id != $gdb_main_spawn_id } {
289 1.1 christos error "This should not happen."
290 1.1 christos }
291 1.1 christos
292 1.1 christos with_test_prefix "inferior $inf" {
293 1.1 christos with_spawn_id $gdb_main_spawn_id {
294 1.1 christos # Continue to the point where we know for sure the threads are
295 1.1 christos # started.
296 1.1 christos gdb_test "tbreak $srcfile:$main_break_line" \
297 1.1 christos "Temporary breakpoint ${any}" \
298 1.1 christos "set breakpoint in main"
299 1.1 christos
300 1.1 christos gdb_continue_to_breakpoint "main breakpoint"
301 1.1 christos
302 1.1 christos # Consume MI event output.
303 1.1 christos with_spawn_id $mi_spawn_id {
304 1.1.1.5 christos if { $inf == 1 } {
305 1.1.1.5 christos mi_expect_stop "breakpoint-hit" "main" "" "$srcfile" \
306 1.1.1.5 christos "$decimal" {"" "disp=\"del\""} "stop at breakpoint in main"
307 1.1.1.5 christos } else {
308 1.1.1.5 christos mi_expect_stop "breakpoint-hit" "main" "" "$srcfile" \
309 1.1.1.5 christos "$decimal" {"" "disp=\"del\"" "locno=\"[0-9]+\""} "stop at breakpoint in main"
310 1.1.1.5 christos }
311 1.1 christos }
312 1.1 christos
313 1.1 christos if { $mode == "all-stop" } {
314 1.1 christos set previous_schedlock_val [show_scheduler_locking]
315 1.1 christos
316 1.1 christos # Set scheduler-locking on, so that we can control threads
317 1.1 christos # independently.
318 1.1 christos gdb_test_no_output "set scheduler-locking on"
319 1.1 christos
320 1.1 christos # Continue each child thread to the point we want them to be.
321 1.1 christos foreach thread { 2 3 } {
322 1.1 christos gdb_test "thread $inf.$thread" ".*" "select child thread $inf.$thread"
323 1.1 christos
324 1.1 christos gdb_test "tbreak $srcfile:$thread_loop_line" \
325 1.1 christos "Temporary breakpoint ${any}" \
326 1.1 christos "set breakpoint for thread $inf.$thread"
327 1.1 christos
328 1.1 christos gdb_continue_to_breakpoint "continue thread $inf.$thread to infinite loop breakpoint"
329 1.1 christos
330 1.1 christos # Consume MI output.
331 1.1 christos with_spawn_id $mi_spawn_id {
332 1.1.1.5 christos if { $inf == 1} {
333 1.1.1.5 christos mi_expect_stop "breakpoint-hit" "child_sub_function" \
334 1.1.1.5 christos "" "$srcfile" "$decimal" {"" "disp=\"del\""} \
335 1.1.1.5 christos "thread $inf.$thread stops MI"
336 1.1.1.5 christos } else {
337 1.1.1.5 christos mi_expect_stop "breakpoint-hit" "child_sub_function" \
338 1.1.1.5 christos "" "$srcfile" "$decimal" {"" "disp=\"del\"" "locno=\"[0-9]+\""} \
339 1.1.1.5 christos "thread $inf.$thread stops MI"
340 1.1.1.5 christos }
341 1.1 christos }
342 1.1 christos }
343 1.1 christos
344 1.1 christos # Restore scheduler-locking to its original value.
345 1.1 christos gdb_test_no_output "set scheduler-locking $previous_schedlock_val"
346 1.1 christos } else { # $mode == "non-stop"
347 1.1 christos # Put a thread-specific breakpoint for thread 2 of the current
348 1.1 christos # inferior. We don't put a breakpoint for thread 3, since we
349 1.1 christos # want to let it run.
350 1.1 christos set test "set thread-specific breakpoint, thread $inf.2"
351 1.1 christos gdb_test_multiple "tbreak $srcfile:$thread_loop_line thread $inf.2" $test {
352 1.1 christos -re "Temporary breakpoint ${any}\r\n$gdb_prompt " {
353 1.1 christos pass $test
354 1.1 christos }
355 1.1 christos }
356 1.1 christos
357 1.1 christos # Confirm the stop of thread $inf.2.
358 1.1 christos set test "thread $inf.2 stops CLI"
359 1.1 christos gdb_test_multiple "" $test {
360 1.1 christos -re "Thread $inf.2 ${any} hit Temporary breakpoint ${any}\r\n$thread_loop_line${any}\r\n" {
361 1.1 christos pass $test
362 1.1 christos }
363 1.1 christos }
364 1.1 christos
365 1.1 christos # Consume MI output.
366 1.1 christos with_spawn_id $mi_spawn_id {
367 1.1.1.7 christos mi_expect_stop "breakpoint-hit" "child_sub_function" \
368 1.1.1.7 christos "" "$srcfile" "$decimal" {"" "disp=\"del\""} \
369 1.1.1.7 christos "thread $inf.2 stops MI"
370 1.1 christos }
371 1.1 christos }
372 1.1 christos }
373 1.1 christos }
374 1.1 christos }
375 1.1 christos
376 1.1 christos # Prepare the test environment.
377 1.1 christos #
378 1.1 christos # MODE can be either "all-stop" or "non-stop".
379 1.1 christos
380 1.1.1.2 christos proc_with_prefix test_setup { mode } {
381 1.1 christos global srcfile
382 1.1 christos global srcdir
383 1.1 christos global subdir
384 1.1 christos global gdb_main_spawn_id
385 1.1 christos global mi_spawn_id
386 1.1 christos global decimal
387 1.1 christos global binfile
388 1.1 christos global GDBFLAGS
389 1.1 christos global async
390 1.1 christos
391 1.1 christos set any "\[^\r\n\]*"
392 1.1 christos
393 1.1 christos save_vars { GDBFLAGS } {
394 1.1 christos if { $mode == "non-stop" } {
395 1.1 christos set GDBFLAGS [concat $GDBFLAGS " -ex \"set non-stop 1\""]
396 1.1 christos }
397 1.1 christos
398 1.1.1.6 christos if { [mi_clean_restart $binfile "separate-mi-tty"] != 0 } {
399 1.1.1.5 christos return -1
400 1.1 christos }
401 1.1 christos }
402 1.1 christos
403 1.1.1.5 christos if { [mi_runto_main] < 0 } {
404 1.1.1.5 christos return -1
405 1.1 christos }
406 1.1 christos
407 1.1 christos # When using mi_expect_stop, we don't expect a prompt after the *stopped
408 1.1 christos # event, since the blocking commands are done from the CLI. Setting async
409 1.1 christos # to 1 makes it not expect the prompt.
410 1.1 christos set async 1
411 1.1 christos
412 1.1 christos with_spawn_id $gdb_main_spawn_id {
413 1.1 christos # Add the second inferior now. While this is not mandatory, it allows
414 1.1 christos # us to assume that per-inferior thread numbering will be used,
415 1.1 christos # simplifying test_continue_to_start a bit (Thread 1.2 and not Thread 2).
416 1.1.1.4 christos gdb_test "add-inferior" "Added inferior 2 on connection .*" "add inferior 2"
417 1.1 christos
418 1.1 christos # Prepare the first inferior for the test.
419 1.1 christos test_continue_to_start $mode 1
420 1.1 christos
421 1.1 christos # Switch to and start the second inferior.
422 1.1 christos gdb_test "inferior 2" "\\\[Switching to inferior 2${any}\\\]" "switch to inferior 2"
423 1.1 christos gdb_load ${binfile}
424 1.1 christos
425 1.1 christos # Doing "start" on the CLI generates a ton of MI output. At some point,
426 1.1 christos # if we don't consume/match it, the buffer between GDB's MI channel and
427 1.1 christos # Expect will get full, GDB will block on a write system call and we'll
428 1.1 christos # deadlock, waiting for CLI output that will never arrive. And then
429 1.1 christos # we're sad. So instead of using gdb_test and expect CLI output, send
430 1.1 christos # the start command first, then consume MI output, and finally consume
431 1.1 christos # CLI output.
432 1.1 christos send_gdb "start\n"
433 1.1 christos
434 1.1 christos with_spawn_id $mi_spawn_id {
435 1.1 christos mi_expect_stop "breakpoint-hit" "main" "" "$srcfile" "$decimal" \
436 1.1.1.7 christos {"" "disp=\"del\""} "main stop"
437 1.1 christos }
438 1.1 christos
439 1.1 christos # Consume CLI output.
440 1.1 christos gdb_test "" "Temporary breakpoint.*Starting program.*"
441 1.1 christos
442 1.1 christos # Prepare the second inferior for the test.
443 1.1 christos test_continue_to_start $mode 2
444 1.1 christos }
445 1.1.1.5 christos
446 1.1.1.5 christos return 0
447 1.1 christos }
448 1.1 christos
449 1.1 christos # Reset the selection to frame #0 of thread THREAD.
450 1.1 christos
451 1.1 christos proc reset_selection { thread } {
452 1.1 christos global gdb_main_spawn_id
453 1.1 christos
454 1.1 christos set any "\[^\r\n\]*"
455 1.1 christos
456 1.1 christos with_spawn_id $gdb_main_spawn_id {
457 1.1 christos gdb_test "thread $thread" \
458 1.1 christos "\\\[Switching to thread $thread ${any}\\\].*" \
459 1.1 christos "reset selection to thread $thread"
460 1.1 christos gdb_test "frame 0" ".*" "reset selection to frame 0"
461 1.1 christos }
462 1.1 christos }
463 1.1 christos
464 1.1 christos # Flush Expect's internal buffers for both CLI and MI.
465 1.1 christos #
466 1.1 christos # The idea here is to send a command, and to consume all the characters that we
467 1.1 christos # expect that command to output, including the following prompt. Using gdb_test
468 1.1 christos # and mi_gdb_test should do that.
469 1.1 christos
470 1.1 christos proc flush_buffers { } {
471 1.1 christos global gdb_main_spawn_id mi_spawn_id
472 1.1 christos
473 1.1 christos with_spawn_id $gdb_main_spawn_id {
474 1.1 christos gdb_test "print 444" "= 444" "flush CLI"
475 1.1 christos }
476 1.1 christos
477 1.1 christos with_spawn_id $mi_spawn_id {
478 1.1 christos mi_gdb_test "555-data-evaluate-expression 666" ".*done,value=\"666\"" "flush MI"
479 1.1 christos }
480 1.1 christos }
481 1.1 christos
482 1.1 christos # Run a command on the current spawn id, to confirm that no output is pending
483 1.1 christos # in Expect's internal buffer. This is used to ensure that nothing was output
484 1.1 christos # on the spawn id since the call to gdb_test/mi_gdb_test/flush_buffers.
485 1.1 christos #
486 1.1 christos # The key here is that the regexes use start-of-buffer anchors (^), ensuring
487 1.1 christos # that they match the entire buffer, confirming that there was nothing in it
488 1.1 christos # before.
489 1.1 christos
490 1.1 christos proc ensure_no_output { test } {
491 1.1 christos global gdb_spawn_id gdb_main_spawn_id mi_spawn_id
492 1.1 christos global decimal
493 1.1 christos
494 1.1 christos if { $gdb_spawn_id == $gdb_main_spawn_id } {
495 1.1 christos # CLI
496 1.1 christos gdb_test "print 666" \
497 1.1.1.6 christos "^\\\$$decimal = 666" \
498 1.1 christos "$test, ensure no output CLI"
499 1.1 christos } elseif { $gdb_spawn_id == $mi_spawn_id } {
500 1.1 christos # MI
501 1.1 christos mi_gdb_test "777-data-evaluate-expression 888" \
502 1.1 christos "^777-data-evaluate-expression 888\r\n777\\^done,value=\"888\"" \
503 1.1 christos "$test, ensure no output MI"
504 1.1 christos } else {
505 1.1 christos error "Unexpected gdb_spawn_id value."
506 1.1 christos }
507 1.1 christos }
508 1.1 christos
509 1.1 christos # Match a regular expression, or ensure that there was no output.
510 1.1 christos #
511 1.1 christos # If RE is non-empty, try to match the content of the program output (using the
512 1.1 christos # current spawn_id) and pass/fail TEST accordingly.
513 1.1 christos # If RE is empty, ensure that the program did not output anything.
514 1.1 christos
515 1.1.1.5 christos proc match_re_or_ensure_no_output { re test } {
516 1.1 christos if { $re != "" } {
517 1.1 christos gdb_expect {
518 1.1 christos -re "$re" {
519 1.1 christos pass $test
520 1.1 christos }
521 1.1 christos
522 1.1 christos default {
523 1.1 christos fail $test
524 1.1 christos }
525 1.1 christos }
526 1.1 christos } else {
527 1.1 christos ensure_no_output $test
528 1.1 christos }
529 1.1 christos }
530 1.1 christos
531 1.1 christos # Test selecting an inferior from CLI.
532 1.1 christos
533 1.1.1.2 christos proc_with_prefix test_cli_inferior { mode } {
534 1.1 christos global gdb_main_spawn_id mi_spawn_id
535 1.1 christos
536 1.1 christos reset_selection "1.1"
537 1.1 christos
538 1.1 christos set mi_re [make_mi_re $mode 4 2 event]
539 1.1 christos set cli_re [make_cli_re $mode 2 2.1 2]
540 1.1 christos
541 1.1 christos flush_buffers
542 1.1 christos
543 1.1 christos # Do the 'inferior' command.
544 1.1 christos with_spawn_id $gdb_main_spawn_id {
545 1.1 christos gdb_test "inferior 2" $cli_re "CLI select inferior"
546 1.1 christos }
547 1.1 christos
548 1.1 christos with_spawn_id $mi_spawn_id {
549 1.1.1.5 christos match_re_or_ensure_no_output $mi_re "event on MI"
550 1.1 christos }
551 1.1 christos
552 1.1 christos # Do the 'inferior' command on the currently selected inferior. For now,
553 1.1 christos # GDB naively re-outputs everything.
554 1.1 christos with_spawn_id $gdb_main_spawn_id {
555 1.1 christos gdb_test "inferior 2" $cli_re "CLI select inferior again"
556 1.1 christos }
557 1.1 christos
558 1.1 christos with_spawn_id $mi_spawn_id {
559 1.1.1.5 christos match_re_or_ensure_no_output $mi_re "event on MI again"
560 1.1 christos }
561 1.1 christos }
562 1.1 christos
563 1.1 christos # Test thread selection from CLI.
564 1.1 christos
565 1.1.1.2 christos proc_with_prefix test_cli_thread { mode } {
566 1.1 christos global gdb_main_spawn_id
567 1.1 christos global mi_spawn_id
568 1.1 christos
569 1.1 christos set any "\[^\r\n\]*"
570 1.1 christos
571 1.1 christos reset_selection "1.1"
572 1.1 christos flush_buffers
573 1.1 christos
574 1.1 christos with_test_prefix "thread 1.2" {
575 1.1 christos # Do the 'thread' command to select a stopped thread.
576 1.1 christos
577 1.1 christos set mi_re [make_mi_re $mode 2 0 event]
578 1.1 christos set cli_re [make_cli_re $mode -1 1.2 0]
579 1.1 christos
580 1.1 christos with_spawn_id $gdb_main_spawn_id {
581 1.1 christos gdb_test "thread 1.2" $cli_re "select thread"
582 1.1 christos }
583 1.1 christos
584 1.1 christos with_spawn_id $mi_spawn_id {
585 1.1.1.5 christos match_re_or_ensure_no_output $mi_re "select thread, event on MI "
586 1.1 christos }
587 1.1 christos
588 1.1 christos # Do the 'thread' command to select the same thread. We shouldn't receive
589 1.1 christos # an event on MI, since we won't actually switch thread.
590 1.1 christos
591 1.1 christos set mi_re ""
592 1.1 christos
593 1.1 christos with_spawn_id $gdb_main_spawn_id {
594 1.1 christos gdb_test "thread 1.2" $cli_re "select thread again"
595 1.1 christos }
596 1.1 christos
597 1.1 christos with_spawn_id $mi_spawn_id {
598 1.1.1.5 christos match_re_or_ensure_no_output $mi_re "select thread, event on MI again"
599 1.1 christos }
600 1.1 christos
601 1.1 christos # Try the 'thread' command without arguments.
602 1.1 christos
603 1.1 christos set cli_re "\\\[Current thread is 1\\.2.*\\\]"
604 1.1 christos set mi_re ""
605 1.1 christos
606 1.1 christos with_spawn_id $gdb_main_spawn_id {
607 1.1 christos gdb_test "thread" $cli_re "thread without args"
608 1.1 christos }
609 1.1 christos
610 1.1 christos with_spawn_id $mi_spawn_id {
611 1.1.1.5 christos match_re_or_ensure_no_output $mi_re "thread without args, event on MI"
612 1.1 christos }
613 1.1 christos }
614 1.1 christos
615 1.1 christos with_test_prefix "thread 1.3" {
616 1.1 christos # Do the 'thread' command to select the third thread, stopped on all-stop,
617 1.1 christos # running on non-stop.
618 1.1 christos
619 1.1 christos if { $mode == "all-stop" } {
620 1.1 christos set cli_re [make_cli_re $mode -1 1.3 0]
621 1.1 christos set mi_re [make_mi_re $mode 3 0 event]
622 1.1 christos } else {
623 1.1 christos set cli_re [make_cli_re $mode -1 1.3 -1]
624 1.1 christos set mi_re [make_mi_re $mode 3 -1 event]
625 1.1 christos }
626 1.1 christos
627 1.1 christos with_spawn_id $gdb_main_spawn_id {
628 1.1 christos gdb_test "thread 1.3" $cli_re "select thread"
629 1.1 christos }
630 1.1 christos
631 1.1 christos with_spawn_id $mi_spawn_id {
632 1.1.1.5 christos match_re_or_ensure_no_output $mi_re "select thread, event on MI"
633 1.1 christos }
634 1.1 christos
635 1.1 christos # Do the 'thread' command to select the third thread again. Again, we
636 1.1 christos # shouldn't receive an event on MI.
637 1.1 christos
638 1.1 christos set mi_re ""
639 1.1 christos
640 1.1 christos with_spawn_id $gdb_main_spawn_id {
641 1.1 christos gdb_test "thread 1.3" $cli_re "select thread again"
642 1.1 christos }
643 1.1 christos
644 1.1 christos with_spawn_id $mi_spawn_id {
645 1.1.1.5 christos match_re_or_ensure_no_output $mi_re "select thread again, event on MI"
646 1.1 christos }
647 1.1 christos
648 1.1 christos # Try the 'thread' command without arguments.
649 1.1 christos
650 1.1 christos set cli_re "\\\[Current thread is 1\\.3 ${any}\\\]"
651 1.1 christos set mi_re ""
652 1.1 christos
653 1.1 christos with_spawn_id $gdb_main_spawn_id {
654 1.1 christos gdb_test "thread" $cli_re "thread without args"
655 1.1 christos }
656 1.1 christos
657 1.1 christos with_spawn_id $mi_spawn_id {
658 1.1.1.5 christos match_re_or_ensure_no_output $mi_re "thread without args, event on MI"
659 1.1 christos }
660 1.1 christos }
661 1.1 christos
662 1.1 christos # Idea for the future: selecting a thread in a different inferior. For now,
663 1.1 christos # GDB doesn't show an inferior switch, but if it did, it would be a nice
664 1.1 christos # place to test it.
665 1.1 christos }
666 1.1 christos
667 1.1 christos # Test frame selection from CLI.
668 1.1 christos
669 1.1.1.2 christos proc_with_prefix test_cli_frame { mode } {
670 1.1 christos global gdb_main_spawn_id mi_spawn_id
671 1.1 christos
672 1.1 christos with_test_prefix "thread 1.2" {
673 1.1 christos reset_selection "1.2"
674 1.1 christos flush_buffers
675 1.1 christos
676 1.1 christos # Do the 'frame' command to select frame 1.
677 1.1 christos
678 1.1 christos set mi_re [make_mi_re $mode 2 1 event]
679 1.1 christos set cli_re [make_cli_re $mode -1 -1 1]
680 1.1 christos
681 1.1 christos with_spawn_id $gdb_main_spawn_id {
682 1.1 christos gdb_test "frame 1" $cli_re "select frame 1"
683 1.1 christos }
684 1.1 christos
685 1.1 christos with_spawn_id $mi_spawn_id {
686 1.1.1.5 christos match_re_or_ensure_no_output $mi_re "select frame 1, event on MI"
687 1.1 christos }
688 1.1 christos
689 1.1 christos # Do the 'frame' command to select the same frame. This time we don't
690 1.1 christos # expect an event on MI, since we won't actually change frame.
691 1.1 christos
692 1.1 christos set mi_re ""
693 1.1 christos
694 1.1 christos with_spawn_id $gdb_main_spawn_id {
695 1.1 christos gdb_test "frame 1" $cli_re "select frame 1 again"
696 1.1 christos }
697 1.1 christos
698 1.1 christos with_spawn_id $mi_spawn_id {
699 1.1.1.5 christos match_re_or_ensure_no_output $mi_re "select frame 1 again, event on MI"
700 1.1 christos }
701 1.1 christos
702 1.1 christos # Do the 'frame' command without arguments. We shouldn't see anything on MI.
703 1.1 christos
704 1.1 christos with_spawn_id $gdb_main_spawn_id {
705 1.1 christos gdb_test "frame" $cli_re "frame without args"
706 1.1 christos }
707 1.1 christos
708 1.1 christos with_spawn_id $mi_spawn_id {
709 1.1.1.5 christos match_re_or_ensure_no_output $mi_re "frame without args, event on MI"
710 1.1 christos }
711 1.1 christos }
712 1.1 christos
713 1.1 christos with_test_prefix "thread 1.3" {
714 1.1 christos # Now, try the 'frame' command on thread 3, which is running if we are in
715 1.1 christos # non-stop mode.
716 1.1 christos reset_selection "1.3"
717 1.1 christos flush_buffers
718 1.1 christos
719 1.1 christos if {$mode == "all-stop"} {
720 1.1 christos set mi_re [make_mi_re $mode 3 1 event]
721 1.1 christos set cli_re [make_cli_re $mode -1 -1 1]
722 1.1 christos } elseif {$mode == "non-stop"} {
723 1.1 christos set mi_re ""
724 1.1 christos set cli_re "Selected thread is running\\."
725 1.1 christos }
726 1.1 christos
727 1.1 christos with_spawn_id $gdb_main_spawn_id {
728 1.1 christos gdb_test "frame 1" $cli_re "select frame 1"
729 1.1 christos }
730 1.1 christos
731 1.1 christos with_spawn_id $mi_spawn_id {
732 1.1.1.5 christos match_re_or_ensure_no_output $mi_re "select frame 1, event on MI"
733 1.1 christos }
734 1.1 christos
735 1.1 christos # Do the 'frame' command without arguments.
736 1.1 christos
737 1.1 christos if { $mode == "non-stop" } {
738 1.1 christos set cli_re "No stack\\."
739 1.1 christos }
740 1.1 christos set mi_re ""
741 1.1 christos
742 1.1 christos with_spawn_id $gdb_main_spawn_id {
743 1.1 christos gdb_test "frame" $cli_re "frame without args"
744 1.1 christos }
745 1.1 christos
746 1.1 christos with_spawn_id $mi_spawn_id {
747 1.1.1.5 christos match_re_or_ensure_no_output $mi_re "frame without args, event on MI"
748 1.1 christos }
749 1.1 christos }
750 1.1 christos }
751 1.1 christos
752 1.1 christos # Test frame selection from CLI with the select-frame command.
753 1.1 christos
754 1.1.1.2 christos proc_with_prefix test_cli_select_frame { mode } {
755 1.1 christos global gdb_main_spawn_id mi_spawn_id expect_out
756 1.1 christos
757 1.1 christos with_test_prefix "thread 1.2" {
758 1.1 christos reset_selection "1.2"
759 1.1 christos flush_buffers
760 1.1 christos
761 1.1 christos # Do the 'select-frame' command to select frame 1.
762 1.1 christos
763 1.1 christos set mi_re [make_mi_re $mode 2 1 event]
764 1.1 christos
765 1.1 christos with_spawn_id $gdb_main_spawn_id {
766 1.1 christos gdb_test_no_output "select-frame 1" "select frame 1"
767 1.1 christos }
768 1.1 christos
769 1.1 christos with_spawn_id $mi_spawn_id {
770 1.1.1.5 christos match_re_or_ensure_no_output $mi_re "select frame 1, event on MI"
771 1.1 christos }
772 1.1 christos
773 1.1 christos # Do the 'select-frame' command to select the same frame. This time we expect to
774 1.1 christos # event on MI, since we won't actually change frame.
775 1.1 christos
776 1.1 christos set mi_re ""
777 1.1 christos
778 1.1 christos with_spawn_id $gdb_main_spawn_id {
779 1.1 christos gdb_test_no_output "select-frame 1" "select frame 1 again"
780 1.1 christos }
781 1.1 christos
782 1.1 christos with_spawn_id $mi_spawn_id {
783 1.1.1.5 christos match_re_or_ensure_no_output $mi_re "select frame 1 again, event on MI"
784 1.1 christos }
785 1.1 christos }
786 1.1 christos
787 1.1 christos with_test_prefix "thread 1.3" {
788 1.1 christos # Now, try the 'select-frame' command on thread 3, which is running if we are in
789 1.1 christos # non-stop mode.
790 1.1 christos reset_selection "1.3"
791 1.1 christos flush_buffers
792 1.1 christos
793 1.1 christos if {$mode == "all-stop"} {
794 1.1 christos set mi_re [make_mi_re $mode 3 1 event]
795 1.1 christos } elseif {$mode == "non-stop"} {
796 1.1 christos set mi-re ""
797 1.1 christos set cli_re "Selected thread is running\\."
798 1.1 christos }
799 1.1 christos
800 1.1 christos with_spawn_id $gdb_main_spawn_id {
801 1.1 christos if { $mode == "all-stop" } {
802 1.1 christos gdb_test_no_output "select-frame 1" "select frame 1"
803 1.1 christos } else {
804 1.1 christos gdb_test "select-frame 1" $cli_re "select frame 1"
805 1.1 christos }
806 1.1 christos }
807 1.1 christos
808 1.1 christos with_spawn_id $mi_spawn_id {
809 1.1.1.5 christos match_re_or_ensure_no_output $mi_re "select frame 1, event on MI"
810 1.1 christos }
811 1.1 christos }
812 1.1 christos }
813 1.1 christos
814 1.1 christos # Test doing an up and then down command from CLI.
815 1.1 christos
816 1.1.1.2 christos proc_with_prefix test_cli_up_down { mode } {
817 1.1 christos global gdb_main_spawn_id mi_spawn_id
818 1.1 christos
819 1.1 christos reset_selection "1.2"
820 1.1 christos flush_buffers
821 1.1 christos
822 1.1 christos # Try doing an 'up'.
823 1.1 christos
824 1.1 christos set mi_re [make_mi_re $mode 2 1 event]
825 1.1 christos set cli_re [make_cli_re $mode -1 -1 1]
826 1.1 christos
827 1.1 christos with_spawn_id $gdb_main_spawn_id {
828 1.1 christos gdb_test "up" $cli_re "frame up"
829 1.1 christos }
830 1.1 christos
831 1.1 christos with_spawn_id $mi_spawn_id {
832 1.1.1.5 christos match_re_or_ensure_no_output $mi_re "frame up, event on MI"
833 1.1 christos }
834 1.1 christos
835 1.1 christos # Try doing a 'down'.
836 1.1 christos
837 1.1 christos set mi_re [make_mi_re $mode 2 0 event]
838 1.1 christos set cli_re [make_cli_re $mode -1 -1 0]
839 1.1 christos
840 1.1 christos with_spawn_id $gdb_main_spawn_id {
841 1.1 christos gdb_test "down" $cli_re "frame down"
842 1.1 christos }
843 1.1 christos
844 1.1 christos with_spawn_id $mi_spawn_id {
845 1.1.1.5 christos match_re_or_ensure_no_output $mi_re "frame down, event on MI"
846 1.1 christos }
847 1.1 christos }
848 1.1 christos
849 1.1 christos # Test selecting a thread from MI.
850 1.1 christos
851 1.1.1.2 christos proc_with_prefix test_mi_thread_select { mode } {
852 1.1 christos global gdb_main_spawn_id mi_spawn_id
853 1.1 christos
854 1.1 christos reset_selection "1.1"
855 1.1 christos flush_buffers
856 1.1 christos
857 1.1 christos with_test_prefix "thread 1.2" {
858 1.1 christos # Do the '-thread-select' command to select a stopped thread.
859 1.1 christos
860 1.1 christos set mi_re [make_mi_re $mode 2 0 response]
861 1.1 christos set cli_re [make_cli_re $mode -1 1.2 0]
862 1.1 christos
863 1.1 christos with_spawn_id $mi_spawn_id {
864 1.1 christos mi_gdb_test "-thread-select 2" $mi_re "-thread-select"
865 1.1 christos }
866 1.1 christos
867 1.1 christos with_spawn_id $gdb_main_spawn_id {
868 1.1.1.5 christos match_re_or_ensure_no_output "$cli_re\r\n" "-thread-select, event on CLI"
869 1.1 christos }
870 1.1 christos
871 1.1 christos # Do the '-thread-select' command to select the same thread. We
872 1.1 christos # shouldn't receive an event on CLI, since we won't actually switch
873 1.1 christos # thread.
874 1.1 christos
875 1.1 christos set cli_re ""
876 1.1 christos
877 1.1 christos with_spawn_id $mi_spawn_id {
878 1.1 christos mi_gdb_test "-thread-select 2" $mi_re "-thread-select again"
879 1.1 christos }
880 1.1 christos
881 1.1 christos with_spawn_id $gdb_main_spawn_id {
882 1.1.1.5 christos match_re_or_ensure_no_output $cli_re "-thread-select again, event on CLI"
883 1.1 christos }
884 1.1 christos }
885 1.1 christos
886 1.1 christos with_test_prefix "thread 1.3" {
887 1.1 christos # Do the '-thread-select' command to select the third thread, stopped on all-stop,
888 1.1 christos # running on non-stop.
889 1.1 christos
890 1.1 christos if { $mode == "all-stop" } {
891 1.1 christos set mi_re [make_mi_re $mode 3 0 response]
892 1.1 christos set cli_re [make_cli_re $mode -1 1.3 0]
893 1.1 christos } else {
894 1.1 christos set mi_re [make_mi_re $mode 3 -1 response]
895 1.1 christos set cli_re [make_cli_re $mode -1 1.3 -1]
896 1.1 christos }
897 1.1 christos
898 1.1 christos with_spawn_id $mi_spawn_id {
899 1.1 christos mi_gdb_test "-thread-select 3" $mi_re "-thread-select"
900 1.1 christos }
901 1.1 christos
902 1.1 christos with_spawn_id $gdb_main_spawn_id {
903 1.1.1.5 christos match_re_or_ensure_no_output "$cli_re\r\n" "-thread-select, event on CLI"
904 1.1 christos }
905 1.1 christos
906 1.1 christos # Do the 'thread' command to select the third thread again. Again, we
907 1.1 christos # shouldn't receive an event on MI.
908 1.1 christos
909 1.1 christos set cli_re ""
910 1.1 christos
911 1.1 christos with_spawn_id $mi_spawn_id {
912 1.1 christos mi_gdb_test "-thread-select 3" $mi_re "-thread-select again"
913 1.1 christos }
914 1.1 christos
915 1.1 christos with_spawn_id $gdb_main_spawn_id {
916 1.1.1.5 christos match_re_or_ensure_no_output $cli_re "-thread-select again, event on CLI"
917 1.1 christos }
918 1.1 christos }
919 1.1 christos
920 1.1.1.5 christos with_test_prefix "thread 1.2 with --thread 2" {
921 1.1 christos # Test selecting a thread from MI with a --thread option. This test
922 1.1.1.5 christos # verifies that even if the thread GDB would switch to is the same as
923 1.1 christos # the thread specified with --thread, an event is still sent to CLI.
924 1.1 christos # In this case this is thread 1.2
925 1.1 christos
926 1.1 christos set mi_re [make_mi_re $mode 2 0 response]
927 1.1 christos set cli_re [make_cli_re $mode -1 1.2 0]
928 1.1 christos
929 1.1 christos with_spawn_id $mi_spawn_id {
930 1.1 christos mi_gdb_test "-thread-select --thread 2 2" $mi_re "-thread-select"
931 1.1 christos }
932 1.1 christos
933 1.1 christos with_spawn_id $gdb_main_spawn_id {
934 1.1.1.5 christos match_re_or_ensure_no_output "$cli_re\r\n" "-thread-select, event on cli"
935 1.1.1.5 christos }
936 1.1.1.5 christos }
937 1.1.1.5 christos
938 1.1.1.5 christos with_test_prefix "thread 1.2 with --thread 3" {
939 1.1.1.5 christos # Test selecting a thread from MI with a --thread option.
940 1.1.1.5 christos # This test verifies that when different thread numbers are
941 1.1.1.5 christos # passed to the --thread option and the underlying
942 1.1.1.5 christos # -thread-select command, the correct thread is selected.
943 1.1.1.5 christos # In this case this is thread 1.2
944 1.1.1.5 christos
945 1.1.1.5 christos reset_selection "1.1"
946 1.1.1.5 christos
947 1.1.1.5 christos set mi_re [make_mi_re $mode 2 0 response]
948 1.1.1.5 christos set cli_re [make_cli_re $mode -1 1.2 0]
949 1.1.1.5 christos
950 1.1.1.5 christos with_spawn_id $mi_spawn_id {
951 1.1.1.5 christos mi_gdb_test "-thread-select --thread 3 2" $mi_re "-thread-select"
952 1.1.1.5 christos }
953 1.1.1.5 christos
954 1.1.1.5 christos with_spawn_id $gdb_main_spawn_id {
955 1.1.1.5 christos match_re_or_ensure_no_output "$cli_re\r\n" "-thread-select, event on cli"
956 1.1 christos }
957 1.1 christos }
958 1.1 christos
959 1.1 christos # Idea for the future: selecting a thread in a different inferior. For now,
960 1.1 christos # GDB doesn't show an inferior switch, but if it did, it would be a nice
961 1.1 christos # place to test it.
962 1.1 christos }
963 1.1 christos
964 1.1.1.2 christos proc_with_prefix test_mi_stack_select_frame { mode } {
965 1.1 christos global gdb_main_spawn_id mi_spawn_id
966 1.1 christos
967 1.1 christos with_test_prefix "thread 1.2" {
968 1.1 christos reset_selection "1.2"
969 1.1 christos flush_buffers
970 1.1 christos
971 1.1 christos # Do the '-stack-select-frame' command to select frame 1.
972 1.1 christos
973 1.1 christos set mi_re "\\^done"
974 1.1 christos set cli_re [make_cli_re $mode -1 -1 1]
975 1.1 christos
976 1.1 christos with_spawn_id $mi_spawn_id {
977 1.1 christos mi_gdb_test "-stack-select-frame 1" $mi_re "-stack-select-frame"
978 1.1 christos }
979 1.1 christos
980 1.1 christos with_spawn_id $gdb_main_spawn_id {
981 1.1.1.5 christos match_re_or_ensure_no_output "$cli_re\r\n" "-stack-select-frame, event on CLI"
982 1.1 christos }
983 1.1 christos
984 1.1 christos # Do the '-stack-select-frame' command to select the same frame. This time we don't
985 1.1 christos # expect an event on CLI, since we won't actually change frame.
986 1.1 christos
987 1.1 christos set cli_re ""
988 1.1 christos
989 1.1 christos with_spawn_id $mi_spawn_id {
990 1.1 christos mi_gdb_test "-stack-select-frame 1" $mi_re "-stack-select-frame again"
991 1.1 christos }
992 1.1 christos
993 1.1 christos with_spawn_id $gdb_main_spawn_id {
994 1.1.1.5 christos match_re_or_ensure_no_output $cli_re "-stack-select-frame again, event on CLI"
995 1.1.1.5 christos }
996 1.1.1.5 christos
997 1.1.1.5 christos # Now use the '-stack-select-frame' command with the --frame
998 1.1.1.5 christos # option, this verifies that even when the frame GDB would
999 1.1.1.5 christos # swith to is the same as the frame specified with --frame, an
1000 1.1.1.5 christos # event is still sent to the CLI.
1001 1.1.1.5 christos
1002 1.1.1.5 christos set cli_re [make_cli_re $mode -1 -1 0]
1003 1.1.1.5 christos
1004 1.1.1.5 christos with_spawn_id $mi_spawn_id {
1005 1.1.1.5 christos mi_gdb_test "-stack-select-frame --thread 2 --frame 0 0" $mi_re
1006 1.1.1.5 christos }
1007 1.1.1.5 christos
1008 1.1.1.5 christos with_spawn_id $gdb_main_spawn_id {
1009 1.1.1.5 christos match_re_or_ensure_no_output "$cli_re\r\n" "-stack-select-frame with --frame 0, event on CLI"
1010 1.1.1.5 christos }
1011 1.1.1.5 christos
1012 1.1.1.5 christos # Now use the '-stack-select-frame' command with the --frame
1013 1.1.1.5 christos # option, this verifies that the correct event is sent to the
1014 1.1.1.5 christos # CLI when the frame specified with --frame is different to
1015 1.1.1.5 christos # the actual frame selected.
1016 1.1.1.5 christos
1017 1.1.1.5 christos set cli_re [make_cli_re $mode -1 -1 1]
1018 1.1.1.5 christos
1019 1.1.1.5 christos with_spawn_id $mi_spawn_id {
1020 1.1.1.5 christos mi_gdb_test "-stack-select-frame --thread 2 --frame 2 1" $mi_re
1021 1.1.1.5 christos }
1022 1.1.1.5 christos
1023 1.1.1.5 christos with_spawn_id $gdb_main_spawn_id {
1024 1.1.1.5 christos match_re_or_ensure_no_output "$cli_re\r\n" "-stack-select-frame with --frame 2, event on CLI"
1025 1.1 christos }
1026 1.1 christos }
1027 1.1 christos
1028 1.1 christos with_test_prefix "thread 1.3" {
1029 1.1 christos # Now, try the '-stack-select-frame' command on thread 3, which is
1030 1.1 christos # running if we are in non-stop mode.
1031 1.1 christos reset_selection "1.3"
1032 1.1 christos flush_buffers
1033 1.1 christos
1034 1.1 christos if {$mode == "all-stop"} {
1035 1.1 christos set mi_re "\\^done"
1036 1.1 christos set cli_re [make_cli_re $mode -1 -1 1]
1037 1.1 christos append cli_re "\r\n"
1038 1.1 christos } elseif {$mode == "non-stop"} {
1039 1.1 christos set cli_re ""
1040 1.1 christos set mi_re "\\^error,msg=\"Selected thread is running\\.\""
1041 1.1 christos }
1042 1.1 christos
1043 1.1 christos with_spawn_id $mi_spawn_id {
1044 1.1 christos mi_gdb_test "-stack-select-frame 1" $mi_re "-stack-select-frame"
1045 1.1 christos }
1046 1.1 christos
1047 1.1 christos with_spawn_id $gdb_main_spawn_id {
1048 1.1.1.5 christos match_re_or_ensure_no_output $cli_re "-stack-select-frame, event on CLI"
1049 1.1 christos }
1050 1.1 christos }
1051 1.1 christos }
1052 1.1 christos
1053 1.1 christos proc make_cli_in_mi_command { cli_in_mi_mode command } {
1054 1.1 christos if { $cli_in_mi_mode == "direct" } {
1055 1.1 christos return $command
1056 1.1 christos } elseif { $cli_in_mi_mode == "interpreter-exec" } {
1057 1.1 christos return "-interpreter-exec console \"$command\""
1058 1.1 christos } else {
1059 1.1 christos error "Invalid value for CLI_IN_MI_MODE."
1060 1.1 christos }
1061 1.1 christos }
1062 1.1 christos
1063 1.1 christos # Test selecting the inferior using a CLI command in the MI channel.
1064 1.1 christos
1065 1.1.1.2 christos proc_with_prefix test_cli_in_mi_inferior { mode cli_in_mi_mode } {
1066 1.1 christos global gdb_main_spawn_id mi_spawn_id
1067 1.1 christos
1068 1.1 christos reset_selection "1.1"
1069 1.1 christos flush_buffers
1070 1.1 christos
1071 1.1 christos set command [make_cli_in_mi_command $cli_in_mi_mode "inferior 2"]
1072 1.1 christos
1073 1.1 christos set mi_re [make_cli_in_mi_re $command $cli_in_mi_mode $mode 1 2 2.1 4 2]
1074 1.1 christos set cli_re [make_cli_re $mode 2 "2.1" 2]
1075 1.1 christos
1076 1.1 christos with_spawn_id $mi_spawn_id {
1077 1.1 christos mi_gdb_test $command $mi_re "select inferior"
1078 1.1 christos }
1079 1.1 christos
1080 1.1 christos with_spawn_id $gdb_main_spawn_id {
1081 1.1.1.5 christos match_re_or_ensure_no_output "$cli_re\r\n" "select inferior, event on CLI"
1082 1.1 christos }
1083 1.1 christos
1084 1.1 christos # Do the 'inferior' command on the currently selected inferior. For now,
1085 1.1 christos # GDB naively re-outputs everything.
1086 1.1 christos with_spawn_id $mi_spawn_id {
1087 1.1 christos mi_gdb_test $command $mi_re "select inferior again"
1088 1.1 christos }
1089 1.1 christos
1090 1.1 christos with_spawn_id $gdb_main_spawn_id {
1091 1.1.1.5 christos match_re_or_ensure_no_output $cli_re "select inferior again, event on CLI"
1092 1.1 christos }
1093 1.1 christos }
1094 1.1 christos
1095 1.1 christos # Test selecting the thread using a CLI command in the MI channel.
1096 1.1 christos
1097 1.1.1.2 christos proc_with_prefix test_cli_in_mi_thread { mode cli_in_mi_mode } {
1098 1.1 christos global gdb_main_spawn_id mi_spawn_id
1099 1.1 christos
1100 1.1 christos reset_selection "1.1"
1101 1.1 christos flush_buffers
1102 1.1 christos
1103 1.1 christos with_test_prefix "thread 1.2" {
1104 1.1 christos # Do the 'thread' command to select a stopped thread.
1105 1.1 christos
1106 1.1 christos set command [make_cli_in_mi_command $cli_in_mi_mode "thread 1.2"]
1107 1.1 christos set mi_re [make_cli_in_mi_re $command $cli_in_mi_mode $mode 1 -1 1.2 2 0]
1108 1.1 christos set cli_re [make_cli_re $mode -1 1.2 0]
1109 1.1 christos
1110 1.1 christos with_spawn_id $mi_spawn_id {
1111 1.1 christos mi_gdb_test $command $mi_re "select thread"
1112 1.1 christos }
1113 1.1 christos
1114 1.1 christos with_spawn_id $gdb_main_spawn_id {
1115 1.1.1.5 christos match_re_or_ensure_no_output "$cli_re\r\n" "select thread, event on CLI"
1116 1.1 christos }
1117 1.1 christos
1118 1.1 christos # Do the 'thread' command to select the same thread. We shouldn't
1119 1.1 christos # receive an event on CLI, since we won't actually switch thread.
1120 1.1 christos
1121 1.1 christos set mi_re [make_cli_in_mi_re $command $cli_in_mi_mode $mode 0 -1 1.2 2 0]
1122 1.1 christos set cli_re ""
1123 1.1 christos
1124 1.1 christos with_spawn_id $mi_spawn_id {
1125 1.1 christos mi_gdb_test $command $mi_re "select thread again"
1126 1.1 christos }
1127 1.1 christos
1128 1.1 christos with_spawn_id $gdb_main_spawn_id {
1129 1.1.1.5 christos match_re_or_ensure_no_output $cli_re "select thread again, event on CLI"
1130 1.1 christos }
1131 1.1 christos
1132 1.1 christos # Try the 'thread' command without arguments.
1133 1.1 christos
1134 1.1 christos set command [make_cli_in_mi_command $cli_in_mi_mode "thread"]
1135 1.1 christos
1136 1.1 christos set mi_re "${command}.*~\"\\\[Current thread is 1\\.2.*\\\]\\\\n\".*\\^done"
1137 1.1 christos set cli_re ""
1138 1.1 christos
1139 1.1 christos with_spawn_id $mi_spawn_id {
1140 1.1 christos mi_gdb_test $command $mi_re "thread without args"
1141 1.1 christos }
1142 1.1 christos
1143 1.1 christos with_spawn_id $gdb_main_spawn_id {
1144 1.1.1.5 christos match_re_or_ensure_no_output $cli_re "thread without args, event on CLI"
1145 1.1 christos }
1146 1.1 christos }
1147 1.1 christos
1148 1.1 christos with_test_prefix "thread 1.3" {
1149 1.1 christos # Do the 'thread' command to select the third thread, stopped on
1150 1.1 christos # all-stop, running on non-stop.
1151 1.1 christos
1152 1.1 christos set command [make_cli_in_mi_command $cli_in_mi_mode "thread 1.3"]
1153 1.1 christos if { $mode == "all-stop" } {
1154 1.1 christos set mi_re [make_cli_in_mi_re $command $cli_in_mi_mode $mode 1 -1 1.3 3 0]
1155 1.1 christos set cli_re [make_cli_re $mode -1 "1.3" 0]
1156 1.1 christos } else {
1157 1.1 christos set mi_re [make_cli_in_mi_re $command $cli_in_mi_mode $mode 1 -1 1.3 3 -1]
1158 1.1 christos set cli_re [make_cli_re $mode -1 "1.3" -1]
1159 1.1 christos }
1160 1.1 christos
1161 1.1 christos with_spawn_id $mi_spawn_id {
1162 1.1 christos mi_gdb_test $command $mi_re "select thread"
1163 1.1 christos }
1164 1.1 christos
1165 1.1 christos with_spawn_id $gdb_main_spawn_id {
1166 1.1.1.5 christos match_re_or_ensure_no_output "$cli_re\r\n" "select thread, event on CLI"
1167 1.1 christos }
1168 1.1 christos
1169 1.1 christos # Do the 'thread' command to select the third thread again. Again, we
1170 1.1 christos # shouldn't receive an event on MI.
1171 1.1 christos
1172 1.1 christos if { $mode == "all-stop" } {
1173 1.1 christos set mi_re [make_cli_in_mi_re $command $cli_in_mi_mode $mode 0 -1 1.3 3 0]
1174 1.1 christos } else {
1175 1.1 christos set mi_re [make_cli_in_mi_re $command $cli_in_mi_mode $mode 0 -1 1.3 3 -1]
1176 1.1 christos }
1177 1.1 christos set cli_re ""
1178 1.1 christos
1179 1.1 christos with_spawn_id $mi_spawn_id {
1180 1.1 christos mi_gdb_test $command $mi_re "select thread again"
1181 1.1 christos }
1182 1.1 christos
1183 1.1 christos with_spawn_id $gdb_main_spawn_id {
1184 1.1.1.5 christos match_re_or_ensure_no_output $cli_re "select thread again, event on CLI"
1185 1.1 christos }
1186 1.1 christos
1187 1.1 christos # Try the 'thread' command without arguments.
1188 1.1 christos
1189 1.1 christos set command [make_cli_in_mi_command $cli_in_mi_mode "thread"]
1190 1.1 christos
1191 1.1 christos set mi_re "${command}.*~\"\\\[Current thread is 1\\.3.*\\\]\\\\n\".*\\^done"
1192 1.1 christos set cli_re ""
1193 1.1 christos
1194 1.1 christos with_spawn_id $mi_spawn_id {
1195 1.1 christos mi_gdb_test $command $mi_re "thread without args"
1196 1.1 christos }
1197 1.1 christos
1198 1.1 christos with_spawn_id $gdb_main_spawn_id {
1199 1.1.1.5 christos match_re_or_ensure_no_output $cli_re "thread without args, event on CLI"
1200 1.1 christos }
1201 1.1 christos }
1202 1.1 christos
1203 1.1 christos # Idea for the future: selecting a thread in a different inferior. For now,
1204 1.1 christos # GDB doesn't show an inferior switch, but if it did, it would be a nice
1205 1.1 christos # place to test it.
1206 1.1 christos }
1207 1.1 christos
1208 1.1 christos # Test selecting the frame using a CLI command in the MI channel.
1209 1.1 christos
1210 1.1.1.2 christos proc_with_prefix test_cli_in_mi_frame { mode cli_in_mi_mode } {
1211 1.1 christos global gdb_main_spawn_id mi_spawn_id
1212 1.1 christos
1213 1.1 christos with_test_prefix "thread 1.2" {
1214 1.1 christos reset_selection "1.2"
1215 1.1 christos flush_buffers
1216 1.1 christos
1217 1.1 christos # Do the 'frame' command to select frame 1.
1218 1.1 christos
1219 1.1 christos set command [make_cli_in_mi_command $cli_in_mi_mode "frame 1"]
1220 1.1 christos set cli_re [make_cli_re $mode -1 -1 1]
1221 1.1 christos set mi_re [make_cli_in_mi_re $command $cli_in_mi_mode $mode 1 -1 -1 2 1]
1222 1.1 christos
1223 1.1 christos with_spawn_id $mi_spawn_id {
1224 1.1 christos mi_gdb_test $command $mi_re "select frame 1"
1225 1.1 christos }
1226 1.1 christos
1227 1.1 christos with_spawn_id $gdb_main_spawn_id {
1228 1.1.1.5 christos match_re_or_ensure_no_output "$cli_re\r\n" "select frame 1, event on CLI"
1229 1.1 christos }
1230 1.1 christos
1231 1.1 christos # Do the 'frame' command to select the same frame. This time we don't
1232 1.1 christos # expect an event on MI, since we won't actually change frame.
1233 1.1 christos
1234 1.1 christos set mi_re [make_cli_in_mi_re $command $cli_in_mi_mode $mode 0 -1 -1 2 1]
1235 1.1 christos set cli_re ""
1236 1.1 christos
1237 1.1 christos with_spawn_id $mi_spawn_id {
1238 1.1 christos mi_gdb_test $command $mi_re "select frame 1 again"
1239 1.1 christos }
1240 1.1 christos
1241 1.1 christos with_spawn_id $gdb_main_spawn_id {
1242 1.1.1.5 christos match_re_or_ensure_no_output $cli_re "select frame 1 again, event on CLI"
1243 1.1 christos }
1244 1.1 christos
1245 1.1 christos # Do the 'frame' command without arguments. We shouldn't see anything on MI.
1246 1.1 christos
1247 1.1 christos set command [make_cli_in_mi_command $cli_in_mi_mode "frame"]
1248 1.1 christos set mi_re [make_cli_in_mi_re $command $cli_in_mi_mode $mode 0 -1 -1 2 1]
1249 1.1 christos
1250 1.1 christos with_spawn_id $mi_spawn_id {
1251 1.1 christos mi_gdb_test $command $mi_re "frame without args"
1252 1.1 christos }
1253 1.1 christos
1254 1.1 christos with_spawn_id $gdb_main_spawn_id {
1255 1.1.1.5 christos match_re_or_ensure_no_output $cli_re "frame without args, event on CLI"
1256 1.1 christos }
1257 1.1 christos }
1258 1.1 christos
1259 1.1 christos with_test_prefix "thread 1.3" {
1260 1.1 christos # Now, try the 'frame' command on thread 3, which is running if we are in
1261 1.1 christos # non-stop mode.
1262 1.1 christos reset_selection "1.3"
1263 1.1 christos flush_buffers
1264 1.1 christos
1265 1.1 christos set command [make_cli_in_mi_command $cli_in_mi_mode "frame 1"]
1266 1.1 christos if {$mode == "all-stop"} {
1267 1.1 christos set cli_re [make_cli_re $mode -1 -1 1]
1268 1.1 christos append cli_re "\r\n"
1269 1.1 christos set mi_re [make_cli_in_mi_re $command $cli_in_mi_mode $mode 1 -1 -1 3 1]
1270 1.1 christos } elseif {$mode == "non-stop"} {
1271 1.1 christos set cli_re ""
1272 1.1 christos set mi_re "\\^error,msg=\"Selected thread is running\\.\".*"
1273 1.1 christos }
1274 1.1 christos
1275 1.1 christos with_spawn_id $mi_spawn_id {
1276 1.1 christos mi_gdb_test $command $mi_re "select frame 1"
1277 1.1 christos }
1278 1.1 christos
1279 1.1 christos with_spawn_id $gdb_main_spawn_id {
1280 1.1.1.5 christos match_re_or_ensure_no_output $cli_re "select frame 1, event on CLI"
1281 1.1 christos }
1282 1.1 christos
1283 1.1 christos # Do the 'frame' command without arguments.
1284 1.1 christos
1285 1.1 christos set command [make_cli_in_mi_command $cli_in_mi_mode "frame"]
1286 1.1 christos if { $mode == "all-stop" } {
1287 1.1 christos set mi_re [make_cli_in_mi_re $command $cli_in_mi_mode $mode 0 -1 -1 -1 1]
1288 1.1 christos } else {
1289 1.1 christos set mi_re "\\^error,msg=\"No stack\\.\""
1290 1.1 christos }
1291 1.1 christos set cli_re ""
1292 1.1 christos
1293 1.1 christos with_spawn_id $mi_spawn_id {
1294 1.1 christos mi_gdb_test $command $mi_re "frame without args"
1295 1.1 christos }
1296 1.1 christos
1297 1.1 christos with_spawn_id $gdb_main_spawn_id {
1298 1.1.1.5 christos match_re_or_ensure_no_output $cli_re "frame without args, event on CLI"
1299 1.1 christos }
1300 1.1 christos }
1301 1.1 christos }
1302 1.1 christos
1303 1.1 christos foreach_with_prefix mode { "all-stop" "non-stop" } {
1304 1.1.1.5 christos set test "setup done"
1305 1.1.1.5 christos if { [test_setup $mode] == -1 } {
1306 1.1.1.5 christos fail $test
1307 1.1.1.5 christos continue
1308 1.1.1.5 christos }
1309 1.1.1.5 christos pass $test
1310 1.1 christos
1311 1.1 christos # Test selecting inferior, thread and frame from CLI
1312 1.1 christos
1313 1.1.1.2 christos test_cli_inferior $mode
1314 1.1.1.2 christos test_cli_thread $mode
1315 1.1.1.2 christos test_cli_frame $mode
1316 1.1.1.2 christos test_cli_select_frame $mode
1317 1.1.1.2 christos test_cli_up_down $mode
1318 1.1 christos
1319 1.1 christos # Test selecting thread and frame from MI
1320 1.1 christos
1321 1.1.1.2 christos test_mi_thread_select $mode
1322 1.1.1.2 christos test_mi_stack_select_frame $mode
1323 1.1 christos
1324 1.1 christos # Test some CLI commands sent through MI, both with a "direct" command,
1325 1.1 christos # such as "thread 1", and with -interpreter-exec, such as
1326 1.1 christos # '-interpreter-exec console "thread 1"'.
1327 1.1 christos
1328 1.1 christos foreach_with_prefix exec_mode {"direct" "interpreter-exec"} {
1329 1.1.1.2 christos test_cli_in_mi_inferior $mode $exec_mode
1330 1.1.1.2 christos test_cli_in_mi_thread $mode $exec_mode
1331 1.1.1.2 christos test_cli_in_mi_frame $mode $exec_mode
1332 1.1 christos }
1333 1.1 christos }
1334