1# Copyright 2012-2020 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# Tests for explicit locations
17
18load_lib completion-support.exp
19
20standard_testfile explicit.c explicit2.c 3explicit.c
21set exefile $testfile
22
23if {[prepare_for_testing "failed to prepare" $exefile \
24	 [list $srcfile $srcfile2 $srcfile3] {debug nowarnings}]} {
25    return -1
26}
27
28# Wrap the entire test in a namespace to avoid contaminating other tests.
29namespace eval $testfile {
30
31    # Test the given (explicit) LINESPEC which should cause gdb to break
32    # at LOCATION.
33    proc test_breakpoint {linespec location} {
34
35	set testname "set breakpoint at \"$linespec\""
36	# Delete all breakpoints, set a new breakpoint at LINESPEC,
37	# and attempt to run to it.
38	delete_breakpoints
39	if {[gdb_breakpoint $linespec]} {
40	    pass $testname
41	    send_log "\nexpecting locpattern \"$location\"\n"
42	    gdb_continue_to_breakpoint $linespec $location
43	} else {
44	    fail $testname
45	}
46    }
47
48    # Add the given LINESPEC to the array named in THEARRAY.  GDB is expected
49    # to stop at LOCATION.
50    proc add {thearray linespec location} {
51	upvar $thearray ar
52
53	lappend ar(linespecs) $linespec
54	lappend ar(locations) $location
55    }
56
57    # A list of all explicit linespec arguments.
58    variable all_arguments
59    set all_arguments {"source" "function" "label" "line"}
60
61    # Some locations used in this test
62    variable lineno
63    variable location
64    set lineno(normal) [gdb_get_line_number "myfunction location" $srcfile]
65    set lineno(top) [gdb_get_line_number "top location" $srcfile]
66    foreach v [array names lineno] {
67	set location($v) ".*[string_to_regexp "$srcfile:$lineno($v)"].*"
68    }
69
70    # A list of explicit locations and the corresponding location.
71    variable linespecs
72    set linespecs(linespecs) {}
73    set linespecs(location) {}
74
75    add linespecs "-source $srcfile -function myfunction" $location(normal)
76    add linespecs "-source $srcfile -function myfunction -label top" \
77	$location(top)
78
79    # This isn't implemented yet; -line is silently ignored.
80    add linespecs "-source $srcfile -function myfunction -label top -line 3" \
81	$location(top)
82    add linespecs "-source $srcfile -line $lineno(top)" $location(top)
83    add linespecs "-function myfunction" $location(normal)
84    add linespecs "-function myfunction -label top" $location(top)
85
86    # These are also not yet supported; -line is silently ignored.
87    add linespecs "-function myfunction -line 3" $location(normal)
88    add linespecs "-function myfunction -label top -line 3" $location(top)
89    add linespecs "-line 3" $location(normal)
90
91    # Fire up gdb.
92    if {![runto_main]} {
93	return -1
94    }
95
96    # Turn off queries
97    gdb_test_no_output "set confirm off"
98
99    # Simple error tests (many more are tested in ls-err.exp)
100    foreach arg $all_arguments {
101	# Test missing argument
102	gdb_test "break -$arg" \
103	    [string_to_regexp "missing argument for \"-$arg\""]
104
105	# Test abbreviations
106	set short [string range $arg 0 3]
107	if { $arg != $short } {
108	    gdb_test "break -$short" \
109		[string_to_regexp "missing argument for \"-$short\""]
110	}
111    }
112
113    # Test invalid arguments
114    foreach arg {"-foo" "-foo bar" "-function myfunction -foo" \
115		     "-function -myfunction -foo bar"} {
116	gdb_test "break $arg" \
117	    [string_to_regexp "invalid explicit location argument, \"-foo\""]
118    }
119
120    # Test explicit locations, with and without conditions.
121    # For these tests, it is easiest to turn of pending breakpoint.
122    gdb_test_no_output "set breakpoint pending off" \
123	"turn off pending breakpoints"
124
125    foreach linespec $linespecs(linespecs) loc_pattern $linespecs(locations) {
126
127	# Test the linespec
128	test_breakpoint $linespec $loc_pattern
129
130	# Test with a valid condition
131	delete_breakpoints
132	set tst "set breakpoint at \"$linespec\" with valid condition"
133	if {[gdb_breakpoint "$linespec if arg == 0"]} {
134	    pass $tst
135
136	    gdb_test "info break" ".*stop only if arg == 0.*" \
137		"info break of conditional breakpoint at \"$linespec\""
138	} else {
139	    fail $tst
140	}
141
142	# Test with invalid condition
143	gdb_test "break $linespec if foofoofoo == 1" \
144	    ".*No symbol \"foofoofoo\" in current context.*" \
145	    "set breakpoint at \"$linespec\" with invalid condition"
146
147	# Test with thread
148	delete_breakpoints
149	gdb_test "break $linespec thread 123" "Unknown thread 123."
150    }
151
152    # Tests below are about tab-completion, which doesn't work if readline
153    # library isn't used.  Check it first.
154    if { [readline_is_used] } {
155
156	# Test the explicit location completer
157	foreach abbrev {"fun" "so" "lab" "li"}  full {"function" "source" "label" "line"} {
158	    set tst "complete 'break -$abbrev'"
159	    send_gdb "break -${abbrev}\t"
160	    gdb_test_multiple "" $tst {
161		-re "break -$full " {
162		    send_gdb "\n"
163		    gdb_test_multiple "" $tst {
164			-re "missing argument for \"-$full\".*$gdb_prompt " {
165			    pass $tst
166			}
167		    }
168		}
169	    }
170	    set tst "complete -$full with no value"
171	    send_gdb "break -$full \t"
172	    gdb_test_multiple "" $tst {
173		-re ".*break -$full " {
174		    send_gdb "\n"
175		    gdb_test_multiple "" $tst {
176			-re ".*Source filename requires function, label, or line offset\..*$gdb_prompt " {
177			    if {[string equal $full "source"]} {
178				pass $tst
179			    } else {
180				fail $tst
181			    }
182			}
183			-re "missing argument for \"-$full\".*$gdb_prompt " {
184			    pass $tst
185			}
186		    }
187		}
188	    }
189	}
190
191	set tst "complete unique function name"
192	send_gdb "break -function my_unique_func\t"
193	gdb_test_multiple "" $tst {
194	    -re "break -function my_unique_function_name" {
195		send_gdb "\n"
196		gdb_test "" ".*Breakpoint \[0-9\]+.*" $tst
197		gdb_test_no_output "delete \$bpnum" "delete $tst breakpoint"
198	    }
199	}
200
201	set tst "complete non-unique function name"
202	send_gdb "break -function myfunc\t"
203	gdb_test_multiple "" $tst {
204	    -re "break -function myfunc\\\x07tion" {
205		send_gdb "\t\t"
206		gdb_test_multiple "" $tst {
207		    -re "\\\x07\r\nmyfunction\[ \t\]+myfunction2\[ \t\]+myfunction3\[ \t\]+myfunction4\[ \t\]+\r\n$gdb_prompt " {
208			gdb_test "2" ".*Breakpoint \[0-9\]+.*" $tst
209			gdb_test_no_output "delete \$bpnum" "delete $tst breakpoint"
210		    }
211		}
212	    }
213	}
214
215	set tst "complete non-existant function name"
216	send_gdb "break -function foo\t"
217	gdb_test_multiple "" $tst {
218	    -re "break -function foo\\\x07" {
219		send_gdb "\t\t"
220		gdb_test_multiple "" $tst {
221		    -re "\\\x07\\\x07" {
222			send_gdb "\n"
223			gdb_test "" {Function "foo" not defined.} $tst
224		    }
225		}
226	    }
227	}
228
229	with_test_prefix "complete unique file name" {
230	    foreach qc $completion::maybe_quoted_list {
231		set cmd "break -source ${qc}3explicit.c${qc}"
232		test_gdb_complete_unique \
233		    "break -source ${qc}3ex" \
234		    $cmd
235		gdb_test $cmd \
236		    {Source filename requires function, label, or line offset.}
237	    }
238	}
239
240	set tst "complete non-unique file name"
241	send_gdb "break -source exp\t"
242	# We're matching two cases here:
243	# - without GLIBC debuginfo
244	#   (gdb) break -source exp^Glicit^G^M
245	#   explicit.c  explicit2.c  ^M
246	#   (gdb) break -source explicit^M
247	#   Source filename requires function, label, or line offset.^M
248	#   (gdb) PASS: gdb.linespec/explicit.exp: complete non-unique file name
249	# - with GLIBC debuginfo:
250	#   (gdb) break -source exp^Gl^G^M
251	#   explicit.c  explicit2.c  explicit_bzero.c  explicit_bzero_chk.c \
252	#     explodename.c  ^M
253	#   (gdb) break -source expl^M
254	#   Source filename requires function, label, or line offset.^M
255	#   (gdb) PASS: gdb.linespec/explicit.exp: complete non-unique file name
256	gdb_test_multiple "" $tst {
257	    -re "break -source exp\\\x07l" {
258		# At this point, either output is done (first case), or a
259		# further "icit" is emitted (second case).  We have no reliable
260		# way to decide one way or another, so just send the tabs, even
261		# though that may be a little early in the second case.
262		send_gdb "\t\t"
263		gdb_test_multiple "" $tst {
264		    -re "\\\x07\r\nexplicit.c\[ \t\]+explicit2.c\[ \t\]+\(expl.*\)?\r\n$gdb_prompt" {
265			send_gdb "\n"
266			gdb_test "" \
267			    {Source filename requires function, label, or line offset.} \
268			    $tst
269		    }
270		}
271	    }
272	}
273
274	set tst "complete non-existant file name"
275	send_gdb "break -source foo\t"
276	gdb_test_multiple "" $tst {
277	    -re "break -source foo" {
278		send_gdb "\t\t"
279		gdb_test_multiple "" $tst {
280		    -re "\\\x07\\\x07" {
281			send_gdb "\n"
282			gdb_test "" \
283			    {Source filename requires function, label, or line offset.} \
284			    $tst
285		    }
286		}
287	    }
288	}
289
290	set tst "complete filename and unique function name"
291	send_gdb "break -source explicit.c -function ma\t"
292	gdb_test_multiple "" $tst {
293	    -re "break -source explicit.c -function main " {
294		send_gdb "\n"
295		gdb_test "" ".*Breakpoint .*" $tst
296		gdb_test_no_output "delete \$bpnum" "delete $tst breakpoint"
297	    }
298	}
299
300	set tst "complete filename and non-unique function name"
301	send_gdb "break -so 3explicit.c -func myfunc\t"
302	gdb_test_multiple "" $tst {
303	    -re "break -so 3explicit.c -func myfunc\\\x07tion" {
304		send_gdb "\t\t"
305		gdb_test_multiple "" $tst {
306		    -re "\\\x07\r\nmyfunction3\[ \t\]+myfunction4\[ \t\]+\r\n$gdb_prompt " {
307			gdb_test "3" ".*Breakpoint \[0-9\]+.*" $tst
308			gdb_test_no_output "delete \$bpnum" "delete $tst breakpoint"
309		    }
310		}
311	    }
312	}
313
314	set tst "complete filename and non-existant function name"
315	send_gdb "break -sou 3explicit.c -fun foo\t"
316	gdb_test_multiple "" $tst {
317	    -re "break -sou 3explicit.c -fun foo\\\x07" {
318		send_gdb "\t\t"
319		gdb_test_multiple "" $tst {
320		    -re "\\\x07\\\x07" {
321			send_gdb "\n"
322			gdb_test "" \
323			    {Function "foo" not defined in "3explicit.c".} $tst
324		    }
325		}
326	    }
327	}
328
329	set tst "complete filename and function reversed"
330	send_gdb "break -func myfunction4 -source 3ex\t"
331	gdb_test_multiple "" $tst {
332	    -re "break -func myfunction4 -source 3explicit.c " {
333		send_gdb "\n"
334		gdb_test "" "Breakpoint \[0-9\]+.*" $tst
335		gdb_test_no_output "delete \$bpnum" "delete $tst breakpoint"
336	    }
337	}
338
339	with_test_prefix "complete unique label name" {
340	    foreach qc $completion::maybe_quoted_list {
341		test_gdb_complete_unique \
342		    "break -function myfunction -label ${qc}to" \
343		    "break -function myfunction -label ${qc}top${qc}"
344	    }
345	}
346
347	with_test_prefix "complete unique label name with source file" {
348	    test_gdb_complete_unique \
349		"break -source explicit.c -function myfunction -label to" \
350		"break -source explicit.c -function myfunction -label top"
351	}
352
353	with_test_prefix "complete unique label name reversed" {
354	    test_gdb_complete_multiple "b -label top -function " "myfunction" "" {
355		"myfunction"
356		"myfunction2"
357		"myfunction3"
358		"myfunction4"
359	    }
360	}
361
362	with_test_prefix "complete non-unique label name" {
363	    test_gdb_complete_multiple "b -function myfunction -label " "" "" {
364		"done"
365		"top"
366	    }
367	}
368
369	# The program is stopped at myfunction, so gdb is able to
370	# infer the label's function.
371	with_test_prefix "complete label name with no function" {
372	    test_gdb_complete_unique \
373		"break -label to" \
374		"break -label top"
375	    check_bp_locations_match_list \
376		"break -label top" {
377		    "-function myfunction -label top"
378		}
379	}
380
381	# See above.
382	with_test_prefix "complete label name with source file but no function" {
383	    test_gdb_complete_unique \
384		"break -source explicit.c -label to" \
385		"break -source explicit.c -label top"
386	    check_bp_locations_match_list \
387		"break -source explicit.c -label top" {
388		    "-source explicit.c -function myfunction -label top"
389		}
390	}
391
392	with_test_prefix "complete label name with wrong source file" {
393	    test_gdb_complete_none \
394		"break -source explicit2.c -function myfunction -label to"
395	    check_setting_bp_fails \
396		"break -source explicit2.c -function myfunction -label top"
397	}
398
399	# Get rid of symbols from shared libraries, otherwise
400	# "b -source thr<tab>" could find some system library's
401	# source.
402	gdb_test_no_output "nosharedlibrary"
403
404	# Test that after a seemingly finished option argument,
405	# completion matches both the explicit location options and
406	# the linespec keywords.
407	set completions_list {
408	    "-function"
409	    "-label"
410	    "-line"
411	    "-qualified"
412	    "-source"
413	    "if"
414	    "task"
415	    "thread"
416	}
417	foreach what { "-function" "-label" "-line" "-source" } {
418	    # Also test with "-qualified" appearing before the
419	    # explicit location.
420	    foreach prefix {"" "-qualified "} {
421
422		# ... and with "-qualified" appearing after the
423		# explicit location.
424		foreach suffix {"" " -qualified"} {
425		    with_test_prefix "complete after $prefix$what$suffix" {
426			if {$what != "-line"} {
427			    set w "$prefix$what argument$suffix "
428			    test_gdb_complete_multiple \
429				"b $w" "" "" $completions_list
430			    test_gdb_complete_unique \
431				"b $w thr" \
432				"b $w thread"
433			    test_gdb_complete_unique \
434				"b $w -fun" \
435				"b $w -function"
436			} else {
437			    # After -line, we expect a number / offset.
438			    foreach line {"10" "+10" "-10"} {
439				set w "$prefix-line $line$suffix"
440				test_gdb_complete_multiple \
441				    "b $w " "" "" $completions_list
442				test_gdb_complete_unique \
443				    "b $w thr" \
444				    "b $w thread"
445				test_gdb_complete_unique \
446				    "b $w -fun" \
447				    "b $w -function"
448			    }
449
450			    # With an invalid -line argument, we don't get any
451			    # completions.
452			    test_gdb_complete_none "b $prefix-line argument$suffix "
453			}
454
455		    }
456
457		}
458
459		# These tests don't make sense with "-qualified" after
460		# the location.
461		with_test_prefix "complete after $prefix$what" {
462		    # Don't complete a linespec keyword ("thread") or
463		    # another option name when expecting an option
464		    # argument.
465		    test_gdb_complete_none "b $prefix$what thr"
466		    test_gdb_complete_none "b $prefix$what -fun"
467		}
468	    }
469	}
470
471	# Tests that ensure that after "if" we complete on expressions
472	# are in cpcompletion.exp.
473
474	# Disable the completion limit for the rest of the testcase.
475	gdb_test_no_output "set max-completions unlimited"
476
477	# Get rid of symbols from shared libraries, otherwise the
478	# completions match list for "break <tab>" is huge and makes
479	# the test below quite long while the gdb_test_multiple loop
480	# below consumes the matches.  Not doing this added ~20
481	# seconds at the time of writing.  (Actually, already done above.)
482	# gdb_test_no_output "nosharedlibrary"
483
484	# Test completion with no input argument.  We should see all
485	# the options, plus all the functions.  To keep it simple, as
486	# proxy, we check for presence of one explicit location
487	# option, one probe location, and one function.
488	set saw_opt_function 0
489	set saw_opt_probe_stap 0
490	set saw_function 0
491
492	set tst "complete with no arguments"
493	send_gdb "break \t"
494	gdb_test_multiple "" $tst {
495	    "break \\\x07" {
496		send_gdb "\t"
497		gdb_test_multiple "" $tst {
498		    "Display all" {
499			send_gdb "y"
500			exp_continue
501		    }
502		    -re "-function" {
503			set saw_opt_function 1
504			exp_continue
505		    }
506		    -re "-probe-stap" {
507			set saw_opt_probe_stap 1
508			exp_continue
509		    }
510		    -re "myfunction4" {
511			set saw_function 1
512			exp_continue
513		    }
514		    -re "\r\n$gdb_prompt " {
515			gdb_assert {$saw_opt_function && $saw_opt_probe_stap && $saw_function} $tst
516		    }
517		    -re "  " {
518			exp_continue
519		    }
520		}
521	    }
522	}
523	clear_input_line $tst
524
525	# NOTE: We don't bother testing more elaborate combinations of options,
526	# such as "-func main -sour 3ex\t" (main is defined in explicit.c).
527	# The completer cannot handle these yet.
528
529	# The following completion tests require having no symbols
530	# loaded.
531	gdb_exit
532	gdb_start
533
534	# The match list you get when you complete with no options
535	# specified at all.
536	set completion_list {
537	    "-function"
538	    "-label"
539	    "-line"
540	    "-probe"
541	    "-probe-dtrace"
542	    "-probe-stap"
543	    "-qualified"
544	    "-source"
545	}
546	with_test_prefix "complete with no arguments and no symbols" {
547	    test_gdb_complete_multiple "b " "" "-" $completion_list
548	    test_gdb_complete_multiple "b " "-" "" $completion_list
549	}
550    }
551    # End of completion tests.
552
553    # Test pending explicit breakpoints
554    gdb_exit
555    gdb_start
556
557    set tst "pending invalid conditional explicit breakpoint"
558    if {![gdb_breakpoint "-func myfunction if foofoofoo == 1" \
559	      allow-pending]} {
560	fail "set $tst"
561    } else {
562	gdb_test "info break" ".*PENDING.*myfunction if foofoofoo == 1.*" $tst
563    }
564
565    gdb_exit
566    gdb_start
567
568    set tst "pending valid conditional explicit breakpoint"
569    if {![gdb_breakpoint "-func myfunction if arg == 0" \
570	      allow-pending]} {
571	fail "set $tst"
572    } else {
573	gdb_test "info break" ".*PENDING.*myfunction if arg == 0" $tst
574
575	gdb_load [standard_output_file $exefile]
576	gdb_test "info break" \
577	    ".*in myfunction at .*$srcfile:.*stop only if arg == 0.*" \
578	    "$tst resolved"
579    }
580
581    # Test interaction of condition command and explicit linespec conditons.
582    gdb_exit
583    gdb_start
584    gdb_load [standard_output_file $exefile]
585
586    set tst "condition_command overrides explicit linespec condition"
587    if {![runto main]} {
588	fail $tst
589    } else {
590	if {![gdb_breakpoint "-func myfunction if arg == 1"]} {
591	    fail "set breakpoint with condition 'arg == 1'"
592	} else {
593	    gdb_test_no_output "cond 2 arg == 0" \
594		"set new breakpoint condition for explicit linespec"
595
596	    gdb_continue_to_breakpoint $tst $location(normal)
597	}
598    }
599
600    gdb_test "cond 2" [string_to_regexp "Breakpoint 2 now unconditional."] \
601	"clear condition for explicit breakpoint"
602    set tst "info break of cleared condition of explicit breakpoint"
603    gdb_test_multiple "info break" $tst {
604	-re ".*in myfunction at .*$srcfile:.*stop only if arg == 0.*" {
605	    fail $tst
606	}
607	-re ".*in myfunction at .*$srcfile:.*$gdb_prompt $" {
608	    pass $tst
609	}
610    }
611
612    # Test explicit "ranges."  Make sure that using explicit
613    # locations doesn't alter the expected outcome.
614    gdb_test "list main" ".*" "list main 1"
615    set list_result [capture_command_output "list -,+" ""]
616    gdb_test "list main" ".*" "list main 2"
617    gdb_test "list -line -,-line +" [string_to_regexp $list_result]
618
619    # Ditto for the reverse (except that no output is expected).
620    gdb_test "list myfunction" ".*" "list myfunction 1"
621    gdb_test_no_output "list +,-"
622    gdb_test "list myfunction" ".*" "list myfunction 2"
623    gdb_test_no_output "list -line +, -line -"
624}
625
626namespace delete $testfile
627