| # Copyright (C) 2015-2021 Free Software Foundation, Inc. |
| |
| # This program is free software; you can redistribute it and/or modify |
| # it under the terms of the GNU General Public License as published by |
| # the Free Software Foundation; either version 3 of the License, or |
| # (at your option) any later version. |
| # |
| # This program is distributed in the hope that it will be useful, |
| # but WITHOUT ANY WARRANTY; without even the implied warranty of |
| # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| # GNU General Public License for more details. |
| # |
| # You should have received a copy of the GNU General Public License |
| # along with this program. If not, see <http://www.gnu.org/licenses/>. |
| |
| # Check that "gdb -batch -ex run" does not leave the terminal in the |
| # wrong state. |
| |
| standard_testfile |
| |
| if {[build_executable "failed to prepare" $testfile $srcfile debug] == -1} { |
| return -1 |
| } |
| |
| set file_arg $binfile |
| if [is_remote host] { |
| set file_arg [remote_download host $file_arg] |
| } |
| |
| # The shell's prompt. |
| set shell_prompt_ps1 "gdb-subshell$ " |
| set shell_prompt_re [string_to_regexp $shell_prompt_ps1] |
| |
| # Spawn shell. Returns true on success, false otherwise. |
| |
| proc spawn_shell {} { |
| global shell_prompt_ps1 shell_prompt_re |
| |
| set res [remote_spawn host "/bin/sh"] |
| if { $res < 0 || $res == "" } { |
| unsupported "spawning shell failed." |
| return 0 |
| } |
| |
| send_gdb "PS1=\"$shell_prompt_ps1\"\n" |
| |
| # Try to match: |
| # PS1="gdb-subshell$ "^M |
| # $ gdb-subshell$ |
| # or: |
| # PS1="gdb-subshell$ "^M |
| # sh-4.4$ PS1="gdb-subshell$ "^M |
| # gdb-subshell$ |
| set gotit 0 |
| set test "spawn shell" |
| gdb_expect { |
| -re "PS1=\"$shell_prompt_re" { |
| exp_continue |
| } |
| -re "$shell_prompt_re$" { |
| pass $test |
| set gotit 1 |
| } |
| timeout { |
| fail "$test (timeout)" |
| } |
| eof { |
| fail "$test (eof)" |
| } |
| } |
| |
| return $gotit |
| } |
| |
| # Exit the shell. |
| |
| proc exit_shell {} { |
| global shell_prompt_re |
| |
| set test "exit shell" |
| send_gdb "exit\n" |
| gdb_expect { |
| timeout { |
| fail "$test (timeout)" |
| return 0 |
| } |
| eof { |
| pass "$test" |
| } |
| } |
| if ![is_remote host] { |
| remote_close host |
| } |
| } |
| |
| # Run "stty" and store the output in $result. Returns true on |
| # success, false otherwise. |
| |
| proc run_stty {message result} { |
| global shell_prompt_re |
| |
| upvar $result output |
| |
| send_gdb "stty || echo \"not found\"\n" |
| set gotit 0 |
| gdb_expect { |
| -re "not found.*not found.*$shell_prompt_re$" { |
| pass "$message (not found)" |
| } |
| -re "(.*)$shell_prompt_re$" { |
| set output $expect_out(1,string) |
| set gotit 1 |
| pass $message |
| } |
| timeout { |
| fail "$message (timeout)" |
| } |
| eof { |
| fail "$message (eof)" |
| } |
| } |
| return $gotit |
| } |
| |
| # Check that "gdb -batch -ex run" does not leave the terminal in the |
| # wrong state. |
| |
| proc test_terminal_settings_preserved {} { |
| global file_arg |
| global GDB INTERNAL_GDBFLAGS GDBFLAGS |
| global gdb_prompt |
| global shell_prompt_re |
| |
| if ![spawn_shell] { |
| return |
| } |
| |
| set stty_supported [run_stty "stty before" stty_before] |
| |
| set test "gdb -batch -ex run" |
| append EXTRA_GDBFLAGS "-batch" |
| append EXTRA_GDBFLAGS " -ex \"set height unlimited\"" |
| append EXTRA_GDBFLAGS " -ex \"start\"" |
| append EXTRA_GDBFLAGS " --args \"$file_arg\"" |
| send_gdb "$GDB $INTERNAL_GDBFLAGS $GDBFLAGS $EXTRA_GDBFLAGS [host_info gdb_opts]\n" |
| gdb_expect { |
| -re "Don't know how to run.*$shell_prompt_re$" { |
| unsupported $test |
| } |
| -re "$gdb_prompt $" { |
| # -batch implies no GDB prompt. |
| fail $test |
| } |
| -re "Temporary breakpoint .*$shell_prompt_re$" { |
| pass $test |
| } |
| timeout { |
| fail "$test (timeout)" |
| } |
| eof { |
| fail "$test (eof)" |
| } |
| } |
| |
| set test "echo test_echo" |
| send_gdb "echo test_echo\n" |
| gdb_expect { |
| -re "^echo test_echo\r\ntest_echo\r\n.*$shell_prompt_re$" { |
| pass $test |
| } |
| timeout { |
| fail "$test (timeout)" |
| } |
| eof { |
| fail "$test (eof)" |
| } |
| } |
| |
| set test "terminal settings preserved" |
| if $stty_supported { |
| run_stty "stty after" stty_after |
| |
| gdb_assert [string equal $stty_before $stty_after] $test |
| } else { |
| unsupported "$test (no stty)" |
| } |
| |
| exit_shell |
| } |
| |
| # Send the quit command to GDB and make sure it exits. |
| |
| proc send_quit_command { test_name } { |
| global shell_prompt_re |
| |
| set test $test_name |
| send_gdb "quit\n" |
| gdb_expect { |
| -re "(y or n)" { |
| send_gdb "y\n" |
| exp_continue |
| } |
| -re ".*$shell_prompt_re$" { |
| pass $test |
| return |
| } |
| timeout { |
| fail "$test (timeout)" |
| return 0 |
| } |
| eof { |
| fail "$test (eof)" |
| return 0 |
| } |
| } |
| } |
| |
| # Check that quitting from the CLI via the "quit" command does not leave the |
| # terminal in the wrong state. The GDB commands CMDS are executed before |
| # quitting. |
| |
| proc test_terminal_settings_preserved_after_cli_exit { cmds } { |
| global file_arg |
| global GDB INTERNAL_GDBFLAGS GDBFLAGS |
| global gdb_prompt |
| global shell_prompt_re |
| |
| if ![spawn_shell] { |
| return |
| } |
| |
| set saved_gdbflags $GDBFLAGS |
| |
| set stty_supported [run_stty "stty before" stty_before] |
| |
| set test "start gdb" |
| send_gdb "$GDB $INTERNAL_GDBFLAGS $GDBFLAGS [host_info gdb_opts] --args \"$file_arg\"\n" |
| gdb_expect { |
| -re "$gdb_prompt $" { |
| pass $test |
| } |
| timeout { |
| fail "$test (timeout)" |
| } |
| eof { |
| fail "$test (eof)" |
| } |
| } |
| |
| foreach cmd $cmds { |
| set test "run command $cmd" |
| send_gdb "$cmd\n" |
| gdb_expect { |
| -re "$gdb_prompt $" { |
| pass $test |
| } |
| timeout { |
| fail "$test (timeout)" |
| } |
| eof { |
| fail "$test (eof)" |
| } |
| } |
| } |
| |
| send_quit_command "quit gdb" |
| |
| set test "terminal settings preserved" |
| if $stty_supported { |
| run_stty "stty after" stty_after |
| |
| gdb_assert [string equal $stty_before $stty_after] $test |
| } else { |
| unsupported "$test (no stty)" |
| } |
| |
| exit_shell |
| } |
| |
| # Check that sending SIGTERM kills GDB and does not leave the terminal in the |
| # wrong state. |
| |
| proc test_terminal_settings_preserved_after_sigterm { } { |
| global file_arg |
| global GDB INTERNAL_GDBFLAGS GDBFLAGS |
| global gdb_prompt |
| global shell_prompt_re |
| |
| # On Windows, GDB's "shell" command spawns cmd.exe, which does not |
| # understand PPID. So we're out of luck even if the test harness |
| # uses a remote_exec shell with a working "kill" command. |
| if [ishost *-*-mingw*] { |
| return |
| } |
| |
| if ![spawn_shell] { |
| return |
| } |
| |
| set saved_gdbflags $GDBFLAGS |
| |
| set stty_supported [run_stty "stty before" stty_before] |
| |
| set test "start gdb" |
| send_gdb "$GDB $INTERNAL_GDBFLAGS $GDBFLAGS [host_info gdb_opts]\n" |
| gdb_expect { |
| -re "$gdb_prompt $" { |
| pass $test |
| } |
| timeout { |
| fail "$test (timeout)" |
| } |
| eof { |
| fail "$test (eof)" |
| } |
| } |
| |
| # Retrieve the pid of gdb with the gdb command "shell echo $PPID" |
| set gdb_pid -1 |
| set test "run shell echo \$PPID" |
| send_gdb "shell echo \$PPID\n" |
| gdb_expect { |
| -re ".*\r\n(\\d+)\r\n$gdb_prompt $" { |
| set gdb_pid $expect_out(1,string) |
| pass $test |
| } |
| -re ".*\r\n\r\n$gdb_prompt $" { |
| fail "$test (no \$PPID)" |
| } |
| timeout { |
| fail "$test (timeout)" |
| } |
| eof { |
| fail "$test (eof)" |
| } |
| } |
| |
| set test "kill gdb with SIGTERM" |
| if { $gdb_pid == -1 } { |
| fail "$test (no pid)" |
| send_quit_command "quit gdb" |
| } else { |
| remote_exec host "kill -TERM $gdb_pid" |
| set gdb_killed 0 |
| gdb_expect { |
| -re ".*$shell_prompt_re$" { |
| pass $test |
| set gdb_killed 1 |
| } |
| default { |
| fail "$test (did not quit)" |
| } |
| } |
| |
| if !$gdb_killed { |
| send_quit_command "quit gdb" |
| } |
| } |
| |
| set test "terminal settings preserved" |
| if $stty_supported { |
| run_stty "stty after" stty_after |
| |
| gdb_assert [string equal $stty_before $stty_after] $test |
| } else { |
| unsupported "$test (no stty)" |
| } |
| |
| exit_shell |
| } |
| |
| with_test_prefix "batch run" { |
| test_terminal_settings_preserved |
| } |
| |
| with_test_prefix "cli exit" { |
| test_terminal_settings_preserved_after_cli_exit { } |
| } |
| |
| with_test_prefix "cli exit after start cmd" { |
| test_terminal_settings_preserved_after_cli_exit { "start" } |
| } |
| |
| with_test_prefix "cli exit after run cmd" { |
| test_terminal_settings_preserved_after_cli_exit { "run" } |
| } |
| |
| with_test_prefix "cli exit after SIGTERM" { |
| test_terminal_settings_preserved_after_sigterm |
| } |