# Copyright (C) 2015-2017 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 . # 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_re "\[$#\] " # Spawn shell. Returns true on success, false otherwise. proc spawn_shell {} { global shell_prompt_re set res [remote_spawn host "/bin/sh"] if { $res < 0 || $res == "" } { unsupported "Spawning shell failed." return 0 } set gotit 0 set test "spawn shell" gdb_expect { -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 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 }