# Copyright (C) 2019-2024 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 . import gdb class BadKey: def __repr__(self): return "Bad Key" class ReallyBadKey: def __repr__(self): return BadKey() class pycmd1(gdb.MICommand): def invoke(self, argv): if argv[0] == "int": return {"result": 42} elif argv[0] == "str": return {"result": "Hello world!"} elif argv[0] == "ary": return {"result": ["Hello", 42]} elif argv[0] == "dct": return {"result": {"hello": "world", "times": 42}} elif argv[0] == "bk1": return {"result": {BadKey(): "world"}} elif argv[0] == "bk2": return {"result": {1: "world"}} elif argv[0] == "bk3": return {"result": {ReallyBadKey(): "world"}} elif argv[0] == "tpl": return {"result": (42, "Hello")} elif argv[0] == "itr": return {"result": iter([1, 2, 3])} elif argv[0] == "nn1": return None elif argv[0] == "nn2": return {"result": [None]} elif argv[0] == "red": pycmd2("-pycmd") return None elif argv[0] == "nd1": return [1, 2, 3] elif argv[0] == "nd2": return 123 elif argv[0] == "nd3": return "abc" elif argv[0] == "ik1": return {"xxx yyy": 123} elif argv[0] == "ik2": return {"result": {"xxx yyy": 123}} elif argv[0] == "ik3": return {"xxx+yyy": 123} elif argv[0] == "ik4": return {"xxx.yyy": 123} elif argv[0] == "ik5": return {"123xxxyyy": 123} elif argv[0] == "empty_key": return {"": 123} elif argv[0] == "dash-key": return {"the-key": 123} elif argv[0] == "exp": raise gdb.GdbError() else: raise gdb.GdbError("Invalid parameter: %s" % argv[0]) class pycmd2(gdb.MICommand): def invoke(self, argv): if argv[0] == "str": return {"result": "Ciao!"} elif argv[0] == "red": pycmd1("-pycmd") raise gdb.GdbError("Command redefined but we failing anyway") elif argv[0] == "new": pycmd1("-pycmd-new") return None else: raise gdb.GdbError("Invalid parameter: %s" % argv[0]) # This class creates a command that returns a string, which is passed # when the command is created. class pycmd3(gdb.MICommand): def __init__(self, name, msg, top_level): super(pycmd3, self).__init__(name) self._msg = msg self._top_level = top_level def invoke(self, args): return {self._top_level: {"msg": self._msg}} # A command that is missing it's invoke method. class no_invoke(gdb.MICommand): def __init__(self, name): super(no_invoke, self).__init__(name) def free_invoke(obj, args): return {"result": args} # Run some test involving catching exceptions. It's easier to write # these as a Python function which is then called from the exp script. def run_exception_tests(): print("PASS") # Run some execute_mi tests. This is easier to do from Python. def run_execute_mi_tests(): # Install the command. cmd = pycmd1("-pycmd") # Pass in a representative subset of the pycmd1 keys, and then # check that the result via MI is the same as the result via a # direct Python call. Note that some results won't compare as # equal -- for example, a Python MI command can return a tuple, # but that will be translated to a Python list. for name in ("int", "str", "dct"): expect = cmd.invoke([name]) got = gdb.execute_mi("-pycmd", name) if expect != got: print("FAIL: saw " + repr(got) + ", but expected " + repr(expect)) return ok = False try: gdb.execute_mi("-pycmd", "exp") # Due to the "denaturation" problem, we have to expect a gdb.error # here and not a gdb.GdbError. except gdb.error: ok = True if not ok: print("FAIL: did not throw exception") print("PASS")