]>
Commit | Line | Data |
---|---|---|
1d506c26 | 1 | # Copyright (C) 2009-2024 Free Software Foundation, Inc. |
6db7e351 TJB |
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 | ||
f39a75d0 | 19 | load_lib gdb-python.exp |
6db7e351 | 20 | |
d82e5429 | 21 | require allow_python_tests |
79749205 | 22 | |
92e32e33 | 23 | standard_testfile |
6db7e351 | 24 | |
5b362f04 | 25 | if { [prepare_for_testing "failed to prepare" ${testfile} ${srcfile}] } { |
92e32e33 PM |
26 | return -1 |
27 | } | |
6db7e351 | 28 | |
b0e16ca5 | 29 | if {![runto_main]} { |
92e32e33 PM |
30 | return 0 |
31 | } | |
32 | ||
6db7e351 TJB |
33 | # Test a simple command. |
34 | ||
2a17c803 | 35 | gdb_test_multiline "input simple command" \ |
6db7e351 TJB |
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):" "" \ | |
9325cb04 | 41 | " print (\"test_cmd output, arg = %s\" % arg)" "" \ |
6db7e351 TJB |
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 | ||
2a17c803 | 49 | gdb_test_multiline "input prefix command" \ |
6db7e351 TJB |
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):" "" \ | |
9325cb04 | 55 | " print (\"prefix_cmd output, arg = %s\" % arg)" "" \ |
6db7e351 TJB |
56 | "prefix_cmd ()" "" \ |
57 | "end" "" | |
58 | ||
59 | gdb_test "prefix_cmd ugh" "prefix_cmd output, arg = ugh" "call prefix command" | |
60 | ||
2a17c803 | 61 | gdb_test_multiline "input subcommand" \ |
6db7e351 TJB |
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):" "" \ | |
9325cb04 | 67 | " print (\"subcmd output, arg = %s\" % arg)" "" \ |
6db7e351 TJB |
68 | "subcmd ()" "" \ |
69 | "end" "" | |
70 | ||
71 | gdb_test "prefix_cmd subcmd ugh" "subcmd output, arg = ugh" "call subcmd" | |
72 | ||
cc924cad TJB |
73 | # Test prefix command using keyword arguments. |
74 | ||
2a17c803 | 75 | gdb_test_multiline "input prefix command, keyword arguments" \ |
cc924cad TJB |
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):" "" \ | |
9325cb04 | 81 | " print (\"prefix_cmd2 output, arg = %s\" % arg)" "" \ |
cc924cad TJB |
82 | "prefix_cmd2 ()" "" \ |
83 | "end" "" | |
84 | ||
85 | gdb_test "prefix_cmd2 argh" "prefix_cmd2 output, arg = argh" "call prefix command, keyword arguments" | |
86 | ||
2a17c803 | 87 | gdb_test_multiline "input subcommand under prefix_cmd2" \ |
cc924cad TJB |
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):" "" \ | |
9325cb04 | 93 | " print (\"subcmd output, arg = %s\" % arg)" "" \ |
cc924cad TJB |
94 | "subcmd ()" "" \ |
95 | "end" "" | |
96 | ||
97 | gdb_test "prefix_cmd2 subcmd ugh" "subcmd output, arg = ugh" "call subcmd under prefix_cmd2" | |
98 | ||
6db7e351 TJB |
99 | # Test a subcommand in an existing GDB prefix. |
100 | ||
2a17c803 | 101 | gdb_test_multiline "input new subcommand" \ |
6db7e351 TJB |
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):" "" \ | |
9325cb04 | 107 | " print (\"newsubcmd output, arg = %s\" % arg)" "" \ |
6db7e351 TJB |
108 | "newsubcmd ()" "" \ |
109 | "end" "" | |
110 | ||
111 | gdb_test "info newsubcmd ugh" "newsubcmd output, arg = ugh" "call newsubcmd" | |
07ca107c DE |
112 | |
113 | # Test a command that throws gdb.GdbError. | |
114 | ||
2a17c803 | 115 | gdb_test_multiline "input command to throw error" \ |
07ca107c DE |
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 | ||
9325cb04 | 129 | gdb_test "python print (gdb.string_to_argv (\"1 2 3\"))" \ |
07ca107c DE |
130 | {\['1', '2', '3'\]} \ |
131 | "string_to_argv (\"1 2 3\")" | |
132 | ||
9325cb04 | 133 | gdb_test "python print (gdb.string_to_argv (\"'1 2' 3\"))" \ |
07ca107c DE |
134 | {\['1 2', '3'\]} \ |
135 | "string_to_argv (\"'1 2' 3\")" | |
136 | ||
9325cb04 | 137 | gdb_test "python print (gdb.string_to_argv ('\"1 2\" 3'))" \ |
07ca107c DE |
138 | {\['1 2', '3'\]} \ |
139 | "string_to_argv ('\"1 2\" 3')" | |
140 | ||
9325cb04 | 141 | gdb_test "python print (gdb.string_to_argv ('1\\ 2 3'))" \ |
07ca107c DE |
142 | {\['1 2', '3'\]} \ |
143 | "string_to_argv ('1\\ 2 3')" | |
7d74f244 DE |
144 | |
145 | # Test user-defined python commands. | |
2a17c803 | 146 | gdb_test_multiline "input simple user-defined command" \ |
7d74f244 DE |
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):" "" \ | |
9325cb04 | 153 | " print (\"test_cmd output, arg = %s\" % arg)" "" \ |
7d74f244 DE |
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`. | |
206584bd | 160 | test_user_defined_class_help {"test_help -- Docstring[\r\n]"} |
92e32e33 | 161 | |
a9f116cb GKB |
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 | ||
92e32e33 | 166 | # Test expression completion on fields |
2a17c803 | 167 | gdb_test_multiline "expression completion command" \ |
92e32e33 PM |
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.*" \ | |
bb95117e | 180 | "test completion through complete command" |
92e32e33 | 181 | |
51ed89aa SDJ |
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 { } { | |
dc4bde35 | 188 | global gdb_prompt |
b04480b1 | 189 | set end "\r\n$gdb_prompt $" |
dc4bde35 | 190 | |
b04480b1 AH |
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" ] ] | |
51ed89aa | 197 | |
dc4bde35 | 198 | # This also tests trailing whitespace on the command. |
b04480b1 AH |
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" ] ] | |
dc4bde35 SDJ |
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] { | |
51ed89aa SDJ |
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 | ||
0d4d0e77 YQ |
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 | } | |
92e32e33 PM |
258 | } |
259 | } | |
260 | } | |
261 | } | |
bc543c90 TT |
262 | |
263 | ||
264 | # Test that interrupting pagination throws a gdb quit. | |
265 | gdb_test_no_output "set height 10" | |
266 | ||
2a17c803 | 267 | gdb_test_multiline "input multi-line-output command" \ |
bc543c90 TT |
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 "--Type <RET>" { | |
282 | exp_continue | |
283 | } | |
284 | -re " for more, q to quit" { | |
285 | exp_continue | |
286 | } | |
287 | -re ", c to continue without paging--$" { | |
288 | pass $test | |
289 | } | |
290 | } | |
291 | ||
292 | send_gdb "q\n" | |
293 | set test "verify pagination from test_multiline: q" | |
254de262 | 294 | gdb_test_multiple "" $test { |
bc543c90 TT |
295 | -re "Error occurred in Python" { |
296 | fail $test | |
297 | } | |
298 | -re "Quit" { | |
299 | pass $test | |
300 | } | |
301 | } | |
429f0cd1 JV |
302 | |
303 | # Test command redefining itself | |
304 | ||
305 | proc_with_prefix test_command_redefining_itself {} { | |
306 | # Start with a fresh gdb | |
307 | clean_restart | |
308 | ||
309 | ||
310 | gdb_test_multiline "input command redefining itself" \ | |
311 | "python" "" \ | |
312 | "class redefine_cmd (gdb.Command):" "" \ | |
313 | " def __init__ (self, msg):" "" \ | |
314 | " super (redefine_cmd, self).__init__ (\"redefine_cmd\", gdb.COMMAND_OBSCURE)" "" \ | |
315 | " self._msg = msg" "" \ | |
316 | " def invoke (self, arg, from_tty):" "" \ | |
317 | " print (\"redefine_cmd output, msg = %s\" % self._msg)" "" \ | |
318 | " redefine_cmd (arg)" "" \ | |
319 | "redefine_cmd (\"XXX\")" "" \ | |
320 | "end" "" | |
321 | ||
322 | gdb_test "redefine_cmd AAA" \ | |
323 | "redefine_cmd output, msg = XXX" \ | |
324 | "call command redefining itself 1" | |
325 | ||
326 | gdb_test "redefine_cmd BBB" \ | |
327 | "redefine_cmd output, msg = AAA" \ | |
328 | "call command redefining itself 2" | |
329 | } | |
330 | ||
331 | test_command_redefining_itself |