xref: /netbsd-src/external/gpl3/gdb.old/dist/gdb/testsuite/lib/completion-support.exp (revision e670fd5c413e99c2f6a37901bb21c537fcd322d2)
1# Copyright 2017-2019 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.
17
18# Any variable or procedure in the namespace whose name starts with
19# "_" is private to the module.  Do not use these.
20
21namespace eval completion {
22    variable bell_re "\\\x07"
23
24    # List of all quote chars.
25    variable all_quotes_list {"'" "\""}
26
27    # List of all quote chars, including no-quote at all.
28    variable maybe_quoted_list {"" "'" "\""}
29
30    variable keyword_list {"if" "task" "thread"}
31
32    variable explicit_opts_list \
33	{"-function" "-label" "-line" "-qualified" "-source"}
34}
35
36# Make a regular expression that matches a TAB completion list.
37
38proc make_tab_completion_list_re { completion_list } {
39    # readline separates the completion columns that fit on the same
40    # line with whitespace.  Since we're testing under "set width
41    # unlimited", all completions will be printed on the same line.
42    # The amount of whitespace depends on the length of the widest
43    # completion.  We could compute that here and expect the exact
44    # number of ws characters between each completion match, but to
45    # keep it simple, we accept any number of characters.
46    set ws " +"
47
48    set completion_list_re ""
49    foreach c $completion_list {
50	append completion_list_re [string_to_regexp $c]
51	append completion_list_re $ws
52    }
53    append completion_list_re $ws
54
55    return $completion_list_re
56}
57
58# Make a regular expression that matches a "complete" command
59# completion list.  CMD_PREFIX is the command prefix added to each
60# completion match.
61
62proc make_cmd_completion_list_re { cmd_prefix completion_list start_quote_char end_quote_char } {
63
64    set completion_list_re ""
65    foreach c $completion_list {
66	# The command prefix is included in all completion matches.
67	append completion_list_re [string_to_regexp $cmd_prefix$start_quote_char$c$end_quote_char]
68	append completion_list_re "\r\n"
69    }
70
71    return $completion_list_re
72}
73
74# Clear the input line.
75
76proc clear_input_line { test } {
77    global gdb_prompt
78
79    send_gdb "\003"
80    gdb_test_multiple "" "$test (clearing input line)" {
81	-re "Quit\r\n$gdb_prompt $" {
82	}
83    }
84}
85
86# Test that completing LINE with TAB completes to nothing.
87
88proc test_gdb_complete_tab_none { line } {
89    set line_re [string_to_regexp $line]
90
91    set test "tab complete \"$line\""
92    send_gdb "$line\t"
93    gdb_test_multiple "" "$test" {
94	-re "^$line_re$completion::bell_re$" {
95	    pass "$test"
96	}
97    }
98
99    clear_input_line $test
100}
101
102# Test that completing INPUT_LINE with TAB completes to
103# COMPLETE_LINE_RE.  APPEND_CHAR_RE is the character expected to be
104# appended after EXPECTED_OUTPUT.  Normally that's a whitespace, but
105# in some cases it's some other character, like a colon.
106
107proc test_gdb_complete_tab_unique { input_line complete_line_re append_char_re } {
108
109    set test "tab complete \"$input_line\""
110    send_gdb "$input_line\t"
111    gdb_test_multiple "" "$test" {
112	-re "^$complete_line_re$append_char_re$" {
113	    pass "$test"
114	}
115    }
116
117    clear_input_line $test
118}
119
120# Test that completing INPUT_LINE with TAB completes to "INPUT_LINE +
121# ADD_COMPLETED_LINE" and that it displays the completion matches in
122# COMPLETION_LIST.
123
124proc test_gdb_complete_tab_multiple { input_line add_completed_line \
125					  completion_list } {
126    global gdb_prompt
127
128    set input_line_re [string_to_regexp $input_line]
129    set add_completed_line_re [string_to_regexp $add_completed_line]
130
131    set expected_re [make_tab_completion_list_re $completion_list]
132
133    set test "tab complete \"$input_line\""
134    send_gdb "$input_line\t"
135    gdb_test_multiple "" "$test (first tab)" {
136	-re "^${input_line_re}${completion::bell_re}$add_completed_line_re$" {
137	    send_gdb "\t"
138	    # If we auto-completed to an ambiguous prefix, we need an
139	    # extra tab to show the matches list.
140	    if {$add_completed_line != ""} {
141		send_gdb "\t"
142		set maybe_bell ${completion::bell_re}
143	    } else {
144		set maybe_bell ""
145	    }
146	    gdb_test_multiple "" "$test (second tab)" {
147		-re "^${maybe_bell}\r\n$expected_re\r\n$gdb_prompt $input_line_re$add_completed_line_re$" {
148		    pass "$test"
149		}
150	    }
151	}
152    }
153
154    clear_input_line $test
155}
156
157# Test that completing LINE with the complete command completes to
158# nothing.
159
160proc test_gdb_complete_cmd_none { line } {
161    gdb_test_no_output "complete $line" "cmd complete \"$line\""
162}
163
164# Test that completing LINE with the complete command completes to
165# COMPLETE_LINE_RE.
166
167proc test_gdb_complete_cmd_unique { input_line complete_line_re } {
168    global gdb_prompt
169
170    set cmd "complete $input_line"
171    set cmd_re [string_to_regexp $cmd]
172    set test "cmd complete \"$input_line\""
173    gdb_test_multiple $cmd $test {
174	-re "^$cmd_re\r\n$complete_line_re\r\n$gdb_prompt $" {
175	    pass $test
176	}
177    }
178}
179
180# Test that completing "CMD_PREFIX + COMPLETION_WORD" with the
181# complete command displays the COMPLETION_LIST completion list.  Each
182# entry in the list should be prefixed by CMD_PREFIX.
183
184proc test_gdb_complete_cmd_multiple { cmd_prefix completion_word completion_list {start_quote_char ""} {end_quote_char ""} } {
185    global gdb_prompt
186
187    set expected_re [make_cmd_completion_list_re $cmd_prefix $completion_list $start_quote_char $end_quote_char]
188    set cmd_re [string_to_regexp "complete $cmd_prefix$completion_word"]
189    set test "cmd complete \"$cmd_prefix$completion_word\""
190    gdb_test_multiple "complete $cmd_prefix$completion_word" $test {
191	-re "^$cmd_re\r\n$expected_re$gdb_prompt $" {
192	    pass $test
193	}
194    }
195}
196
197# Test that completing LINE completes to nothing.
198
199proc test_gdb_complete_none { input_line } {
200    test_gdb_complete_tab_none $input_line
201    test_gdb_complete_cmd_none $input_line
202}
203
204# Test that completing INPUT_LINE completes to COMPLETE_LINE_RE.
205#
206# APPEND_CHAR is the character expected to be appended after
207# EXPECTED_OUTPUT when TAB completing.  Normally that's a whitespace,
208# but in some cases it's some other character, like a colon.
209#
210# If MAX_COMPLETIONS is true, then we expect the completion to hit the
211# max-completions limit.  Since we're expecting a unique completion
212# match, this will only be visible in the "complete" command output.
213# Tab completion will just auto-complete the only match and won't
214# display a match list.
215#
216# Note: usually it's more convenient to pass a literal string instead
217# of a regular expression (as COMPLETE_LINE_RE).  See
218# test_gdb_complete_unique below.
219
220proc test_gdb_complete_unique_re { input_line complete_line_re {append_char " "} {max_completions 0}} {
221    set append_char_re [string_to_regexp $append_char]
222    test_gdb_complete_tab_unique $input_line $complete_line_re $append_char_re
223
224    # Trim INPUT_LINE and COMPLETE LINE, for the case we're completing
225    # a command with leading whitespace.  Leading command whitespace
226    # is discarded by GDB.
227    set input_line [string trimleft $input_line]
228    set expected_output_re [string trimleft $complete_line_re]
229    if {$append_char_re != " "} {
230	append expected_output_re $append_char_re
231    }
232    if {$max_completions} {
233	set max_completion_reached_msg \
234	    "*** List may be truncated, max-completions reached. ***"
235	set input_line_re \
236	    [string_to_regexp $input_line]
237	set max_completion_reached_msg_re \
238	    [string_to_regexp $max_completion_reached_msg]
239
240	append expected_output_re \
241	    "\r\n$input_line_re $max_completion_reached_msg_re"
242    }
243
244    test_gdb_complete_cmd_unique $input_line $expected_output_re
245}
246
247# Like TEST_GDB_COMPLETE_UNIQUE_RE, but COMPLETE_LINE is a string, not
248# a regular expression.
249
250proc test_gdb_complete_unique { input_line complete_line {append_char " "} {max_completions 0}} {
251    set complete_line_re [string_to_regexp $complete_line]
252    test_gdb_complete_unique_re $input_line $complete_line_re $append_char $max_completions
253}
254
255# Test that completing "CMD_PREFIX + COMPLETION_WORD" adds
256# ADD_COMPLETED_LINE to the input line, and that it displays
257# COMPLETION_LIST as completion match list.  COMPLETION_WORD is the
258# completion word.
259
260proc test_gdb_complete_multiple { cmd_prefix completion_word add_completed_line completion_list {start_quote_char ""} {end_quote_char ""}} {
261    test_gdb_complete_tab_multiple "$cmd_prefix$completion_word" $add_completed_line $completion_list
262    test_gdb_complete_cmd_multiple $cmd_prefix $completion_word $completion_list $start_quote_char $end_quote_char
263}
264
265# Test that all the substring prefixes of INPUT from [0..START) to
266# [0..END) complete to COMPLETION_RE (a regular expression).  If END
267# is ommitted, default to the length of INPUT.
268
269proc test_complete_prefix_range_re {input completion_re start {end -1}} {
270    if {$end == -1} {
271	set end [string length $input]
272    }
273
274    for {set i $start} {$i < $end} {incr i} {
275	set line [string range $input 0 $i]
276	test_gdb_complete_unique_re "$line" $completion_re
277    }
278}
279
280# Test that all the substring prefixes of COMPLETION from [0..START)
281# to [0..END) complete to COMPLETION.  If END is ommitted, default to
282# the length of COMPLETION.
283
284proc test_complete_prefix_range {completion start {end -1}} {
285    set completion_re [string_to_regexp $completion]
286    test_complete_prefix_range_re $completion $completion_re $start $end
287}
288
289# Find NEEDLE in HAYSTACK and return the index _after_ NEEDLE.  E.g.,
290# searching for "(" in "foo(int)" returns 4, which would be useful if
291# you want to find the "(" to try completing "foo(".
292
293proc index_after {needle haystack} {
294    set start [string first $needle $haystack]
295    if {$start == -1} {
296	error "could not find \"$needle\" in \"$haystack\""
297    }
298    return [expr $start + [string length $needle]]
299}
300
301# Create a breakpoint using BREAK_COMMAND, and return the number
302# of locations found.
303
304proc completion::_create_bp {break_command} {
305    global gdb_prompt
306    global decimal hex
307
308    set found_locations -1
309
310    set test "set breakpoint"
311    gdb_test_multiple "$break_command" $test {
312	-re "\\\(\($decimal\) locations\\\)\r\n$gdb_prompt $" {
313	    set found_locations "$expect_out(1,string)"
314	}
315	-re "Breakpoint $decimal at $hex: file .*, line .*$gdb_prompt $" {
316	    set found_locations 1
317	}
318	-re "Make breakpoint pending on future shared library load.*y or .n.. $" {
319	    send_gdb "n\n"
320	    gdb_test_multiple "" "$test (prompt)" {
321		-re "$gdb_prompt $" {
322		}
323	    }
324	    set found_locations 0
325	}
326	-re "invalid explicit location argument, \[^\r\n\]*\r\n$gdb_prompt $" {
327	    set found_locations 0
328	}
329	-re "Function \[^\r\n\]* not defined in \[^\r\n\]*\r\n$gdb_prompt $" {
330	    set found_locations 0
331	}
332    }
333    return $found_locations
334}
335
336# Return true if lists A and B have the same elements.  Order of
337# elements does not matter.
338
339proc completion::_leq {a b} {
340    return [expr {[lsort $a] eq [lsort $b]}]
341}
342
343# Check that trying to create a breakpoint using BREAK_COMMAND fails.
344
345proc check_setting_bp_fails {break_command} {
346    with_test_prefix "\"$break_command\" creates no bp locations" {
347	set found_locations [completion::_create_bp $break_command]
348	gdb_assert {$found_locations == 0} "matches"
349	if {$found_locations != 0} {
350	    delete_breakpoints
351	}
352    }
353}
354
355# Check that creating the breakpoint using BREAK_COMMAND finds the
356# same breakpoint locations as completing BREAK_COMMAND.
357# COMPLETION_LIST is the expected completion match list.
358
359proc check_bp_locations_match_list {break_command completion_list} {
360    global gdb_prompt
361    global hex
362
363    with_test_prefix "compare \"$break_command\" completion list with bp location list" {
364	set num_locations [completion::_create_bp $break_command]
365
366	set found_list ""
367
368	set any "\[^\r\n\]*"
369
370	gdb_test_multiple "info breakpoint \$bpnum" "info breakpoint" {
371	    -re "in \(\[^\r\n\]*\) at " {
372		# A function location.
373		set found_location "$expect_out(1,string)"
374		lappend found_list $found_location
375		exp_continue
376	    }
377	    -re "breakpoint${any}keep${any}y${any}$hex\[ \t]*\(${any}\)\r\n" {
378		# A label location.
379		set found_location "$expect_out(1,string)"
380		lappend found_list $found_location
381		exp_continue
382	    }
383	    -re "$gdb_prompt $" {
384	    }
385	}
386
387	gdb_assert {[completion::_leq $found_list $completion_list]} "matches"
388
389	delete_breakpoints
390    }
391}
392
393# Build linespec and explicit locations out of all the combinations of
394# SOURCES, FUNCTIONS and LABELS, with all combinations of possible
395# quoting and whitespace around separators, and run BODY_LINESPEC and
396# BODY_EXPLICIT in the context of the caller for each combination.  A
397# variable named "location" is set in the callers context with the
398# currently iterated location.
399
400proc foreach_location_functions { sources functions body_linespec body_explicit } {
401    upvar source source
402    upvar function function
403    upvar source_sep source_sep
404    upvar location location
405
406    foreach source $sources {
407	# Test with and without source quoting.
408	foreach sqc $completion::maybe_quoted_list {
409	    if {$source == "" && $sqc != ""} {
410		# Invalid combination.
411		continue
412	    }
413
414	    # Test with and without function quoting.
415	    foreach fqc $completion::maybe_quoted_list {
416		# Test known and unknown functions.
417		foreach function $functions {
418		    # Linespec version.  Test with and without spacing
419		    # after the source/colon colon separator.
420		    foreach source_sep {"" ":" ": "} {
421			# Skip invalid combinations.
422			if {$source == "" && $source_sep != ""} {
423			    continue
424			}
425			if {$source != "" && $source_sep == ""} {
426			    continue
427			}
428
429			set location "${sqc}${source}${sqc}${source_sep}${fqc}$function${fqc}"
430			uplevel 1 $body_linespec
431		    }
432
433		    # Explicit locations version.
434		    if {$source != ""} {
435			set loc_src "-source ${sqc}${source}${sqc} "
436		    } else {
437			set loc_src ""
438		    }
439
440		    set location "${loc_src}-function ${fqc}$function${fqc}"
441		    uplevel 1 $body_explicit
442		}
443	    }
444	}
445    }
446}
447
448# Same as foreach_locations_functions, but also iterate over
449# combinations of labels.
450proc foreach_location_labels { sources functions labels body_linespec body_explicit } {
451    upvar source source
452    upvar function function
453    upvar label label
454    upvar source_sep source_sep
455    upvar label_sep label_sep
456    upvar location location
457
458    # Test both with a known source file and without a source file
459    # component.
460    foreach_location_functions \
461	$sources \
462	$functions \
463	{
464	    # Linespec version.  Test various spacing around the label
465	    # colon separator.
466	    set saved_location ${location}
467	    foreach label_sep {":" " :" ": " " : "} {
468		# Test both known and unknown label.
469		foreach label $labels {
470		    set location "${saved_location}${label_sep}$label"
471		    uplevel 1 $body_linespec
472		}
473	    }
474	} \
475	{
476	    # Explicit locations version.
477	    set saved_location ${location}
478	    foreach label $labels {
479		set location "${saved_location} -label $label"
480		uplevel 1 $body_explicit
481	    }
482	}
483}
484