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