1 # Copyright (C) 2021-2024 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 # Create a TUI window in Python that responds to GDB event. Each 17 # event will trigger the TUI window to redraw itself. 18 # 19 # This test is checking how GDB behaves if the user first displays a 20 # Python based tui window, and then does 'tui disable'. At one point 21 # it was possible that GDB would try to redraw the tui window even 22 # though the tui should be disabled. 23 24 load_lib gdb-python.exp 25 require allow_tui_tests allow_python_tests 26 tuiterm_env 27 28 standard_testfile 29 30 set flags {} 31 lappend flags debug 32 lappend_include_file flags $srcdir/lib/attributes.h 33 34 if {[build_executable "failed to prepare" ${testfile} ${srcfile} $flags] == -1} { 35 return -1 36 } 37 38 clean_restart 39 40 # Copy the Python script to where the tests are being run. 41 set remote_python_file [gdb_remote_download host \ 42 ${srcdir}/${subdir}/${testfile}.py] 43 44 proc clean_restart_and_setup { prefix } { 45 global testfile 46 global remote_python_file 47 48 with_test_prefix $prefix { 49 50 Term::clean_restart 24 80 $testfile 51 52 # Now source the python script. 53 gdb_test_no_output "source ${remote_python_file}" \ 54 "source ${testfile}.py" 55 56 # Create a new layout making use of our new event window. 57 gdb_test_no_output "tui new-layout test events 1 cmd 1" 58 59 # Disable source code highlighting. 60 gdb_test_no_output "set style sources off" 61 62 if {![runto_main]} { 63 perror "test suppressed" 64 return 0 65 } 66 } 67 68 return 1 69 } 70 71 # Run the test. CLEANUP_PROPERLY is either true or false. This is 72 # used to set a flag in the Python code which controls whether the 73 # Python TUI window cleans up properly or not. 74 # 75 # When the Python window does not cleanup properly then it retains a 76 # cyclic reference to itself, this means that it is still possible for 77 # the object to try and redraw itself even when the tui is disabled. 78 proc run_test { cleanup_properly } { 79 80 if { ![clean_restart_and_setup "initial restart"] } { 81 unsupported "couldn't restart GDB" 82 return 83 } 84 85 if { $cleanup_properly } { 86 gdb_test_no_output "python cleanup_properly = True" 87 } else { 88 gdb_test_no_output "python cleanup_properly = False" 89 } 90 91 if {![Term::enter_tui]} { 92 unsupported "TUI not supported" 93 return 94 } 95 96 Term::command "layout test" 97 98 # Confirm that the events box is initially empty, then perform two 99 # actions that will add two events to the window. 100 Term::check_box_contents "no events yet" 0 0 80 16 "" 101 Term::command "next" 102 Term::check_box_contents "single stop event" 0 0 80 16 "stop" 103 Term::command "next" 104 Term::check_box_contents "two stop events" 0 0 80 16 \ 105 "stop\[^\n\]+\nstop" 106 107 # Now disable the tui, we should end up back at a standard GDB prompt. 108 Term::command "tui disable" 109 110 # Do something just so we know that the CLI is working. 111 gdb_test "print 1 + 1 + 1" " = 3" 112 113 # Now perform an action that would trigger an event. At one point 114 # there was a bug where the TUI window might try to redraw itself. 115 # This is why we use GDB_TEST_MULTIPLE here, so we can spot the tui 116 # window title and know that things have gone wrong. 117 gdb_test_multiple "next" "next at cli" { 118 -re -wrap "func \\(3\\);" { 119 pass $gdb_test_name 120 } 121 122 -re "This Is The Event Window" { 123 fail $gdb_test_name 124 } 125 } 126 127 # Do something just so we know that the CLI is still working. This 128 # also serves to drain the expect buffer if the above test failed. 129 gdb_test "print 2 + 2 + 2" " = 6" 130 131 # Now tell the Python code not to check the window is valid before 132 # calling render. The result is the Python code will try to draw to 133 # the screen. This should throw a Python exception. 134 gdb_test_no_output "python perform_valid_check = False" 135 set exception_pattern "\r\nPython Exception\[^\n\r\]+TUI window is invalid\[^\n\r\]+" 136 gdb_test_multiple "next" "next at cli, with an exception" { 137 -re -wrap "func \\(4\\);${exception_pattern}" { 138 pass $gdb_test_name 139 } 140 141 -re "This Is The Event Window" { 142 fail $gdb_test_name 143 } 144 } 145 146 # Do something just so we know that the CLI is still working. This 147 # also serves to drain the expect buffer if the above test failed. 148 gdb_test "print 3 + 3 + 3" " = 9" 149 150 # Set 'update_title' to True. The Python script will now try to set 151 # the window title when an event occurs (instead of trying to redraw 152 # the window). As the window is still not displayed this will again 153 # throw an exception. 154 gdb_test_no_output "python update_title = True" 155 gdb_test_multiple "next" "next at cli, with an exception for setting the title" { 156 -re -wrap "func \\(5\\);${exception_pattern}" { 157 pass $gdb_test_name 158 } 159 160 -re "This Is The Event Window" { 161 fail $gdb_test_name 162 } 163 } 164 165 # We need to perform a restart here as the TUI library we use for 166 # testing doesn't seem to handle output in the command window 167 # correctly, and gets really upset as we approach the bottom of 168 # the screen. 169 # 170 # Restart GDB, enable tui mode, select the new layout. Then 171 # disable tui and re-enable again. 172 if { ![clean_restart_and_setup "second restart"] } { 173 unsupported "couldn't restart GDB" 174 return 175 } 176 177 with_test_prefix "enter tui again" { 178 if {![Term::enter_tui]} { 179 unsupported "TUI not supported" 180 return 181 } 182 } 183 184 Term::command "layout test" 185 Term::command "tui disable" 186 187 send_gdb "tui enable\n" 188 gdb_assert { [Term::wait_for "^$::gdb_prompt tui disable"] } "TUI renabled" 189 190 Term::check_box "check for python window" 0 0 80 16 191 } 192 193 # Run the tests in both cleanup modes. 194 foreach_with_prefix cleanup_properly { True False } { 195 run_test $cleanup_properly 196 } 197