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