blob: 1f042097a0669ae41a54a56eeab2d74201769c48 [file] [log] [blame]
# 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
}