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 # Test custom MI commands implemented in Python. 16 1.1 christos 17 1.1 christos load_lib gdb-python.exp 18 1.1 christos load_lib mi-support.exp 19 1.1 christos set MIFLAGS "-i=mi" 20 1.1 christos 21 1.1 christos gdb_exit 22 1.1 christos if {[mi_gdb_start]} { 23 1.1 christos return 24 1.1 christos } 25 1.1 christos 26 1.1 christos if {[lsearch -exact [mi_get_features] python] < 0} { 27 1.1 christos unsupported "python support is disabled" 28 1.1 christos return -1 29 1.1 christos } 30 1.1 christos 31 1.1 christos standard_testfile 32 1.1 christos 33 1.1 christos mi_gdb_test "set python print-stack full" \ 34 1.1 christos ".*\\^done" \ 35 1.1 christos "set python print-stack full" 36 1.1 christos 37 1.1 christos mi_gdb_test "source ${srcdir}/${subdir}/${testfile}.py" \ 38 1.1 christos ".*\\^done" \ 39 1.1 christos "load python file" 40 1.1 christos 41 1.1 christos mi_gdb_test "python pycmd1('-pycmd')" \ 42 1.1 christos ".*\\^done" \ 43 1.1 christos "define -pycmd MI command" 44 1.1 christos 45 1.1 christos mi_gdb_test "-pycmd int" \ 46 1.1 christos "\\^done,result=\"42\"" \ 47 1.1 christos "-pycmd int" 48 1.1 christos 49 1.1 christos mi_gdb_test "-pycmd str" \ 50 1.1 christos "\\^done,result=\"Hello world!\"" \ 51 1.1 christos "-pycmd str" 52 1.1 christos 53 1.1 christos mi_gdb_test "-pycmd ary" \ 54 1.1 christos "\\^done,result=\\\[\"Hello\",\"42\"\\\]" \ 55 1.1 christos "-pycmd ary" 56 1.1 christos 57 1.1 christos set re_order1 "\\^done,result={hello=\"world\",times=\"42\"}" 58 1.1 christos set re_order2 "\\^done,result={times=\"42\",hello=\"world\"}" 59 1.1 christos mi_gdb_test "-pycmd dct" \ 60 1.1 christos "($re_order1|$re_order2)" \ 61 1.1 christos "-pycmd dct" 62 1.1 christos 63 1.1 christos mi_gdb_test "-pycmd bk1" \ 64 1.1 christos "\\^error,msg=\"Error occurred in Python: non-string object used as key: Bad Key\"" \ 65 1.1 christos "-pycmd bk1" 66 1.1 christos 67 1.1 christos mi_gdb_test "-pycmd bk2" \ 68 1.1 christos "\\^error,msg=\"Error occurred in Python: non-string object used as key: 1\"" \ 69 1.1 christos "-pycmd bk2" 70 1.1 christos 71 1.1 christos mi_gdb_test "-pycmd bk3" \ 72 1.1 christos [multi_line \ 73 1.1.1.2 christos "&\"TypeError.*: __repr__ returned non-string \\(type BadKey\\)..\"" \ 74 1.1 christos "\\^error,msg=\"Error occurred in Python: __repr__ returned non-string \\(type BadKey\\)\""] \ 75 1.1 christos "-pycmd bk3" 76 1.1 christos 77 1.1 christos mi_gdb_test "-pycmd tpl" \ 78 1.1 christos "\\^done,result=\\\[\"42\",\"Hello\"\\\]" \ 79 1.1 christos "-pycmd tpl" 80 1.1 christos 81 1.1 christos mi_gdb_test "-pycmd itr" \ 82 1.1 christos "\\^done,result=\\\[\"1\",\"2\",\"3\"\\\]" \ 83 1.1 christos "-pycmd itr" 84 1.1 christos 85 1.1 christos mi_gdb_test "-pycmd nn1" \ 86 1.1 christos "\\^done" \ 87 1.1 christos "-pycmd nn1" 88 1.1 christos 89 1.1 christos mi_gdb_test "-pycmd nn2" \ 90 1.1 christos "\\^done,result=\\\[\"None\"\\\]" \ 91 1.1 christos "-pycmd nn2" 92 1.1 christos 93 1.1 christos mi_gdb_test "-pycmd bogus" \ 94 1.1 christos "\\^error,msg=\"Invalid parameter: bogus\"" \ 95 1.1 christos "-pycmd bogus" 96 1.1 christos 97 1.1 christos # Check that the top-level result from 'invoke' must be a dictionary. 98 1.1 christos foreach test_name { nd1 nd2 nd3 } { 99 1.1 christos mi_gdb_test "-pycmd ${test_name}" \ 100 1.1 christos "\\^error,msg=\"Error occurred in Python: Result from invoke must be a dictionary\"" 101 1.1 christos } 102 1.1 christos 103 1.1 christos # Check for invalid strings in the result. 104 1.1 christos foreach test_desc { {ik1 "xxx yyy"} {ik2 "xxx yyy"} {ik3 "xxx\\+yyy"} \ 105 1.1 christos {ik4 "xxx\\.yyy"} {ik5 "123xxxyyy"} } { 106 1.1 christos lassign $test_desc name pattern 107 1.1 christos 108 1.1 christos mi_gdb_test "-pycmd ${name}" \ 109 1.1 christos "\\^error,msg=\"Error occurred in Python: Invalid key in MI result: ${pattern}\"" 110 1.1 christos } 111 1.1 christos 112 1.1 christos mi_gdb_test "-pycmd empty_key" \ 113 1.1 christos "\\^error,msg=\"Error occurred in Python: Invalid empty key in MI result\"" 114 1.1 christos 115 1.1 christos # Check that a dash ('-') can be used in a key name. 116 1.1 christos mi_gdb_test "-pycmd dash-key" \ 117 1.1 christos "\\^done,the-key=\"123\"" 118 1.1 christos 119 1.1 christos # With this argument the command raises a gdb.GdbError with no message 120 1.1 christos # string. GDB considers this a bug in the user program, so prints a 121 1.1 christos # backtrace, and a generic error message. 122 1.1.1.3 christos 123 1.1.1.3 christos set line1 \ 124 1.1.1.3 christos [string_to_regexp {Traceback (most recent call last):\n}] 125 1.1.1.3 christos set line2 \ 126 1.1.1.3 christos [string cat \ 127 1.1.1.3 christos [string_to_regexp { File \"}] \ 128 1.1.1.3 christos "\[^\r\n\]+" \ 129 1.1.1.3 christos [string_to_regexp ${testfile}.py] \ 130 1.1.1.3 christos [string_to_regexp {\", line }] \ 131 1.1.1.3 christos $decimal \ 132 1.1.1.3 christos [string_to_regexp {, in invoke\n}]] 133 1.1.1.3 christos set line3 \ 134 1.1.1.3 christos [string_to_regexp { raise gdb.GdbError()\n}] 135 1.1.1.3 christos set line4 \ 136 1.1.1.3 christos [string_to_regexp {gdb.GdbError\n}] 137 1.1.1.3 christos set errline \ 138 1.1.1.3 christos [string_to_regexp {^error,msg="Error occurred in Python."}] 139 1.1.1.3 christos 140 1.1.1.3 christos set start_line \ 141 1.1.1.3 christos [string_to_regexp {&"}] 142 1.1.1.3 christos set end_line \ 143 1.1.1.3 christos [string_to_regexp {"}] 144 1.1.1.3 christos 145 1.1.1.3 christos # With python <= 3.12. 146 1.1.1.3 christos set re1 \ 147 1.1.1.3 christos [multi_line \ 148 1.1.1.3 christos $start_line$line1$end_line \ 149 1.1.1.3 christos $start_line$line2$end_line \ 150 1.1.1.3 christos $start_line$line3$end_line \ 151 1.1.1.3 christos $start_line$line4$end_line \ 152 1.1.1.3 christos $errline] 153 1.1.1.3 christos 154 1.1.1.3 christos # With python >= 3.13. 155 1.1.1.3 christos set re2 \ 156 1.1.1.3 christos [multi_line \ 157 1.1.1.3 christos $start_line$line1$end_line \ 158 1.1.1.3 christos $start_line$line2$line3$end_line \ 159 1.1.1.3 christos $start_line$line4$end_line \ 160 1.1.1.3 christos $errline] 161 1.1.1.3 christos 162 1.1.1.3 christos mi_gdb_test "-pycmd exp" ($re1|$re2) 163 1.1 christos 164 1.1 christos mi_gdb_test "python pycmd2('-pycmd')" \ 165 1.1 christos ".*\\^done" \ 166 1.1 christos "redefine -pycmd MI command from CLI command" 167 1.1 christos 168 1.1 christos mi_gdb_test "-pycmd str" \ 169 1.1 christos "\\^done,result=\"Ciao!\"" \ 170 1.1 christos "-pycmd str - redefined from CLI" 171 1.1 christos 172 1.1 christos mi_gdb_test "-pycmd int" \ 173 1.1 christos "\\^error,msg=\"Invalid parameter: int\"" \ 174 1.1 christos "-pycmd int - redefined from CLI" 175 1.1 christos 176 1.1 christos mi_gdb_test "-pycmd new" \ 177 1.1 christos "\\^done" \ 178 1.1 christos "Define new command -pycmd-new MI command from Python MI command" 179 1.1 christos 180 1.1 christos mi_gdb_test "-pycmd red" \ 181 1.1 christos "\\^error,msg=\"Command redefined but we failing anyway\"" \ 182 1.1 christos "redefine -pycmd MI command from Python MI command" 183 1.1 christos 184 1.1 christos mi_gdb_test "-pycmd int" \ 185 1.1 christos "\\^done,result=\"42\"" \ 186 1.1 christos "-pycmd int - redefined from MI" 187 1.1 christos 188 1.1 christos mi_gdb_test "-pycmd-new int" \ 189 1.1 christos "\\^done,result=\"42\"" \ 190 1.1 christos "-pycmd-new int - defined from MI" 191 1.1 christos 192 1.1 christos mi_gdb_test "python pycmd1('')" \ 193 1.1.1.2 christos ".*&\"ValueError.*: MI command name is empty\\...\".*\\^error,msg=\"Error occurred in Python.*\"" \ 194 1.1 christos "empty MI command name" 195 1.1 christos 196 1.1 christos mi_gdb_test "python pycmd1('-')" \ 197 1.1 christos [multi_line \ 198 1.1 christos ".*" \ 199 1.1.1.2 christos "&\"ValueError.*: MI command name does not start with '-' followed by at least one letter or digit\\...\"" \ 200 1.1.1.2 christos "&\"Error occurred in Python.*..\"" \ 201 1.1.1.2 christos "\\^error,msg=\"Error occurred in Python.*\""] \ 202 1.1 christos "invalid MI command name" 203 1.1 christos 204 1.1 christos mi_gdb_test "python pycmd1('-bad-character-@')" \ 205 1.1 christos [multi_line \ 206 1.1 christos ".*" \ 207 1.1.1.2 christos "&\"ValueError.*: MI command name contains invalid character: @\\...\"" \ 208 1.1.1.2 christos "&\"Error occurred in Python.*..\"" \ 209 1.1.1.2 christos "\\^error,msg=\"Error occurred in Python.*\""] \ 210 1.1 christos "invalid character in MI command name" 211 1.1 christos 212 1.1 christos mi_gdb_test "python cmd=pycmd1('-abc')" \ 213 1.1 christos ".*\\^done" \ 214 1.1 christos "create command -abc, stored in a python variable" 215 1.1 christos 216 1.1 christos mi_gdb_test "python print(cmd.name)" \ 217 1.1 christos ".*\r\n~\"-abc\\\\n\"\r\n\\^done" \ 218 1.1 christos "print the name of the stored mi command" 219 1.1 christos 220 1.1 christos mi_gdb_test "python print(cmd.installed)" \ 221 1.1 christos ".*\r\n~\"True\\\\n\"\r\n\\^done" \ 222 1.1 christos "print the installed status of the stored mi command" 223 1.1 christos 224 1.1 christos mi_gdb_test "-abc str" \ 225 1.1 christos "\\^done,result=\"Hello world!\"" \ 226 1.1 christos "-abc str" 227 1.1 christos 228 1.1 christos mi_gdb_test "python cmd.installed = False" \ 229 1.1 christos ".*\\^done" \ 230 1.1 christos "uninstall the mi command" 231 1.1 christos 232 1.1 christos mi_gdb_test "-abc str" \ 233 1.1 christos "\\^error,msg=\"Undefined MI command: abc\",code=\"undefined-command\"" \ 234 1.1 christos "-abc str, but now the command is gone" 235 1.1 christos 236 1.1.1.3 christos mi_gdb_test "python cmd.installed = None" \ 237 1.1.1.3 christos ".*\r\n\\^error,msg=\"Error occurred in Python: gdb\\.MICommand\\.installed must be set to a bool, not None\"" \ 238 1.1.1.3 christos "re-install the mi command using value None" 239 1.1.1.3 christos 240 1.1.1.3 christos mi_gdb_test "python cmd.installed = 1" \ 241 1.1.1.3 christos ".*\r\n\\^error,msg=\"Error occurred in Python: gdb\\.MICommand\\.installed must be set to a bool, not int\"" \ 242 1.1.1.3 christos "re-install the mi command using an int value" 243 1.1.1.3 christos 244 1.1.1.3 christos mi_gdb_test "python print(cmd.installed)" \ 245 1.1.1.3 christos [multi_line \ 246 1.1.1.3 christos ".*" \ 247 1.1.1.3 christos "~\"False\\\\n\"" \ 248 1.1.1.3 christos "\\^done"] \ 249 1.1.1.3 christos "cmd is still not installed" 250 1.1.1.3 christos 251 1.1 christos mi_gdb_test "python cmd.installed = True" \ 252 1.1 christos ".*\\^done" \ 253 1.1 christos "re-install the mi command" 254 1.1 christos 255 1.1 christos mi_gdb_test "-abc str" \ 256 1.1 christos "\\^done,result=\"Hello world!\"" \ 257 1.1 christos "-abc str, the command is back again" 258 1.1 christos 259 1.1 christos mi_gdb_test "python other=pycmd2('-abc')" \ 260 1.1 christos ".*\\^done" \ 261 1.1 christos "create another command called -abc, stored in a separate python variable" 262 1.1 christos 263 1.1 christos mi_gdb_test "python print(other.installed)" \ 264 1.1 christos ".*\r\n~\"True\\\\n\"\r\n\\^done" \ 265 1.1 christos "print the installed status of the other stored mi command" 266 1.1 christos 267 1.1 christos mi_gdb_test "python print(cmd.installed)" \ 268 1.1 christos ".*\r\n~\"False\\\\n\"\r\n\\^done" \ 269 1.1 christos "print the installed status of the original stored mi command" 270 1.1 christos 271 1.1 christos mi_gdb_test "-abc str" \ 272 1.1 christos "\\^done,result=\"Ciao!\"" \ 273 1.1 christos "-abc str, when the other command is in place" 274 1.1 christos 275 1.1 christos mi_gdb_test "python cmd.installed = True" \ 276 1.1 christos ".*\\^done" \ 277 1.1 christos "re-install the original mi command" 278 1.1 christos 279 1.1 christos mi_gdb_test "-abc str" \ 280 1.1 christos "\\^done,result=\"Hello world!\"" \ 281 1.1 christos "-abc str, the original command is back again" 282 1.1 christos 283 1.1 christos mi_gdb_test "python print(other.installed)" \ 284 1.1 christos ".*\r\n~\"False\\\\n\"\r\n\\^done" \ 285 1.1 christos "the other command is now not installed" 286 1.1 christos 287 1.1 christos mi_gdb_test "python print(cmd.installed)" \ 288 1.1 christos ".*\r\n~\"True\\\\n\"\r\n\\^done" \ 289 1.1 christos "the original command is now installed" 290 1.1 christos 291 1.1 christos mi_gdb_test "python aa = pycmd3('-aa', 'message one', 'xxx')" \ 292 1.1 christos ".*\\^done" \ 293 1.1 christos "created a new -aa command" 294 1.1 christos 295 1.1 christos mi_gdb_test "-aa" \ 296 1.1 christos ".*\\^done,xxx={msg=\"message one\"}" \ 297 1.1 christos "call the -aa command" 298 1.1 christos 299 1.1 christos mi_gdb_test "python aa.__init__('-aa', 'message two', 'yyy')" \ 300 1.1 christos ".*\\^done" \ 301 1.1 christos "reinitialise -aa command with a new message" 302 1.1 christos 303 1.1 christos mi_gdb_test "-aa" \ 304 1.1 christos ".*\\^done,yyy={msg=\"message two\"}" \ 305 1.1 christos "call the -aa command, get the new message" 306 1.1 christos 307 1.1 christos mi_gdb_test "python aa.__init__('-bb', 'message three', 'zzz')" \ 308 1.1 christos [multi_line \ 309 1.1 christos ".*" \ 310 1.1.1.2 christos "&\"ValueError.*: can't reinitialize object with a different command name..\"" \ 311 1.1.1.2 christos "&\"Error occurred in Python.*..\"" \ 312 1.1.1.2 christos "\\^error,msg=\"Error occurred in Python.*\""] \ 313 1.1 christos "attempt to reinitialise aa variable to a new command name" 314 1.1 christos 315 1.1 christos mi_gdb_test "-aa" \ 316 1.1 christos ".*\\^done,yyy={msg=\"message two\"}" \ 317 1.1 christos "check the aa object has not changed after failed initialization" 318 1.1 christos 319 1.1 christos mi_gdb_test "python aa.installed = False" \ 320 1.1 christos ".*\\^done" \ 321 1.1 christos "uninstall the -aa command" 322 1.1 christos 323 1.1 christos mi_gdb_test "python aa.__init__('-bb', 'message three', 'zzz')" \ 324 1.1 christos [multi_line \ 325 1.1 christos ".*" \ 326 1.1.1.2 christos "&\"ValueError.*: can't reinitialize object with a different command name..\"" \ 327 1.1.1.2 christos "&\"Error occurred in Python.*..\"" \ 328 1.1.1.2 christos "\\^error,msg=\"Error occurred in Python.*\""] \ 329 1.1 christos "attempt to reinitialise aa variable to a new command name while uninstalled" 330 1.1 christos 331 1.1 christos mi_gdb_test "python aa.__init__('-aa', 'message three', 'zzz')" \ 332 1.1 christos ".*\\^done" \ 333 1.1 christos "reinitialise -aa command with a new message while uninstalled" 334 1.1 christos 335 1.1 christos mi_gdb_test "python aa.installed = True" \ 336 1.1 christos ".*\\^done" \ 337 1.1 christos "install the -aa command" 338 1.1 christos 339 1.1 christos mi_gdb_test "-aa" \ 340 1.1 christos ".*\\^done,zzz={msg=\"message three\"}" \ 341 1.1 christos "call the -aa command looking for message three" 342 1.1 christos 343 1.1 christos # Try to register a command object that is missing an invoke method. 344 1.1 christos # This is accepted, but will give an error when the user tries to run 345 1.1 christos # the command. 346 1.1 christos mi_gdb_test "python no_invoke('-no-invoke')" ".*\\^done" \ 347 1.1 christos "attempt to register command with no invoke method" 348 1.1 christos mi_gdb_test "-no-invoke" \ 349 1.1 christos [multi_line \ 350 1.1 christos ".*" \ 351 1.1.1.2 christos "&\"AttributeError.*: 'no_invoke' object has no attribute 'invoke'..\"" \ 352 1.1 christos "\\^error,msg=\"Error occurred in Python: 'no_invoke' object has no attribute 'invoke'\""] \ 353 1.1 christos "execute -no-invoke command, which is missing the invoke method" 354 1.1 christos 355 1.1 christos # Register a command, then delete its invoke method. What is the user thinking!! 356 1.1 christos mi_gdb_test "python setattr(no_invoke, 'invoke', free_invoke)" ".*\\^done" 357 1.1 christos mi_gdb_test "python cmd = no_invoke('-hello')" ".*\\^done" 358 1.1 christos mi_gdb_test "-hello" ".*\\^done,result=\\\[\\\]" \ 359 1.1 christos "execute no_invoke command, while it still has an invoke attribute" 360 1.1 christos mi_gdb_test "python delattr(no_invoke, 'invoke')" ".*\\^done" 361 1.1 christos mi_gdb_test "-hello" \ 362 1.1 christos [multi_line \ 363 1.1 christos ".*" \ 364 1.1.1.2 christos "&\"AttributeError.*: 'no_invoke' object has no attribute 'invoke'..\"" \ 365 1.1 christos "\\^error,msg=\"Error occurred in Python: 'no_invoke' object has no attribute 'invoke'\""] \ 366 1.1 christos "execute -hello command, that had its invoke method removed" 367 1.1 christos mi_gdb_test "python cmd.invoke = 'string'" ".*\\^done" 368 1.1 christos mi_gdb_test "-hello" \ 369 1.1 christos [multi_line \ 370 1.1 christos ".*" \ 371 1.1.1.2 christos "&\"TypeError.*: 'str' object is not callable..\"" \ 372 1.1 christos "\\^error,msg=\"Error occurred in Python: 'str' object is not callable\""] \ 373 1.1 christos "execute command with invoke set to a string" 374 1.1 christos 375 1.1 christos # Try to create a new MI command that uses the name of a builtin MI command. 376 1.1 christos mi_gdb_test "python cmd = pycmd2('-data-disassemble')" \ 377 1.1 christos [multi_line \ 378 1.1 christos ".*" \ 379 1.1.1.2 christos "&\"RuntimeError.*: unable to add command, name is already in use..\"" \ 380 1.1.1.2 christos "&\"Error occurred in Python.*..\"" \ 381 1.1.1.2 christos "\\^error,msg=\"Error occurred in Python.*\""] \ 382 1.1 christos "try to register a command that replaces -data-disassemble" 383 1.1 christos 384 1.1 christos 385 1.1 christos 386 1.1 christos mi_gdb_test "python run_exception_tests()" \ 387 1.1 christos [multi_line \ 388 1.1 christos ".*" \ 389 1.1 christos "~\"PASS..\"" \ 390 1.1 christos "\\^done"] 391