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