xref: /netbsd-src/external/gpl3/gdb.old/dist/gdb/testsuite/gdb.mi/user-selected-context-sync.exp (revision cb63e24e8d6aae7ddac1859a9015f48b1d8bd90e)
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.
33if [gdb_debug_enabled] {
34    untested "debug is enabled"
35    return 0
36}
37
38load_lib mi-support.exp
39
40standard_testfile
41
42# Multiple inferiors are needed, therefore only native gdb and extended
43# gdbserver modes are supported.
44if [use_gdb_stub] {
45    untested "using gdb stub"
46    return
47}
48
49set compile_options "debug pthreads"
50if {[build_executable $testfile.exp $testfile ${srcfile} ${compile_options}] == -1} {
51    untested "failed to compile"
52    return -1
53}
54
55set main_break_line [gdb_get_line_number "main break line"]
56set thread_loop_line [gdb_get_line_number "thread loop line"]
57set 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
64proc 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
90proc 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
150proc 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
214proc 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
263proc 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
282proc 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
375proc_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 on connection .*" "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
451proc 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
470proc 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
490proc 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
515proc 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
533proc_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
565proc_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
669proc_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
754proc_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
816proc_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
851proc_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
946proc_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
1005proc 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
1017proc_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
1049proc_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
1162proc_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
1255foreach_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}
1281