1 # Copyright (C) 2019-2024 Free Software Foundation, Inc. 2 # This program is free software; you can redistribute it and/or modify 3 # it under the terms of the GNU General Public License as published by 4 # the Free Software Foundation; either version 3 of the License, or 5 # (at your option) any later version. 6 # 7 # This program is distributed in the hope that it will be useful, 8 # but WITHOUT ANY WARRANTY; without even the implied warranty of 9 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 10 # GNU General Public License for more details. 11 # 12 # You should have received a copy of the GNU General Public License 13 # along with this program. If not, see <http://www.gnu.org/licenses/>. 14 15 import gdb 16 17 18 class BadKey: 19 def __repr__(self): 20 return "Bad Key" 21 22 23 class ReallyBadKey: 24 def __repr__(self): 25 return BadKey() 26 27 28 class pycmd1(gdb.MICommand): 29 def invoke(self, argv): 30 if argv[0] == "int": 31 return {"result": 42} 32 elif argv[0] == "str": 33 return {"result": "Hello world!"} 34 elif argv[0] == "ary": 35 return {"result": ["Hello", 42]} 36 elif argv[0] == "dct": 37 return {"result": {"hello": "world", "times": 42}} 38 elif argv[0] == "bk1": 39 return {"result": {BadKey(): "world"}} 40 elif argv[0] == "bk2": 41 return {"result": {1: "world"}} 42 elif argv[0] == "bk3": 43 return {"result": {ReallyBadKey(): "world"}} 44 elif argv[0] == "tpl": 45 return {"result": (42, "Hello")} 46 elif argv[0] == "itr": 47 return {"result": iter([1, 2, 3])} 48 elif argv[0] == "nn1": 49 return None 50 elif argv[0] == "nn2": 51 return {"result": [None]} 52 elif argv[0] == "red": 53 pycmd2("-pycmd") 54 return None 55 elif argv[0] == "nd1": 56 return [1, 2, 3] 57 elif argv[0] == "nd2": 58 return 123 59 elif argv[0] == "nd3": 60 return "abc" 61 elif argv[0] == "ik1": 62 return {"xxx yyy": 123} 63 elif argv[0] == "ik2": 64 return {"result": {"xxx yyy": 123}} 65 elif argv[0] == "ik3": 66 return {"xxx+yyy": 123} 67 elif argv[0] == "ik4": 68 return {"xxx.yyy": 123} 69 elif argv[0] == "ik5": 70 return {"123xxxyyy": 123} 71 elif argv[0] == "empty_key": 72 return {"": 123} 73 elif argv[0] == "dash-key": 74 return {"the-key": 123} 75 elif argv[0] == "exp": 76 raise gdb.GdbError() 77 else: 78 raise gdb.GdbError("Invalid parameter: %s" % argv[0]) 79 80 81 class pycmd2(gdb.MICommand): 82 def invoke(self, argv): 83 if argv[0] == "str": 84 return {"result": "Ciao!"} 85 elif argv[0] == "red": 86 pycmd1("-pycmd") 87 raise gdb.GdbError("Command redefined but we failing anyway") 88 elif argv[0] == "new": 89 pycmd1("-pycmd-new") 90 return None 91 else: 92 raise gdb.GdbError("Invalid parameter: %s" % argv[0]) 93 94 95 # This class creates a command that returns a string, which is passed 96 # when the command is created. 97 class pycmd3(gdb.MICommand): 98 def __init__(self, name, msg, top_level): 99 super(pycmd3, self).__init__(name) 100 self._msg = msg 101 self._top_level = top_level 102 103 def invoke(self, args): 104 return {self._top_level: {"msg": self._msg}} 105 106 107 # A command that is missing it's invoke method. 108 class no_invoke(gdb.MICommand): 109 def __init__(self, name): 110 super(no_invoke, self).__init__(name) 111 112 113 def free_invoke(obj, args): 114 return {"result": args} 115 116 117 # Run some test involving catching exceptions. It's easier to write 118 # these as a Python function which is then called from the exp script. 119 def run_exception_tests(): 120 print("PASS") 121 122 123 # Run some execute_mi tests. This is easier to do from Python. 124 def run_execute_mi_tests(): 125 # Install the command. 126 cmd = pycmd1("-pycmd") 127 # Pass in a representative subset of the pycmd1 keys, and then 128 # check that the result via MI is the same as the result via a 129 # direct Python call. Note that some results won't compare as 130 # equal -- for example, a Python MI command can return a tuple, 131 # but that will be translated to a Python list. 132 for name in ("int", "str", "dct"): 133 expect = cmd.invoke([name]) 134 got = gdb.execute_mi("-pycmd", name) 135 if expect != got: 136 print("FAIL: saw " + repr(got) + ", but expected " + repr(expect)) 137 return 138 ok = False 139 try: 140 gdb.execute_mi("-pycmd", "exp") 141 # Due to the "denaturation" problem, we have to expect a gdb.error 142 # here and not a gdb.GdbError. 143 except gdb.error: 144 ok = True 145 if not ok: 146 print("FAIL: did not throw exception") 147 print("PASS") 148