8a752b0c3e48ad02009c1528738a770dc707fff7
[deliverable/binutils-gdb.git] / gdb / testsuite / gdb.mi / user-selected-context-sync.exp
1 # Copyright 2016-2020 Free Software Foundation, Inc.
2
3 # This program is free software; you can redistribute it and/or modify
4 # it under the terms of the GNU General Public License as published by
5 # the Free Software Foundation; either version 3 of the License, or
6 # (at your option) any later version.
7 #
8 # This program is distributed in the hope that it will be useful,
9 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # GNU General Public License for more details.
12 #
13 # You should have received a copy of the GNU General Public License
14 # along with this program. If not, see <http://www.gnu.org/licenses/>.
15
16 # 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
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
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] {
45 untested "using gdb stub"
46 return
47 }
48
49 set compile_options "debug pthreads"
50 if {[build_executable $testfile.exp $testfile ${srcfile} ${compile_options}] == -1} {
51 untested "failed to compile"
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
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
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\"\}"
167
168 # Special frame for main thread.
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\"\}"
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
375 proc_with_prefix test_setup { mode } {
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 } {
405 fail "can't run to main"
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).
418 gdb_test "add-inferior" "Added inferior 2" "add inferior 2"
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
533 proc_with_prefix test_cli_inferior { mode } {
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
565 proc_with_prefix test_cli_thread { mode } {
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
669 proc_with_prefix test_cli_frame { mode } {
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
754 proc_with_prefix test_cli_select_frame { mode } {
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
816 proc_with_prefix test_cli_up_down { mode } {
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
851 proc_with_prefix test_mi_thread_select { mode } {
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
946 proc_with_prefix test_mi_stack_select_frame { mode } {
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
1017 proc_with_prefix test_cli_in_mi_inferior { mode cli_in_mi_mode } {
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
1049 proc_with_prefix test_cli_in_mi_thread { mode cli_in_mi_mode } {
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
1162 proc_with_prefix test_cli_in_mi_frame { mode cli_in_mi_mode } {
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" } {
1256 test_setup $mode
1257
1258 # Test selecting inferior, thread and frame from CLI
1259
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
1265
1266 # Test selecting thread and frame from MI
1267
1268 test_mi_thread_select $mode
1269 test_mi_stack_select_frame $mode
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"} {
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
1279 }
1280 }
This page took 0.055223 seconds and 3 git commands to generate.