xref: /netbsd-src/external/gpl3/gdb.old/dist/gdb/testsuite/gdb.mi/user-selected-context-sync.exp (revision 796c32c94f6e154afc9de0f63da35c91bb739b45)
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}
1286