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