From: Tom de Vries Date: Sat, 4 Jan 2025 11:10:42 +0000 (+0100) Subject: [gdb/testsuite] Add gdb.python/py-commands-breakpoint.exp X-Git-Tag: binutils-2_44~265 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=deea250ab63d84a58125ca0963c625b50468a578;p=thirdparty%2Fbinutils-gdb.git [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 --- 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 00000000000..d719922db27 --- /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 . */ + +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 00000000000..d0771bdfaf7 --- /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 . + +# 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 00000000000..dbe7676d6ba --- /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 . + +# 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