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