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