diff options
author | Tom de Vries <tdevries@suse.de> | 2025-01-04 12:10:42 +0100 |
---|---|---|
committer | Tom de Vries <tdevries@suse.de> | 2025-01-04 12:10:42 +0100 |
commit | deea250ab63d84a58125ca0963c625b50468a578 (patch) | |
tree | 4b8d6ede1dcfe638a5154bb71799d9b9b2c4d721 | |
parent | 09859118ffc86b311d47aa461f722a720045e049 (diff) | |
download | gdb-deea250ab63d84a58125ca0963c625b50468a578.zip gdb-deea250ab63d84a58125ca0963c625b50468a578.tar.gz gdb-deea250ab63d84a58125ca0963c625b50468a578.tar.bz2 |
[gdb/testsuite] Add gdb.python/py-commands-breakpoint.exp
A recent discussion about what commands are allowed during
gdb.Breakpoint.stop, made me wonder if there would be less restrictions if
we'd do those commands as part of a breakpoint command list instead.
Attribute gdb.Breakpoint.commands is a string with gdb commands, so I
tried implementing a new class PyCommandsBreakpoint, derived from
gdb.Breakpoint, that supports a py_commands method.
My original idea was to forbid setting PyCommandsBreakpoint.commands, and do:
...
def py_commands(self):
print("VAR: %d" % self.var)
self.var += 1
gdb.execute("continue")
...
but as it turns out 'gdb.execute("continue")' does not behave the same way as
continue. I've filed PR python/32454 about this.
So the unsatisfactory solution is to first execute
PyCommandsBreakpoint.py_commands:
...
def py_commands(self):
print("VAR: %d" % self.var)
self.var += 1
...
and then:
...
self.commands = "continue"
...
I was hoping for a better outcome, but having done the work of writing this, I
suppose it has use as a test-case, perhaps also as an example of how to work
around PR python/32454.
Tested on x86_64-linux.
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=32454
-rw-r--r-- | gdb/testsuite/gdb.python/py-commands-breakpoint.c | 31 | ||||
-rw-r--r-- | gdb/testsuite/gdb.python/py-commands-breakpoint.exp | 45 | ||||
-rw-r--r-- | gdb/testsuite/gdb.python/py-commands-breakpoint.py | 59 |
3 files changed, 135 insertions, 0 deletions
diff --git a/gdb/testsuite/gdb.python/py-commands-breakpoint.c b/gdb/testsuite/gdb.python/py-commands-breakpoint.c new file mode 100644 index 0000000..d719922 --- /dev/null +++ b/gdb/testsuite/gdb.python/py-commands-breakpoint.c @@ -0,0 +1,31 @@ +/* This testcase is part of GDB, the GNU debugger. + + Copyright 2025 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/>. */ + +static void +test (void) +{ +} + +int +main (void) +{ + test (); + test (); + test (); + + return 0; +} diff --git a/gdb/testsuite/gdb.python/py-commands-breakpoint.exp b/gdb/testsuite/gdb.python/py-commands-breakpoint.exp new file mode 100644 index 0000000..d0771bd --- /dev/null +++ b/gdb/testsuite/gdb.python/py-commands-breakpoint.exp @@ -0,0 +1,45 @@ +# Copyright (C) 2025 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/>. + +# This file is part of the GDB testsuite. + +load_lib gdb-python.exp + +require allow_python_tests + +standard_testfile .c .py + +if { [prepare_for_testing "failed to prepare" $testfile $srcfile] } { + return -1 +} + +if { ![runto_main] } { + return 0 +} + +set host_python_file \ + [gdb_remote_download host $srcdir/$subdir/$srcfile2] + +gdb_test_no_output "source $host_python_file" \ + "source python file" + +gdb_test "python TestBreakpoint()" \ + "Breakpoint $decimal .*" + +gdb_test "continue" \ + [multi_line \ + "VAR: 1" \ + "VAR: 2" \ + "VAR: 3"] diff --git a/gdb/testsuite/gdb.python/py-commands-breakpoint.py b/gdb/testsuite/gdb.python/py-commands-breakpoint.py new file mode 100644 index 0000000..dbe7676 --- /dev/null +++ b/gdb/testsuite/gdb.python/py-commands-breakpoint.py @@ -0,0 +1,59 @@ +# Copyright (C) 2025 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/>. + +# This file is part of the GDB testsuite. + +import gdb + + +class PyCommandsBreakpoint(gdb.Breakpoint): + bp_dict = dict() + + def __init__(self, *args, **kwargs): + gdb.Breakpoint.__init__(self, *args, **kwargs) + PyCommandsBreakpoint.bp_dict[self.number] = self + self.commands = "" + + @staticmethod + def run_py_commands(num): + bp = PyCommandsBreakpoint.bp_dict[num] + if hasattr(bp, "py_commands"): + bp.py_commands() + + def __setattr__(self, name, value): + if name == "commands": + l = ["python PyCommandsBreakpoint.run_py_commands(%d)" % self.number] + if value != "": + l.append(value) + value = "\n".join(l) + + super().__setattr__(name, value) + + +class TestBreakpoint(PyCommandsBreakpoint): + def __init__(self): + PyCommandsBreakpoint.__init__(self, spec="test") + self.var = 1 + self.commands = "continue" + self.silent = True + + def stop(self): + if self.var == 3: + self.commands = "" + return True + + def py_commands(self): + print("VAR: %d" % self.var) + self.var += 1 |