]>
Commit | Line | Data |
---|---|---|
b811d2c2 | 1 | # Copyright 2016-2020 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 { | |
310 | mi_expect_stop "breakpoint-hit" "main" "" "$srcfile" \ | |
311 | "$decimal" {"" "disp=\"del\""} "stop at breakpoint in main" | |
312 | } | |
313 | ||
314 | if { $mode == "all-stop" } { | |
315 | set previous_schedlock_val [show_scheduler_locking] | |
316 | ||
317 | # Set scheduler-locking on, so that we can control threads | |
318 | # independently. | |
319 | gdb_test_no_output "set scheduler-locking on" | |
320 | ||
321 | # Continue each child thread to the point we want them to be. | |
322 | foreach thread { 2 3 } { | |
323 | gdb_test "thread $inf.$thread" ".*" "select child thread $inf.$thread" | |
324 | ||
325 | gdb_test "tbreak $srcfile:$thread_loop_line" \ | |
326 | "Temporary breakpoint ${any}" \ | |
327 | "set breakpoint for thread $inf.$thread" | |
328 | ||
329 | gdb_continue_to_breakpoint "continue thread $inf.$thread to infinite loop breakpoint" | |
330 | ||
331 | # Consume MI output. | |
332 | with_spawn_id $mi_spawn_id { | |
333 | mi_expect_stop "breakpoint-hit" "child_sub_function" \ | |
334 | "" "$srcfile" "$decimal" {"" "disp=\"del\""} \ | |
335 | "thread $inf.$thread stops MI" | |
336 | } | |
337 | } | |
338 | ||
339 | # Restore scheduler-locking to its original value. | |
340 | gdb_test_no_output "set scheduler-locking $previous_schedlock_val" | |
341 | } else { # $mode == "non-stop" | |
342 | # Put a thread-specific breakpoint for thread 2 of the current | |
343 | # inferior. We don't put a breakpoint for thread 3, since we | |
344 | # want to let it run. | |
345 | set test "set thread-specific breakpoint, thread $inf.2" | |
346 | gdb_test_multiple "tbreak $srcfile:$thread_loop_line thread $inf.2" $test { | |
347 | -re "Temporary breakpoint ${any}\r\n$gdb_prompt " { | |
348 | pass $test | |
349 | } | |
350 | } | |
351 | ||
352 | # Confirm the stop of thread $inf.2. | |
353 | set test "thread $inf.2 stops CLI" | |
354 | gdb_test_multiple "" $test { | |
355 | -re "Thread $inf.2 ${any} hit Temporary breakpoint ${any}\r\n$thread_loop_line${any}\r\n" { | |
356 | pass $test | |
357 | } | |
358 | } | |
359 | ||
360 | # Consume MI output. | |
361 | with_spawn_id $mi_spawn_id { | |
362 | mi_expect_stop "breakpoint-hit" "child_sub_function" \ | |
363 | "" "$srcfile" "$decimal" {"" "disp=\"del\""} \ | |
364 | "thread $inf.2 stops MI" | |
365 | } | |
366 | } | |
367 | } | |
368 | } | |
369 | } | |
370 | ||
371 | # Prepare the test environment. | |
372 | # | |
373 | # MODE can be either "all-stop" or "non-stop". | |
374 | ||
8354c62c | 375 | proc_with_prefix test_setup { mode } { |
9c36d954 AT |
376 | global srcfile |
377 | global srcdir | |
378 | global subdir | |
379 | global gdb_main_spawn_id | |
380 | global mi_spawn_id | |
381 | global decimal | |
382 | global binfile | |
383 | global GDBFLAGS | |
384 | global async | |
385 | ||
386 | set any "\[^\r\n\]*" | |
387 | ||
388 | mi_gdb_exit | |
389 | ||
390 | save_vars { GDBFLAGS } { | |
391 | if { $mode == "non-stop" } { | |
392 | set GDBFLAGS [concat $GDBFLAGS " -ex \"set non-stop 1\""] | |
393 | } | |
394 | ||
395 | if { [mi_gdb_start "separate-mi-tty"] != 0 } { | |
396 | return | |
397 | } | |
398 | } | |
399 | ||
400 | mi_delete_breakpoints | |
401 | mi_gdb_reinitialize_dir $srcdir/$subdir | |
402 | mi_gdb_load $binfile | |
403 | ||
404 | if { [mi_runto main] < 0 } { | |
bc6c7af4 | 405 | fail "can't run to main" |
9c36d954 AT |
406 | return |
407 | } | |
408 | ||
409 | # When using mi_expect_stop, we don't expect a prompt after the *stopped | |
410 | # event, since the blocking commands are done from the CLI. Setting async | |
411 | # to 1 makes it not expect the prompt. | |
412 | set async 1 | |
413 | ||
414 | with_spawn_id $gdb_main_spawn_id { | |
415 | # Add the second inferior now. While this is not mandatory, it allows | |
416 | # us to assume that per-inferior thread numbering will be used, | |
417 | # simplifying test_continue_to_start a bit (Thread 1.2 and not Thread 2). | |
cdc7edd7 | 418 | gdb_test "add-inferior" "Added inferior 2" "add inferior 2" |
9c36d954 AT |
419 | |
420 | # Prepare the first inferior for the test. | |
421 | test_continue_to_start $mode 1 | |
422 | ||
423 | # Switch to and start the second inferior. | |
424 | gdb_test "inferior 2" "\\\[Switching to inferior 2${any}\\\]" "switch to inferior 2" | |
425 | gdb_load ${binfile} | |
426 | ||
427 | # Doing "start" on the CLI generates a ton of MI output. At some point, | |
428 | # if we don't consume/match it, the buffer between GDB's MI channel and | |
429 | # Expect will get full, GDB will block on a write system call and we'll | |
430 | # deadlock, waiting for CLI output that will never arrive. And then | |
431 | # we're sad. So instead of using gdb_test and expect CLI output, send | |
432 | # the start command first, then consume MI output, and finally consume | |
433 | # CLI output. | |
434 | send_gdb "start\n" | |
435 | ||
436 | with_spawn_id $mi_spawn_id { | |
437 | mi_expect_stop "breakpoint-hit" "main" "" "$srcfile" "$decimal" \ | |
438 | {"" "disp=\"del\""} "main stop" | |
439 | } | |
440 | ||
441 | # Consume CLI output. | |
442 | gdb_test "" "Temporary breakpoint.*Starting program.*" | |
443 | ||
444 | # Prepare the second inferior for the test. | |
445 | test_continue_to_start $mode 2 | |
446 | } | |
447 | } | |
448 | ||
449 | # Reset the selection to frame #0 of thread THREAD. | |
450 | ||
451 | proc reset_selection { thread } { | |
452 | global gdb_main_spawn_id | |
453 | ||
454 | set any "\[^\r\n\]*" | |
455 | ||
456 | with_spawn_id $gdb_main_spawn_id { | |
457 | gdb_test "thread $thread" \ | |
458 | "\\\[Switching to thread $thread ${any}\\\].*" \ | |
459 | "reset selection to thread $thread" | |
460 | gdb_test "frame 0" ".*" "reset selection to frame 0" | |
461 | } | |
462 | } | |
463 | ||
464 | # Flush Expect's internal buffers for both CLI and MI. | |
465 | # | |
466 | # The idea here is to send a command, and to consume all the characters that we | |
467 | # expect that command to output, including the following prompt. Using gdb_test | |
468 | # and mi_gdb_test should do that. | |
469 | ||
470 | proc flush_buffers { } { | |
471 | global gdb_main_spawn_id mi_spawn_id | |
472 | ||
473 | with_spawn_id $gdb_main_spawn_id { | |
474 | gdb_test "print 444" "= 444" "flush CLI" | |
475 | } | |
476 | ||
477 | with_spawn_id $mi_spawn_id { | |
478 | mi_gdb_test "555-data-evaluate-expression 666" ".*done,value=\"666\"" "flush MI" | |
479 | } | |
480 | } | |
481 | ||
482 | # Run a command on the current spawn id, to confirm that no output is pending | |
483 | # in Expect's internal buffer. This is used to ensure that nothing was output | |
484 | # on the spawn id since the call to gdb_test/mi_gdb_test/flush_buffers. | |
485 | # | |
486 | # The key here is that the regexes use start-of-buffer anchors (^), ensuring | |
487 | # that they match the entire buffer, confirming that there was nothing in it | |
488 | # before. | |
489 | ||
490 | proc ensure_no_output { test } { | |
491 | global gdb_spawn_id gdb_main_spawn_id mi_spawn_id | |
492 | global decimal | |
493 | ||
494 | if { $gdb_spawn_id == $gdb_main_spawn_id } { | |
495 | # CLI | |
496 | gdb_test "print 666" \ | |
497 | "^print 666\r\n\\\$$decimal = 666" \ | |
498 | "$test, ensure no output CLI" | |
499 | } elseif { $gdb_spawn_id == $mi_spawn_id } { | |
500 | # MI | |
501 | mi_gdb_test "777-data-evaluate-expression 888" \ | |
502 | "^777-data-evaluate-expression 888\r\n777\\^done,value=\"888\"" \ | |
503 | "$test, ensure no output MI" | |
504 | } else { | |
505 | error "Unexpected gdb_spawn_id value." | |
506 | } | |
507 | } | |
508 | ||
509 | # Match a regular expression, or ensure that there was no output. | |
510 | # | |
511 | # If RE is non-empty, try to match the content of the program output (using the | |
512 | # current spawn_id) and pass/fail TEST accordingly. | |
513 | # If RE is empty, ensure that the program did not output anything. | |
514 | ||
515 | proc match_re_or_ensure_not_output { re test } { | |
516 | if { $re != "" } { | |
517 | gdb_expect { | |
518 | -re "$re" { | |
519 | pass $test | |
520 | } | |
521 | ||
522 | default { | |
523 | fail $test | |
524 | } | |
525 | } | |
526 | } else { | |
527 | ensure_no_output $test | |
528 | } | |
529 | } | |
530 | ||
531 | # Test selecting an inferior from CLI. | |
532 | ||
8354c62c | 533 | proc_with_prefix test_cli_inferior { mode } { |
9c36d954 AT |
534 | global gdb_main_spawn_id mi_spawn_id |
535 | ||
536 | reset_selection "1.1" | |
537 | ||
538 | set mi_re [make_mi_re $mode 4 2 event] | |
539 | set cli_re [make_cli_re $mode 2 2.1 2] | |
540 | ||
541 | flush_buffers | |
542 | ||
543 | # Do the 'inferior' command. | |
544 | with_spawn_id $gdb_main_spawn_id { | |
545 | gdb_test "inferior 2" $cli_re "CLI select inferior" | |
546 | } | |
547 | ||
548 | with_spawn_id $mi_spawn_id { | |
549 | match_re_or_ensure_not_output $mi_re "event on MI" | |
550 | } | |
551 | ||
552 | # Do the 'inferior' command on the currently selected inferior. For now, | |
553 | # GDB naively re-outputs everything. | |
554 | with_spawn_id $gdb_main_spawn_id { | |
555 | gdb_test "inferior 2" $cli_re "CLI select inferior again" | |
556 | } | |
557 | ||
558 | with_spawn_id $mi_spawn_id { | |
559 | match_re_or_ensure_not_output $mi_re "event on MI again" | |
560 | } | |
561 | } | |
562 | ||
563 | # Test thread selection from CLI. | |
564 | ||
8354c62c | 565 | proc_with_prefix test_cli_thread { mode } { |
9c36d954 AT |
566 | global gdb_main_spawn_id |
567 | global mi_spawn_id | |
568 | ||
569 | set any "\[^\r\n\]*" | |
570 | ||
571 | reset_selection "1.1" | |
572 | flush_buffers | |
573 | ||
574 | with_test_prefix "thread 1.2" { | |
575 | # Do the 'thread' command to select a stopped thread. | |
576 | ||
577 | set mi_re [make_mi_re $mode 2 0 event] | |
578 | set cli_re [make_cli_re $mode -1 1.2 0] | |
579 | ||
580 | with_spawn_id $gdb_main_spawn_id { | |
581 | gdb_test "thread 1.2" $cli_re "select thread" | |
582 | } | |
583 | ||
584 | with_spawn_id $mi_spawn_id { | |
585 | match_re_or_ensure_not_output $mi_re "select thread, event on MI " | |
586 | } | |
587 | ||
588 | # Do the 'thread' command to select the same thread. We shouldn't receive | |
589 | # an event on MI, since we won't actually switch thread. | |
590 | ||
591 | set mi_re "" | |
592 | ||
593 | with_spawn_id $gdb_main_spawn_id { | |
594 | gdb_test "thread 1.2" $cli_re "select thread again" | |
595 | } | |
596 | ||
597 | with_spawn_id $mi_spawn_id { | |
598 | match_re_or_ensure_not_output $mi_re "select thread, event on MI again" | |
599 | } | |
600 | ||
601 | # Try the 'thread' command without arguments. | |
602 | ||
603 | set cli_re "\\\[Current thread is 1\\.2.*\\\]" | |
604 | set mi_re "" | |
605 | ||
606 | with_spawn_id $gdb_main_spawn_id { | |
607 | gdb_test "thread" $cli_re "thread without args" | |
608 | } | |
609 | ||
610 | with_spawn_id $mi_spawn_id { | |
611 | match_re_or_ensure_not_output $mi_re "thread without args, event on MI" | |
612 | } | |
613 | } | |
614 | ||
615 | with_test_prefix "thread 1.3" { | |
616 | # Do the 'thread' command to select the third thread, stopped on all-stop, | |
617 | # running on non-stop. | |
618 | ||
619 | if { $mode == "all-stop" } { | |
620 | set cli_re [make_cli_re $mode -1 1.3 0] | |
621 | set mi_re [make_mi_re $mode 3 0 event] | |
622 | } else { | |
623 | set cli_re [make_cli_re $mode -1 1.3 -1] | |
624 | set mi_re [make_mi_re $mode 3 -1 event] | |
625 | } | |
626 | ||
627 | with_spawn_id $gdb_main_spawn_id { | |
628 | gdb_test "thread 1.3" $cli_re "select thread" | |
629 | } | |
630 | ||
631 | with_spawn_id $mi_spawn_id { | |
632 | match_re_or_ensure_not_output $mi_re "select thread, event on MI" | |
633 | } | |
634 | ||
635 | # Do the 'thread' command to select the third thread again. Again, we | |
636 | # shouldn't receive an event on MI. | |
637 | ||
638 | set mi_re "" | |
639 | ||
640 | with_spawn_id $gdb_main_spawn_id { | |
641 | gdb_test "thread 1.3" $cli_re "select thread again" | |
642 | } | |
643 | ||
644 | with_spawn_id $mi_spawn_id { | |
645 | match_re_or_ensure_not_output $mi_re "select thread again, event on MI" | |
646 | } | |
647 | ||
648 | # Try the 'thread' command without arguments. | |
649 | ||
650 | set cli_re "\\\[Current thread is 1\\.3 ${any}\\\]" | |
651 | set mi_re "" | |
652 | ||
653 | with_spawn_id $gdb_main_spawn_id { | |
654 | gdb_test "thread" $cli_re "thread without args" | |
655 | } | |
656 | ||
657 | with_spawn_id $mi_spawn_id { | |
658 | match_re_or_ensure_not_output $mi_re "thread without args, event on MI" | |
659 | } | |
660 | } | |
661 | ||
662 | # Idea for the future: selecting a thread in a different inferior. For now, | |
663 | # GDB doesn't show an inferior switch, but if it did, it would be a nice | |
664 | # place to test it. | |
665 | } | |
666 | ||
667 | # Test frame selection from CLI. | |
668 | ||
8354c62c | 669 | proc_with_prefix test_cli_frame { mode } { |
9c36d954 AT |
670 | global gdb_main_spawn_id mi_spawn_id |
671 | ||
672 | with_test_prefix "thread 1.2" { | |
673 | reset_selection "1.2" | |
674 | flush_buffers | |
675 | ||
676 | # Do the 'frame' command to select frame 1. | |
677 | ||
678 | set mi_re [make_mi_re $mode 2 1 event] | |
679 | set cli_re [make_cli_re $mode -1 -1 1] | |
680 | ||
681 | with_spawn_id $gdb_main_spawn_id { | |
682 | gdb_test "frame 1" $cli_re "select frame 1" | |
683 | } | |
684 | ||
685 | with_spawn_id $mi_spawn_id { | |
686 | match_re_or_ensure_not_output $mi_re "select frame 1, event on MI" | |
687 | } | |
688 | ||
689 | # Do the 'frame' command to select the same frame. This time we don't | |
690 | # expect an event on MI, since we won't actually change frame. | |
691 | ||
692 | set mi_re "" | |
693 | ||
694 | with_spawn_id $gdb_main_spawn_id { | |
695 | gdb_test "frame 1" $cli_re "select frame 1 again" | |
696 | } | |
697 | ||
698 | with_spawn_id $mi_spawn_id { | |
699 | match_re_or_ensure_not_output $mi_re "select frame 1 again, event on MI" | |
700 | } | |
701 | ||
702 | # Do the 'frame' command without arguments. We shouldn't see anything on MI. | |
703 | ||
704 | with_spawn_id $gdb_main_spawn_id { | |
705 | gdb_test "frame" $cli_re "frame without args" | |
706 | } | |
707 | ||
708 | with_spawn_id $mi_spawn_id { | |
709 | match_re_or_ensure_not_output $mi_re "frame without args, event on MI" | |
710 | } | |
711 | } | |
712 | ||
713 | with_test_prefix "thread 1.3" { | |
714 | # Now, try the 'frame' command on thread 3, which is running if we are in | |
715 | # non-stop mode. | |
716 | reset_selection "1.3" | |
717 | flush_buffers | |
718 | ||
719 | if {$mode == "all-stop"} { | |
720 | set mi_re [make_mi_re $mode 3 1 event] | |
721 | set cli_re [make_cli_re $mode -1 -1 1] | |
722 | } elseif {$mode == "non-stop"} { | |
723 | set mi_re "" | |
724 | set cli_re "Selected thread is running\\." | |
725 | } | |
726 | ||
727 | with_spawn_id $gdb_main_spawn_id { | |
728 | gdb_test "frame 1" $cli_re "select frame 1" | |
729 | } | |
730 | ||
731 | with_spawn_id $mi_spawn_id { | |
732 | match_re_or_ensure_not_output $mi_re "select frame 1, event on MI" | |
733 | } | |
734 | ||
735 | # Do the 'frame' command without arguments. | |
736 | ||
737 | if { $mode == "non-stop" } { | |
738 | set cli_re "No stack\\." | |
739 | } | |
740 | set mi_re "" | |
741 | ||
742 | with_spawn_id $gdb_main_spawn_id { | |
743 | gdb_test "frame" $cli_re "frame without args" | |
744 | } | |
745 | ||
746 | with_spawn_id $mi_spawn_id { | |
747 | match_re_or_ensure_not_output $mi_re "frame without args, event on MI" | |
748 | } | |
749 | } | |
750 | } | |
751 | ||
752 | # Test frame selection from CLI with the select-frame command. | |
753 | ||
8354c62c | 754 | proc_with_prefix test_cli_select_frame { mode } { |
9c36d954 AT |
755 | global gdb_main_spawn_id mi_spawn_id expect_out |
756 | ||
757 | with_test_prefix "thread 1.2" { | |
758 | reset_selection "1.2" | |
759 | flush_buffers | |
760 | ||
761 | # Do the 'select-frame' command to select frame 1. | |
762 | ||
763 | set mi_re [make_mi_re $mode 2 1 event] | |
764 | ||
765 | with_spawn_id $gdb_main_spawn_id { | |
766 | gdb_test_no_output "select-frame 1" "select frame 1" | |
767 | } | |
768 | ||
769 | with_spawn_id $mi_spawn_id { | |
770 | match_re_or_ensure_not_output $mi_re "select frame 1, event on MI" | |
771 | } | |
772 | ||
773 | # Do the 'select-frame' command to select the same frame. This time we expect to | |
774 | # event on MI, since we won't actually change frame. | |
775 | ||
776 | set mi_re "" | |
777 | ||
778 | with_spawn_id $gdb_main_spawn_id { | |
779 | gdb_test_no_output "select-frame 1" "select frame 1 again" | |
780 | } | |
781 | ||
782 | with_spawn_id $mi_spawn_id { | |
783 | match_re_or_ensure_not_output $mi_re "select frame 1 again, event on MI" | |
784 | } | |
785 | } | |
786 | ||
787 | with_test_prefix "thread 1.3" { | |
788 | # Now, try the 'select-frame' command on thread 3, which is running if we are in | |
789 | # non-stop mode. | |
790 | reset_selection "1.3" | |
791 | flush_buffers | |
792 | ||
793 | if {$mode == "all-stop"} { | |
794 | set mi_re [make_mi_re $mode 3 1 event] | |
795 | } elseif {$mode == "non-stop"} { | |
796 | set mi-re "" | |
797 | set cli_re "Selected thread is running\\." | |
798 | } | |
799 | ||
800 | with_spawn_id $gdb_main_spawn_id { | |
801 | if { $mode == "all-stop" } { | |
802 | gdb_test_no_output "select-frame 1" "select frame 1" | |
803 | } else { | |
804 | gdb_test "select-frame 1" $cli_re "select frame 1" | |
805 | } | |
806 | } | |
807 | ||
808 | with_spawn_id $mi_spawn_id { | |
809 | match_re_or_ensure_not_output $mi_re "select frame 1, event on MI" | |
810 | } | |
811 | } | |
812 | } | |
813 | ||
814 | # Test doing an up and then down command from CLI. | |
815 | ||
8354c62c | 816 | proc_with_prefix test_cli_up_down { mode } { |
9c36d954 AT |
817 | global gdb_main_spawn_id mi_spawn_id |
818 | ||
819 | reset_selection "1.2" | |
820 | flush_buffers | |
821 | ||
822 | # Try doing an 'up'. | |
823 | ||
824 | set mi_re [make_mi_re $mode 2 1 event] | |
825 | set cli_re [make_cli_re $mode -1 -1 1] | |
826 | ||
827 | with_spawn_id $gdb_main_spawn_id { | |
828 | gdb_test "up" $cli_re "frame up" | |
829 | } | |
830 | ||
831 | with_spawn_id $mi_spawn_id { | |
832 | match_re_or_ensure_not_output $mi_re "frame up, event on MI" | |
833 | } | |
834 | ||
835 | # Try doing a 'down'. | |
836 | ||
837 | set mi_re [make_mi_re $mode 2 0 event] | |
838 | set cli_re [make_cli_re $mode -1 -1 0] | |
839 | ||
840 | with_spawn_id $gdb_main_spawn_id { | |
841 | gdb_test "down" $cli_re "frame down" | |
842 | } | |
843 | ||
844 | with_spawn_id $mi_spawn_id { | |
845 | match_re_or_ensure_not_output $mi_re "frame down, event on MI" | |
846 | } | |
847 | } | |
848 | ||
849 | # Test selecting a thread from MI. | |
850 | ||
8354c62c | 851 | proc_with_prefix test_mi_thread_select { mode } { |
9c36d954 AT |
852 | global gdb_main_spawn_id mi_spawn_id |
853 | ||
854 | reset_selection "1.1" | |
855 | flush_buffers | |
856 | ||
857 | with_test_prefix "thread 1.2" { | |
858 | # Do the '-thread-select' command to select a stopped thread. | |
859 | ||
860 | set mi_re [make_mi_re $mode 2 0 response] | |
861 | set cli_re [make_cli_re $mode -1 1.2 0] | |
862 | ||
863 | with_spawn_id $mi_spawn_id { | |
864 | mi_gdb_test "-thread-select 2" $mi_re "-thread-select" | |
865 | } | |
866 | ||
867 | with_spawn_id $gdb_main_spawn_id { | |
868 | match_re_or_ensure_not_output "$cli_re\r\n" "-thread-select, event on CLI" | |
869 | } | |
870 | ||
871 | # Do the '-thread-select' command to select the same thread. We | |
872 | # shouldn't receive an event on CLI, since we won't actually switch | |
873 | # thread. | |
874 | ||
875 | set cli_re "" | |
876 | ||
877 | with_spawn_id $mi_spawn_id { | |
878 | mi_gdb_test "-thread-select 2" $mi_re "-thread-select again" | |
879 | } | |
880 | ||
881 | with_spawn_id $gdb_main_spawn_id { | |
882 | match_re_or_ensure_not_output $cli_re "-thread-select again, event on CLI" | |
883 | } | |
884 | } | |
885 | ||
886 | with_test_prefix "thread 1.3" { | |
887 | # Do the '-thread-select' command to select the third thread, stopped on all-stop, | |
888 | # running on non-stop. | |
889 | ||
890 | if { $mode == "all-stop" } { | |
891 | set mi_re [make_mi_re $mode 3 0 response] | |
892 | set cli_re [make_cli_re $mode -1 1.3 0] | |
893 | } else { | |
894 | set mi_re [make_mi_re $mode 3 -1 response] | |
895 | set cli_re [make_cli_re $mode -1 1.3 -1] | |
896 | } | |
897 | ||
898 | with_spawn_id $mi_spawn_id { | |
899 | mi_gdb_test "-thread-select 3" $mi_re "-thread-select" | |
900 | } | |
901 | ||
902 | with_spawn_id $gdb_main_spawn_id { | |
903 | match_re_or_ensure_not_output "$cli_re\r\n" "-thread-select, event on CLI" | |
904 | } | |
905 | ||
906 | # Do the 'thread' command to select the third thread again. Again, we | |
907 | # shouldn't receive an event on MI. | |
908 | ||
909 | set cli_re "" | |
910 | ||
911 | with_spawn_id $mi_spawn_id { | |
912 | mi_gdb_test "-thread-select 3" $mi_re "-thread-select again" | |
913 | } | |
914 | ||
915 | with_spawn_id $gdb_main_spawn_id { | |
916 | match_re_or_ensure_not_output $cli_re "-thread-select again, event on CLI" | |
917 | } | |
918 | } | |
919 | ||
920 | with_test_prefix "thread 1.2 with --thread" { | |
921 | # Test selecting a thread from MI with a --thread option. This test | |
922 | # verifies that even if the thread GDB would switch to is the same has | |
923 | # the thread specified with --thread, an event is still sent to CLI. | |
924 | # In this case this is thread 1.2 | |
925 | ||
926 | set mi_re [make_mi_re $mode 2 0 response] | |
927 | set cli_re [make_cli_re $mode -1 1.2 0] | |
928 | ||
929 | with_spawn_id $mi_spawn_id { | |
930 | mi_gdb_test "-thread-select --thread 2 2" $mi_re "-thread-select" | |
931 | } | |
932 | ||
933 | with_spawn_id $gdb_main_spawn_id { | |
934 | # This doesn't work as of now, no event is sent on CLI. It is | |
935 | # commented out so we don't have to wait for the timeout every time. | |
936 | # match_re_or_ensure_not_output "$cli_re\r\n" "-thread-select, event on cli" | |
937 | kfail "gdb/20631" "thread-select, event on cli" | |
938 | } | |
939 | } | |
940 | ||
941 | # Idea for the future: selecting a thread in a different inferior. For now, | |
942 | # GDB doesn't show an inferior switch, but if it did, it would be a nice | |
943 | # place to test it. | |
944 | } | |
945 | ||
8354c62c | 946 | proc_with_prefix test_mi_stack_select_frame { mode } { |
9c36d954 AT |
947 | global gdb_main_spawn_id mi_spawn_id |
948 | ||
949 | with_test_prefix "thread 1.2" { | |
950 | reset_selection "1.2" | |
951 | flush_buffers | |
952 | ||
953 | # Do the '-stack-select-frame' command to select frame 1. | |
954 | ||
955 | set mi_re "\\^done" | |
956 | set cli_re [make_cli_re $mode -1 -1 1] | |
957 | ||
958 | with_spawn_id $mi_spawn_id { | |
959 | mi_gdb_test "-stack-select-frame 1" $mi_re "-stack-select-frame" | |
960 | } | |
961 | ||
962 | with_spawn_id $gdb_main_spawn_id { | |
963 | match_re_or_ensure_not_output "$cli_re\r\n" "-stack-select-frame, event on MI" | |
964 | } | |
965 | ||
966 | # Do the '-stack-select-frame' command to select the same frame. This time we don't | |
967 | # expect an event on CLI, since we won't actually change frame. | |
968 | ||
969 | set cli_re "" | |
970 | ||
971 | with_spawn_id $mi_spawn_id { | |
972 | mi_gdb_test "-stack-select-frame 1" $mi_re "-stack-select-frame again" | |
973 | } | |
974 | ||
975 | with_spawn_id $gdb_main_spawn_id { | |
976 | match_re_or_ensure_not_output $cli_re "-stack-select-frame again, event on MI" | |
977 | } | |
978 | } | |
979 | ||
980 | with_test_prefix "thread 1.3" { | |
981 | # Now, try the '-stack-select-frame' command on thread 3, which is | |
982 | # running if we are in non-stop mode. | |
983 | reset_selection "1.3" | |
984 | flush_buffers | |
985 | ||
986 | if {$mode == "all-stop"} { | |
987 | set mi_re "\\^done" | |
988 | set cli_re [make_cli_re $mode -1 -1 1] | |
989 | append cli_re "\r\n" | |
990 | } elseif {$mode == "non-stop"} { | |
991 | set cli_re "" | |
992 | set mi_re "\\^error,msg=\"Selected thread is running\\.\"" | |
993 | } | |
994 | ||
995 | with_spawn_id $mi_spawn_id { | |
996 | mi_gdb_test "-stack-select-frame 1" $mi_re "-stack-select-frame" | |
997 | } | |
998 | ||
999 | with_spawn_id $gdb_main_spawn_id { | |
1000 | match_re_or_ensure_not_output $cli_re "-stack-select-frame, event on MI" | |
1001 | } | |
1002 | } | |
1003 | } | |
1004 | ||
1005 | proc make_cli_in_mi_command { cli_in_mi_mode command } { | |
1006 | if { $cli_in_mi_mode == "direct" } { | |
1007 | return $command | |
1008 | } elseif { $cli_in_mi_mode == "interpreter-exec" } { | |
1009 | return "-interpreter-exec console \"$command\"" | |
1010 | } else { | |
1011 | error "Invalid value for CLI_IN_MI_MODE." | |
1012 | } | |
1013 | } | |
1014 | ||
1015 | # Test selecting the inferior using a CLI command in the MI channel. | |
1016 | ||
8354c62c | 1017 | proc_with_prefix test_cli_in_mi_inferior { mode cli_in_mi_mode } { |
9c36d954 AT |
1018 | global gdb_main_spawn_id mi_spawn_id |
1019 | ||
1020 | reset_selection "1.1" | |
1021 | flush_buffers | |
1022 | ||
1023 | set command [make_cli_in_mi_command $cli_in_mi_mode "inferior 2"] | |
1024 | ||
1025 | set mi_re [make_cli_in_mi_re $command $cli_in_mi_mode $mode 1 2 2.1 4 2] | |
1026 | set cli_re [make_cli_re $mode 2 "2.1" 2] | |
1027 | ||
1028 | with_spawn_id $mi_spawn_id { | |
1029 | mi_gdb_test $command $mi_re "select inferior" | |
1030 | } | |
1031 | ||
1032 | with_spawn_id $gdb_main_spawn_id { | |
1033 | match_re_or_ensure_not_output "$cli_re\r\n" "select inferior, event on CLI" | |
1034 | } | |
1035 | ||
1036 | # Do the 'inferior' command on the currently selected inferior. For now, | |
1037 | # GDB naively re-outputs everything. | |
1038 | with_spawn_id $mi_spawn_id { | |
1039 | mi_gdb_test $command $mi_re "select inferior again" | |
1040 | } | |
1041 | ||
1042 | with_spawn_id $gdb_main_spawn_id { | |
1043 | match_re_or_ensure_not_output $cli_re "select inferior again, event on CLI" | |
1044 | } | |
1045 | } | |
1046 | ||
1047 | # Test selecting the thread using a CLI command in the MI channel. | |
1048 | ||
8354c62c | 1049 | proc_with_prefix test_cli_in_mi_thread { mode cli_in_mi_mode } { |
9c36d954 AT |
1050 | global gdb_main_spawn_id mi_spawn_id |
1051 | ||
1052 | reset_selection "1.1" | |
1053 | flush_buffers | |
1054 | ||
1055 | with_test_prefix "thread 1.2" { | |
1056 | # Do the 'thread' command to select a stopped thread. | |
1057 | ||
1058 | set command [make_cli_in_mi_command $cli_in_mi_mode "thread 1.2"] | |
1059 | set mi_re [make_cli_in_mi_re $command $cli_in_mi_mode $mode 1 -1 1.2 2 0] | |
1060 | set cli_re [make_cli_re $mode -1 1.2 0] | |
1061 | ||
1062 | with_spawn_id $mi_spawn_id { | |
1063 | mi_gdb_test $command $mi_re "select thread" | |
1064 | } | |
1065 | ||
1066 | with_spawn_id $gdb_main_spawn_id { | |
1067 | match_re_or_ensure_not_output "$cli_re\r\n" "select thread, event on CLI" | |
1068 | } | |
1069 | ||
1070 | # Do the 'thread' command to select the same thread. We shouldn't | |
1071 | # receive an event on CLI, since we won't actually switch thread. | |
1072 | ||
1073 | set mi_re [make_cli_in_mi_re $command $cli_in_mi_mode $mode 0 -1 1.2 2 0] | |
1074 | set cli_re "" | |
1075 | ||
1076 | with_spawn_id $mi_spawn_id { | |
1077 | mi_gdb_test $command $mi_re "select thread again" | |
1078 | } | |
1079 | ||
1080 | with_spawn_id $gdb_main_spawn_id { | |
1081 | match_re_or_ensure_not_output $cli_re "select thread again, event on CLI" | |
1082 | } | |
1083 | ||
1084 | # Try the 'thread' command without arguments. | |
1085 | ||
1086 | set command [make_cli_in_mi_command $cli_in_mi_mode "thread"] | |
1087 | ||
1088 | set mi_re "${command}.*~\"\\\[Current thread is 1\\.2.*\\\]\\\\n\".*\\^done" | |
1089 | set cli_re "" | |
1090 | ||
1091 | with_spawn_id $mi_spawn_id { | |
1092 | mi_gdb_test $command $mi_re "thread without args" | |
1093 | } | |
1094 | ||
1095 | with_spawn_id $gdb_main_spawn_id { | |
1096 | match_re_or_ensure_not_output $cli_re "thread without args, event on CLI" | |
1097 | } | |
1098 | } | |
1099 | ||
1100 | with_test_prefix "thread 1.3" { | |
1101 | # Do the 'thread' command to select the third thread, stopped on | |
1102 | # all-stop, running on non-stop. | |
1103 | ||
1104 | set command [make_cli_in_mi_command $cli_in_mi_mode "thread 1.3"] | |
1105 | if { $mode == "all-stop" } { | |
1106 | set mi_re [make_cli_in_mi_re $command $cli_in_mi_mode $mode 1 -1 1.3 3 0] | |
1107 | set cli_re [make_cli_re $mode -1 "1.3" 0] | |
1108 | } else { | |
1109 | set mi_re [make_cli_in_mi_re $command $cli_in_mi_mode $mode 1 -1 1.3 3 -1] | |
1110 | set cli_re [make_cli_re $mode -1 "1.3" -1] | |
1111 | } | |
1112 | ||
1113 | with_spawn_id $mi_spawn_id { | |
1114 | mi_gdb_test $command $mi_re "select thread" | |
1115 | } | |
1116 | ||
1117 | with_spawn_id $gdb_main_spawn_id { | |
1118 | match_re_or_ensure_not_output "$cli_re\r\n" "select thread, event on CLI" | |
1119 | } | |
1120 | ||
1121 | # Do the 'thread' command to select the third thread again. Again, we | |
1122 | # shouldn't receive an event on MI. | |
1123 | ||
1124 | if { $mode == "all-stop" } { | |
1125 | set mi_re [make_cli_in_mi_re $command $cli_in_mi_mode $mode 0 -1 1.3 3 0] | |
1126 | } else { | |
1127 | set mi_re [make_cli_in_mi_re $command $cli_in_mi_mode $mode 0 -1 1.3 3 -1] | |
1128 | } | |
1129 | set cli_re "" | |
1130 | ||
1131 | with_spawn_id $mi_spawn_id { | |
1132 | mi_gdb_test $command $mi_re "select thread again" | |
1133 | } | |
1134 | ||
1135 | with_spawn_id $gdb_main_spawn_id { | |
1136 | match_re_or_ensure_not_output $cli_re "select thread again, event on CLI" | |
1137 | } | |
1138 | ||
1139 | # Try the 'thread' command without arguments. | |
1140 | ||
1141 | set command [make_cli_in_mi_command $cli_in_mi_mode "thread"] | |
1142 | ||
1143 | set mi_re "${command}.*~\"\\\[Current thread is 1\\.3.*\\\]\\\\n\".*\\^done" | |
1144 | set cli_re "" | |
1145 | ||
1146 | with_spawn_id $mi_spawn_id { | |
1147 | mi_gdb_test $command $mi_re "thread without args" | |
1148 | } | |
1149 | ||
1150 | with_spawn_id $gdb_main_spawn_id { | |
1151 | match_re_or_ensure_not_output $cli_re "thread without args, event on CLI" | |
1152 | } | |
1153 | } | |
1154 | ||
1155 | # Idea for the future: selecting a thread in a different inferior. For now, | |
1156 | # GDB doesn't show an inferior switch, but if it did, it would be a nice | |
1157 | # place to test it. | |
1158 | } | |
1159 | ||
1160 | # Test selecting the frame using a CLI command in the MI channel. | |
1161 | ||
8354c62c | 1162 | proc_with_prefix test_cli_in_mi_frame { mode cli_in_mi_mode } { |
9c36d954 AT |
1163 | global gdb_main_spawn_id mi_spawn_id |
1164 | ||
1165 | with_test_prefix "thread 1.2" { | |
1166 | reset_selection "1.2" | |
1167 | flush_buffers | |
1168 | ||
1169 | # Do the 'frame' command to select frame 1. | |
1170 | ||
1171 | set command [make_cli_in_mi_command $cli_in_mi_mode "frame 1"] | |
1172 | set cli_re [make_cli_re $mode -1 -1 1] | |
1173 | set mi_re [make_cli_in_mi_re $command $cli_in_mi_mode $mode 1 -1 -1 2 1] | |
1174 | ||
1175 | with_spawn_id $mi_spawn_id { | |
1176 | mi_gdb_test $command $mi_re "select frame 1" | |
1177 | } | |
1178 | ||
1179 | with_spawn_id $gdb_main_spawn_id { | |
1180 | match_re_or_ensure_not_output "$cli_re\r\n" "select frame 1, event on CLI" | |
1181 | } | |
1182 | ||
1183 | # Do the 'frame' command to select the same frame. This time we don't | |
1184 | # expect an event on MI, since we won't actually change frame. | |
1185 | ||
1186 | set mi_re [make_cli_in_mi_re $command $cli_in_mi_mode $mode 0 -1 -1 2 1] | |
1187 | set cli_re "" | |
1188 | ||
1189 | with_spawn_id $mi_spawn_id { | |
1190 | mi_gdb_test $command $mi_re "select frame 1 again" | |
1191 | } | |
1192 | ||
1193 | with_spawn_id $gdb_main_spawn_id { | |
1194 | match_re_or_ensure_not_output $cli_re "select frame 1 again, event on CLI" | |
1195 | } | |
1196 | ||
1197 | # Do the 'frame' command without arguments. We shouldn't see anything on MI. | |
1198 | ||
1199 | set command [make_cli_in_mi_command $cli_in_mi_mode "frame"] | |
1200 | set mi_re [make_cli_in_mi_re $command $cli_in_mi_mode $mode 0 -1 -1 2 1] | |
1201 | ||
1202 | with_spawn_id $mi_spawn_id { | |
1203 | mi_gdb_test $command $mi_re "frame without args" | |
1204 | } | |
1205 | ||
1206 | with_spawn_id $gdb_main_spawn_id { | |
1207 | match_re_or_ensure_not_output $cli_re "frame without args, event on CLI" | |
1208 | } | |
1209 | } | |
1210 | ||
1211 | with_test_prefix "thread 1.3" { | |
1212 | # Now, try the 'frame' command on thread 3, which is running if we are in | |
1213 | # non-stop mode. | |
1214 | reset_selection "1.3" | |
1215 | flush_buffers | |
1216 | ||
1217 | set command [make_cli_in_mi_command $cli_in_mi_mode "frame 1"] | |
1218 | if {$mode == "all-stop"} { | |
1219 | set cli_re [make_cli_re $mode -1 -1 1] | |
1220 | append cli_re "\r\n" | |
1221 | set mi_re [make_cli_in_mi_re $command $cli_in_mi_mode $mode 1 -1 -1 3 1] | |
1222 | } elseif {$mode == "non-stop"} { | |
1223 | set cli_re "" | |
1224 | set mi_re "\\^error,msg=\"Selected thread is running\\.\".*" | |
1225 | } | |
1226 | ||
1227 | with_spawn_id $mi_spawn_id { | |
1228 | mi_gdb_test $command $mi_re "select frame 1" | |
1229 | } | |
1230 | ||
1231 | with_spawn_id $gdb_main_spawn_id { | |
1232 | match_re_or_ensure_not_output $cli_re "select frame 1, event on CLI" | |
1233 | } | |
1234 | ||
1235 | # Do the 'frame' command without arguments. | |
1236 | ||
1237 | set command [make_cli_in_mi_command $cli_in_mi_mode "frame"] | |
1238 | if { $mode == "all-stop" } { | |
1239 | set mi_re [make_cli_in_mi_re $command $cli_in_mi_mode $mode 0 -1 -1 -1 1] | |
1240 | } else { | |
1241 | set mi_re "\\^error,msg=\"No stack\\.\"" | |
1242 | } | |
1243 | set cli_re "" | |
1244 | ||
1245 | with_spawn_id $mi_spawn_id { | |
1246 | mi_gdb_test $command $mi_re "frame without args" | |
1247 | } | |
1248 | ||
1249 | with_spawn_id $gdb_main_spawn_id { | |
1250 | match_re_or_ensure_not_output $cli_re "frame without args, event on CLI" | |
1251 | } | |
1252 | } | |
1253 | } | |
1254 | ||
1255 | foreach_with_prefix mode { "all-stop" "non-stop" } { | |
8354c62c | 1256 | test_setup $mode |
9c36d954 AT |
1257 | |
1258 | # Test selecting inferior, thread and frame from CLI | |
1259 | ||
8354c62c SM |
1260 | test_cli_inferior $mode |
1261 | test_cli_thread $mode | |
1262 | test_cli_frame $mode | |
1263 | test_cli_select_frame $mode | |
1264 | test_cli_up_down $mode | |
9c36d954 AT |
1265 | |
1266 | # Test selecting thread and frame from MI | |
1267 | ||
8354c62c SM |
1268 | test_mi_thread_select $mode |
1269 | test_mi_stack_select_frame $mode | |
9c36d954 AT |
1270 | |
1271 | # Test some CLI commands sent through MI, both with a "direct" command, | |
1272 | # such as "thread 1", and with -interpreter-exec, such as | |
1273 | # '-interpreter-exec console "thread 1"'. | |
1274 | ||
1275 | foreach_with_prefix exec_mode {"direct" "interpreter-exec"} { | |
8354c62c SM |
1276 | test_cli_in_mi_inferior $mode $exec_mode |
1277 | test_cli_in_mi_thread $mode $exec_mode | |
1278 | test_cli_in_mi_frame $mode $exec_mode | |
9c36d954 AT |
1279 | } |
1280 | } |