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