1 # Copyright (C) 2009-2025 Free Software Foundation, Inc. 2 3 # This program is free software; you can redistribute it and/or modify 4 # it under the terms of the GNU General Public License as published by 5 # the Free Software Foundation; either version 3 of the License, or 6 # (at your option) any later version. 7 # 8 # This program is distributed in the hope that it will be useful, 9 # but WITHOUT ANY WARRANTY; without even the implied warranty of 10 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 # GNU General Public License for more details. 12 # 13 # You should have received a copy of the GNU General Public License 14 # along with this program. If not, see <http://www.gnu.org/licenses/>. 15 16 # This file is part of the GDB testsuite. It tests the mechanism 17 # for defining new GDB commands in Python. 18 19 load_lib gdb-python.exp 20 21 require allow_python_tests 22 23 standard_testfile 24 25 if { [prepare_for_testing "failed to prepare" ${testfile} ${srcfile}] } { 26 return -1 27 } 28 29 if {![runto_main]} { 30 return 0 31 } 32 33 # Test a simple command. 34 35 gdb_test_multiline "input simple command" \ 36 "python" "" \ 37 "class test_cmd (gdb.Command):" "" \ 38 " def __init__ (self):" "" \ 39 " super (test_cmd, self).__init__ (\"test_cmd\", gdb.COMMAND_OBSCURE)" "" \ 40 " def invoke (self, arg, from_tty):" "" \ 41 " print (\"test_cmd output, arg = %s\" % arg)" "" \ 42 "test_cmd ()" "" \ 43 "end" "" 44 45 gdb_test "test_cmd ugh" "test_cmd output, arg = ugh" "call simple command" 46 47 # Test a prefix command, and a subcommand within it. 48 49 gdb_test_multiline "input prefix command" \ 50 "python" "" \ 51 "class prefix_cmd (gdb.Command):" "" \ 52 " def __init__ (self):" "" \ 53 " super (prefix_cmd, self).__init__ (\"prefix_cmd\", gdb.COMMAND_OBSCURE, gdb.COMPLETE_NONE, True)" "" \ 54 " def invoke (self, arg, from_tty):" "" \ 55 " print (\"prefix_cmd output, arg = %s\" % arg)" "" \ 56 "prefix_cmd ()" "" \ 57 "end" "" 58 59 gdb_test "prefix_cmd ugh" "prefix_cmd output, arg = ugh" "call prefix command" 60 61 gdb_test_multiline "input subcommand" \ 62 "python" "" \ 63 "class subcmd (gdb.Command):" "" \ 64 " def __init__ (self):" "" \ 65 " super (subcmd, self).__init__ (\"prefix_cmd subcmd\", gdb.COMMAND_OBSCURE)" "" \ 66 " def invoke (self, arg, from_tty):" "" \ 67 " print (\"subcmd output, arg = %s\" % arg)" "" \ 68 "subcmd ()" "" \ 69 "end" "" 70 71 gdb_test "prefix_cmd subcmd ugh" "subcmd output, arg = ugh" "call subcmd" 72 73 # Test prefix command using keyword arguments. 74 75 gdb_test_multiline "input prefix command, keyword arguments" \ 76 "python" "" \ 77 "class prefix_cmd2 (gdb.Command):" "" \ 78 " def __init__ (self):" "" \ 79 " super (prefix_cmd2, self).__init__ (\"prefix_cmd2\", gdb.COMMAND_OBSCURE, prefix = True, completer_class = gdb.COMPLETE_FILENAME)" "" \ 80 " def invoke (self, arg, from_tty):" "" \ 81 " print (\"prefix_cmd2 output, arg = %s\" % arg)" "" \ 82 "prefix_cmd2 ()" "" \ 83 "end" "" 84 85 gdb_test "prefix_cmd2 argh" "prefix_cmd2 output, arg = argh" "call prefix command, keyword arguments" 86 87 gdb_test_multiline "input subcommand under prefix_cmd2" \ 88 "python" "" \ 89 "class subcmd (gdb.Command):" "" \ 90 " def __init__ (self):" "" \ 91 " super (subcmd, self).__init__ (\"prefix_cmd2 subcmd\", gdb.COMMAND_OBSCURE)" "" \ 92 " def invoke (self, arg, from_tty):" "" \ 93 " print (\"subcmd output, arg = %s\" % arg)" "" \ 94 "subcmd ()" "" \ 95 "end" "" 96 97 gdb_test "prefix_cmd2 subcmd ugh" "subcmd output, arg = ugh" "call subcmd under prefix_cmd2" 98 99 # Test a subcommand in an existing GDB prefix. 100 101 gdb_test_multiline "input new subcommand" \ 102 "python" "" \ 103 "class newsubcmd (gdb.Command):" "" \ 104 " def __init__ (self):" "" \ 105 " super (newsubcmd, self).__init__ (\"info newsubcmd\", gdb.COMMAND_OBSCURE)" "" \ 106 " def invoke (self, arg, from_tty):" "" \ 107 " print (\"newsubcmd output, arg = %s\" % arg)" "" \ 108 "newsubcmd ()" "" \ 109 "end" "" 110 111 gdb_test "info newsubcmd ugh" "newsubcmd output, arg = ugh" "call newsubcmd" 112 113 # Test a command that throws gdb.GdbError. 114 115 gdb_test_multiline "input command to throw error" \ 116 "python" "" \ 117 "class test_error_cmd (gdb.Command):" "" \ 118 " def __init__ (self):" "" \ 119 " super (test_error_cmd, self).__init__ (\"test_error_cmd\", gdb.COMMAND_OBSCURE)" "" \ 120 " def invoke (self, arg, from_tty):" "" \ 121 " raise gdb.GdbError ('you lose!')" "" \ 122 "test_error_cmd ()" "" \ 123 "end" "" 124 125 gdb_test "test_error_cmd ugh" "you lose!" "call error command" 126 127 # Test gdb.string_to_argv. 128 129 gdb_test "python print (gdb.string_to_argv (\"1 2 3\"))" \ 130 {\['1', '2', '3'\]} \ 131 "string_to_argv (\"1 2 3\"), case 1" 132 133 gdb_test "python print (gdb.string_to_argv (\"'1 2' 3\"))" \ 134 {\['1 2', '3'\]} \ 135 "string_to_argv (\"'1 2' 3\"), case 2" 136 137 gdb_test "python print (gdb.string_to_argv ('\"1 2\" 3'))" \ 138 {\['1 2', '3'\]} \ 139 "string_to_argv ('\"1 2\" 3'), case 3" 140 141 gdb_test "python print (gdb.string_to_argv ('1\\ 2 3'))" \ 142 {\['1 2', '3'\]} \ 143 "string_to_argv ('1\\ 2 3'), case 4" 144 145 # Test user-defined python commands. 146 gdb_test_multiline "input simple user-defined command" \ 147 "python" "" \ 148 "class test_help (gdb.Command):" "" \ 149 " \"\"\"Docstring\"\"\"" "" \ 150 " def __init__ (self):" "" \ 151 " super (test_help, self).__init__ (\"test_help\", gdb.COMMAND_USER)" "" \ 152 " def invoke (self, arg, from_tty):" "" \ 153 " print (\"test_cmd output, arg = %s\" % arg)" "" \ 154 "test_help ()" "" \ 155 "end" "" 156 157 gdb_test "test_help ugh" "test_cmd output, arg = ugh" "call simple user-defined command" 158 159 # Make sure the command shows up in `help user-defined`. 160 test_user_defined_class_help {"test_help -- Docstring[\r\n]"} 161 162 # Make sure the command does not show up in `show user`. 163 gdb_test "show user test_help" "Not a user command\." \ 164 "don't show user-defined python command in `show user command`" 165 166 # Test expression completion on fields 167 gdb_test_multiline "expression completion command" \ 168 "python" "" \ 169 "class expr_test (gdb.Command):" "" \ 170 " def __init__ (self):" "" \ 171 " super (expr_test, self).__init__ (\"expr_test\", gdb.COMMAND_USER, gdb.COMPLETE_EXPRESSION)" "" \ 172 " def invoke (self, arg, from_tty):" "" \ 173 " print (\"invoked on = %s\" % arg)" "" \ 174 "expr_test ()" "" \ 175 "end" "" 176 177 178 gdb_test "complete expr_test bar\." \ 179 "expr_test bar\.bc.*expr_test bar\.ij.*" \ 180 "test completion through complete command" 181 182 # Test that the "python" command is correctly recognized as 183 # inline/multi-line when entering a sequence of commands. 184 # 185 # This proc tests PR cli/21688. The PR is not language-specific, but 186 # the easiest way is just to test with Python. 187 proc test_python_inline_or_multiline { } { 188 global gdb_prompt 189 set end "\r\n$gdb_prompt $" 190 191 set define_cmd_not_inline [ list \ 192 [ list "if 1" " >$" "multi-line if 1" ] \ 193 [ list "python" " >$" "multi-line python command" ] \ 194 [ list "print ('hello')" " >$" "multi-line print" ] \ 195 [ list "end" " >$" "multi-line first end" ] \ 196 [ list "end" "hello$end" "multi-line last end" ] ] 197 198 # This also tests trailing whitespace on the command. 199 set define_cmd_alias_not_inline [ list \ 200 [ list "if 1" " >$" "multi-line if 1 alias" ] \ 201 [ list "py " " >$" "multi-line python command alias" ] \ 202 [ list "print ('hello')" " >$" "multi-line print alias" ] \ 203 [ list "end" " >$" "multi-line first end alias" ] \ 204 [ list "end" "hello$end" "multi-line last end alias" ] ] 205 206 set define_cmd_alias_foo_not_inline [ list \ 207 [ list "alias foo=python" "$end" "multi-line alias foo" ] \ 208 [ list "if 1" " >$" "multi-line if 1 alias foo" ] \ 209 [ list "foo " " >$" "multi-line python command alias foo" ] \ 210 [ list "print ('hello')" " >$" "multi-line print alias foo" ] \ 211 [ list "end" " >$" "multi-line first end alias foo" ] \ 212 [ list "end" "hello$end" "multi-line last end alias foo" ] ] 213 214 set define_cmd_inline [ list \ 215 [ list "if 1" " >$" "inline if 1" ] \ 216 [ list "python print ('hello')" " >$" "inline python command" ] \ 217 [ list "end" "hello$end" "inline end" ] ] 218 219 set define_cmd_alias_inline [ list \ 220 [ list "if 1" " >$" "inline if 1 alias" ] \ 221 [ list "py print ('hello')" " >$" "inline python command alias" ] \ 222 [ list "end" "hello$end" "inline end alias" ] ] 223 224 set define_cmd_alias_foo_inline [ list \ 225 [ list "if 1" " >$" "inline if 1 alias foo" ] \ 226 [ list "foo print ('hello')" " >$" "inline python command alias foo" ] \ 227 [ list "end" "hello$end" "inline end alias foo" ] ] 228 229 foreach t [list $define_cmd_not_inline \ 230 $define_cmd_alias_not_inline \ 231 $define_cmd_alias_foo_not_inline \ 232 $define_cmd_inline \ 233 $define_cmd_alias_inline \ 234 $define_cmd_alias_foo_inline] { 235 foreach l $t { 236 lassign $l command regex testmsg 237 gdb_test_multiple "$command" "$testmsg" { 238 -re "$regex" { 239 pass "$testmsg" 240 } 241 } 242 } 243 } 244 } 245 246 test_python_inline_or_multiline 247 248 if { [readline_is_used] } { 249 set test "complete 'expr_test bar.i'" 250 send_gdb "expr_test bar\.i\t\t" 251 gdb_test_multiple "" "$test" { 252 -re "expr_test bar\.ij \\\x07$" { 253 send_gdb "\n" 254 gdb_test_multiple "" $test { 255 -re "invoked on = bar.ij.*$gdb_prompt $" { 256 pass "$test" 257 } 258 } 259 } 260 } 261 } 262 263 264 # Test that interrupting pagination throws a gdb quit. 265 gdb_test_no_output "set height 10" 266 267 gdb_test_multiline "input multi-line-output command" \ 268 "python" "" \ 269 "class test_mline (gdb.Command):" "" \ 270 " \"\"\"Docstring\"\"\"" "" \ 271 " def __init__ (self):" "" \ 272 " super (test_mline, self).__init__ (\"test_multiline\", gdb.COMMAND_USER)" "" \ 273 " def invoke (self, arg, from_tty):" "" \ 274 " for f in range(20):" "" \ 275 " print (\"test_multiline output\")" "" \ 276 "test_mline ()" "" \ 277 "end" "" 278 279 set test "verify pagination from test_multiline" 280 gdb_test_multiple "test_multiline" $test { 281 -re "$pagination_prompt$" { 282 pass $test 283 } 284 } 285 286 send_gdb "q\n" 287 set test "verify pagination from test_multiline: q" 288 gdb_test_multiple "" $test { 289 -re "Error occurred in Python" { 290 fail $test 291 } 292 -re "Quit" { 293 pass $test 294 } 295 } 296 297 # Test command redefining itself 298 299 proc_with_prefix test_command_redefining_itself {} { 300 # Start with a fresh gdb 301 clean_restart 302 303 304 gdb_test_multiline "input command redefining itself" \ 305 "python" "" \ 306 "class redefine_cmd (gdb.Command):" "" \ 307 " def __init__ (self, msg):" "" \ 308 " super (redefine_cmd, self).__init__ (\"redefine_cmd\", gdb.COMMAND_OBSCURE)" "" \ 309 " self._msg = msg" "" \ 310 " def invoke (self, arg, from_tty):" "" \ 311 " print (\"redefine_cmd output, msg = %s\" % self._msg)" "" \ 312 " redefine_cmd (arg)" "" \ 313 "redefine_cmd (\"XXX\")" "" \ 314 "end" "" 315 316 gdb_test "redefine_cmd AAA" \ 317 "redefine_cmd output, msg = XXX" \ 318 "call command redefining itself 1" 319 320 gdb_test "redefine_cmd BBB" \ 321 "redefine_cmd output, msg = AAA" \ 322 "call command redefining itself 2" 323 } 324 325 # Try to create commands using unknown prefixes and check GDB gives an 326 # error. There's also a test in here for an ambiguous prefix, which 327 # gives the same error. 328 proc_with_prefix test_unknown_prefix {} { 329 clean_restart 330 331 gdb_test_no_output "python gdb.Command('foo1', gdb.COMMAND_NONE, prefix=True)" 332 gdb_test_no_output "python gdb.Command('foo cmd', gdb.COMMAND_NONE)" 333 334 foreach prefix { "xxx" "foo xxx" "foo1 xxx" } { 335 gdb_test "python gdb.Command('$prefix cmd', gdb.COMMAND_NONE)" \ 336 [multi_line \ 337 "Python Exception <class 'RuntimeError'>: Could not find command prefix $prefix\\." \ 338 "Error occurred in Python: Could not find command prefix $prefix\\."] 339 } 340 341 gdb_test_no_output "python gdb.Command('foo2', gdb.COMMAND_NONE, prefix=True)" 342 343 foreach prefix { "foo" "foo xxx" "foo1 xxx" "foo2 xxx" } { 344 gdb_test "python gdb.Command('$prefix cmd2', gdb.COMMAND_NONE)" \ 345 [multi_line \ 346 "Python Exception <class 'RuntimeError'>: Could not find command prefix $prefix\\." \ 347 "Error occurred in Python: Could not find command prefix $prefix\\."] 348 } 349 } 350 351 # Check what happens if a command object is called without an 'invoke' 352 # method. 353 proc_with_prefix test_deleting_invoke_methods {} { 354 clean_restart 355 356 gdb_test_multiline "create 'foo' prefix command" \ 357 "python" "" \ 358 "class test_prefix(gdb.Command):" "" \ 359 " def __init__ (self):" "" \ 360 " super().__init__ (\"foo\", gdb.COMMAND_USER, prefix=True)" "" \ 361 " def invoke (self, arg, from_tty):" "" \ 362 " print(\"In 'foo' invoke: %s\" % arg)" "" \ 363 "foo = test_prefix()" "" \ 364 "end" "" 365 366 gdb_test_multiline "create 'foo bar' command" \ 367 "python" "" \ 368 "class test_cmd(gdb.Command):" "" \ 369 " def __init__ (self):" "" \ 370 " super().__init__ (\"foo bar\", gdb.COMMAND_USER)" "" \ 371 " def invoke (self, arg, from_tty):" "" \ 372 " print(\"In 'foo bar' invoke: %s\" % arg)" "" \ 373 "foo_bar = test_cmd()" "" \ 374 "end" "" 375 376 gdb_test "foo def" "In 'foo' invoke: def" \ 377 "call 'foo' with an unknown sub-command" 378 379 gdb_test "foo bar def" "In 'foo bar' invoke: def" \ 380 "call 'foo bar' with arguments" 381 382 gdb_test_no_output "python del(foo_bar.__class__.invoke)" \ 383 "delete invoke from test_cmd class" 384 385 with_test_prefix "after deleting test_cmd.invoke" { 386 gdb_test "foo def" "In 'foo' invoke: def" \ 387 "call 'foo' with an unknown sub-command" 388 389 gdb_test "foo bar def" \ 390 "^Python command object missing 'invoke' method\\." \ 391 "call 'foo bar' with arguments" 392 } 393 394 gdb_test_no_output "python del(foo.__class__.invoke)" \ 395 "delete invoke from test_prefix class" 396 397 with_test_prefix "after deleting test_prefix.invoke" { 398 gdb_test "foo def" \ 399 "^Python command object missing 'invoke' method\\." \ 400 "call 'foo' with an unknown sub-command" 401 402 gdb_test "foo bar def" \ 403 "^Python command object missing 'invoke' method\\." \ 404 "call 'foo bar' with arguments" 405 } 406 } 407 408 test_command_redefining_itself 409 test_unknown_prefix 410 test_deleting_invoke_methods 411