diff options
-rw-r--r-- | gdb/testsuite/gdb.python/tui-window-factory.exp | 73 | ||||
-rw-r--r-- | gdb/testsuite/gdb.python/tui-window-factory.py | 48 | ||||
-rw-r--r-- | gdb/tui/tui-layout.c | 8 |
3 files changed, 129 insertions, 0 deletions
diff --git a/gdb/testsuite/gdb.python/tui-window-factory.exp b/gdb/testsuite/gdb.python/tui-window-factory.exp new file mode 100644 index 0000000..99f9fbb --- /dev/null +++ b/gdb/testsuite/gdb.python/tui-window-factory.exp @@ -0,0 +1,73 @@ +# Copyright (C) 2023 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/>. + +# Test that GDB correctly deallocates the window factory object (a) +# when a window factory is replaced, and (b) during GDB shutdown. +# +# This test also ensures that when a new window is registered (via the +# Python API) with the same name as an existing window, then the +# previous window is replaced. + +load_lib gdb-python.exp + +tuiterm_env + +clean_restart + +require allow_tui_tests allow_python_tests + +set pyfile [gdb_remote_download host \ + ${srcdir}/${subdir}/${gdb_test_file_name}.py] + +Term::clean_restart 24 80 +Term::prepare_for_tui + +gdb_test "source ${pyfile}" "Python script imported" \ + "import python scripts" + +gdb_test "python register_window_factory('msg_1')" \ + "Entering TestWindowFactory\\.__init__: msg_1" + +gdb_test "python register_window_factory('msg_2')" \ + [multi_line \ + "Entering TestWindowFactory\\.__init__: msg_2" \ + "Entering TestWindowFactory\\.__del__: msg_1"] + +gdb_test_no_output "tui new-layout test test_window 1 cmd 1 status 1" + +# Load the custom window layout and ensure that the correct window +# factory was used. +with_test_prefix "msg_2" { + Term::command_no_prompt_prefix "layout test" + Term::check_box_contents "check test_window box" 0 0 80 15 \ + "TestWindow \\(msg_2\\)" +} + +# Replace the existing window factory with a new one, then switch +# layouts so that GDB recreates the window, and check that the new +# window factory was used. +with_test_prefix "msg_3" { + Term::command "python register_window_factory('msg_3')" + Term::check_region_contents "check for python output" \ + 0 18 80 2 \ + [multi_line \ + "Entering TestWindowFactory.__init__: msg_3\\s+" \ + "Entering TestWindowFactory.__del__: msg_2"] + Term::command "layout src" + Term::command "layout test" + + Term::check_box_contents "check test_window box" 0 0 80 15 \ + "TestWindow \\(msg_3\\)" +} diff --git a/gdb/testsuite/gdb.python/tui-window-factory.py b/gdb/testsuite/gdb.python/tui-window-factory.py new file mode 100644 index 0000000..d1254e7 --- /dev/null +++ b/gdb/testsuite/gdb.python/tui-window-factory.py @@ -0,0 +1,48 @@ +# Copyright (C) 2023 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/>. + + +class TestWindow: + def __init__(self, tui_win, msg): + self.msg = msg + self.tui_win = tui_win + print("Entering TestWindow.__init__: %s" % self.msg) + + def render(self): + self.tui_win.erase() + self.tui_win.write("TestWindow (%s)" % self.msg) + + def __del__(self): + print("Entering TestWindow.__del__: %s" % self.msg) + + +class TestWindowFactory: + def __init__(self, msg): + self.msg = msg + print("Entering TestWindowFactory.__init__: %s" % self.msg) + + def __call__(self, tui_win): + print("Entering TestWindowFactory.__call__: %s" % self.msg) + return TestWindow(tui_win, self.msg) + + def __del__(self): + print("Entering TestWindowFactory.__del__: %s" % self.msg) + + +def register_window_factory(msg): + gdb.register_window_type("test_window", TestWindowFactory(msg)) + + +print("Python script imported") diff --git a/gdb/tui/tui-layout.c b/gdb/tui/tui-layout.c index ecdcd48..ba7ec89 100644 --- a/gdb/tui/tui-layout.c +++ b/gdb/tui/tui-layout.c @@ -427,6 +427,14 @@ tui_register_window (const char *name, window_factory &&factory) if (!ISALPHA (name_copy[0])) error (_("window name must start with a letter, not '%c'"), name_copy[0]); + /* We already check above for all the builtin window names. If we get + this far then NAME must be a user defined window. Remove any existing + factory and replace it with this new version. */ + + auto iter = known_window_types->find (name); + if (iter != known_window_types->end ()) + known_window_types->erase (iter); + known_window_types->emplace (std::move (name_copy), std::move (factory)); } |