blob: 326010c44cb4f5a4cede1dd411fd075555926778 [file] [log] [blame]
# Copyright 2012-2016 Free Software Foundation, Inc.
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
# Tests for explicit locations
standard_testfile explicit.c explicit2.c 3explicit.c
set exefile $testfile
if {[prepare_for_testing $testfile $exefile \
[list $srcfile $srcfile2 $srcfile3] {debug nowarnings}]} {
return -1
}
# Wrap the entire test in a namespace to avoid contaminating other tests.
namespace eval $testfile {
# Test the given (explicit) LINESPEC which should cause gdb to break
# at LOCATION.
proc test_breakpoint {linespec location} {
set testname "set breakpoint at \"$linespec\""
# Delete all breakpoints, set a new breakpoint at LINESPEC,
# and attempt to run to it.
delete_breakpoints
if {[gdb_breakpoint $linespec]} {
pass $testname
send_log "\nexpecting locpattern \"$location\"\n"
gdb_continue_to_breakpoint $linespec $location
} else {
fail $testname
}
}
# Add the given LINESPEC to the array named in THEARRAY. GDB is expected
# to stop at LOCATION.
proc add {thearray linespec location} {
upvar $thearray ar
lappend ar(linespecs) $linespec
lappend ar(locations) $location
}
# A list of all explicit linespec arguments.
variable all_arguments
set all_arguments {"source" "function" "label" "line"}
# Some locations used in this test
variable lineno
variable location
set lineno(normal) [gdb_get_line_number "myfunction location" $srcfile]
set lineno(top) [gdb_get_line_number "top location" $srcfile]
foreach v [array names lineno] {
set location($v) ".*[string_to_regexp "$srcfile:$lineno($v)"].*"
}
# A list of explicit locations and the corresponding location.
variable linespecs
set linespecs(linespecs) {}
set linespecs(location) {}
add linespecs "-source $srcfile -function myfunction" $location(normal)
add linespecs "-source $srcfile -function myfunction -label top" \
$location(top)
# This isn't implemented yet; -line is silently ignored.
add linespecs "-source $srcfile -function myfunction -label top -line 3" \
$location(top)
add linespecs "-source $srcfile -line $lineno(top)" $location(top)
add linespecs "-function myfunction" $location(normal)
add linespecs "-function myfunction -label top" $location(top)
# These are also not yet supported; -line is silently ignored.
add linespecs "-function myfunction -line 3" $location(normal)
add linespecs "-function myfunction -label top -line 3" $location(top)
add linespecs "-line 3" $location(normal)
# Fire up gdb.
if {![runto_main]} {
return -1
}
# Turn off queries
gdb_test_no_output "set confirm off"
# Simple error tests (many more are tested in ls-err.exp)
foreach arg $all_arguments {
# Test missing argument
gdb_test "break -$arg" \
[string_to_regexp "missing argument for \"-$arg\""]
# Test abbreviations
set short [string range $arg 0 3]
gdb_test "break -$short" \
[string_to_regexp "missing argument for \"-$short\""]
}
# Test invalid arguments
foreach arg {"-foo" "-foo bar" "-function myfunction -foo" \
"-function -myfunction -foo bar"} {
gdb_test "break $arg" \
[string_to_regexp "invalid explicit location argument, \"-foo\""]
}
# Test explicit locations, with and without conditions.
# For these tests, it is easiest to turn of pending breakpoint.
gdb_test_no_output "set breakpoint pending off" \
"turn off pending breakpoints"
foreach linespec $linespecs(linespecs) loc_pattern $linespecs(locations) {
# Test the linespec
test_breakpoint $linespec $loc_pattern
# Test with a valid condition
delete_breakpoints
set tst "set breakpoint at \"$linespec\" with valid condition"
if {[gdb_breakpoint "$linespec if arg == 0"]} {
pass $tst
gdb_test "info break" ".*stop only if arg == 0.*" \
"info break of conditional breakpoint at \"$linespec\""
} else {
fail $tst
}
# Test with invalid condition
gdb_test "break $linespec if foofoofoo == 1" \
".*No symbol \"foofoofoo\" in current context.*" \
"set breakpoint at \"$linespec\" with invalid condition"
# Test with thread
delete_breakpoints
gdb_test "break $linespec thread 123" "Unknown thread 123."
}
# Tests below are about tab-completion, which doesn't work if readline
# library isn't used. Check it first.
if { [readline_is_used] } {
# Test the explicit location completer
foreach abbrev {"fun" "so" "lab" "li"} full {"function" "source" "label" "line"} {
set tst "complete 'break -$abbrev'"
send_gdb "break -${abbrev}\t"
gdb_test_multiple "" $tst {
"break -$full " {
send_gdb "\n"
gdb_test_multiple "" $tst {
-re "missing argument for \"-$full\".*$gdb_prompt " {
pass $tst
}
}
}
}
set tst "complete -$full with no value"
send_gdb "break -$full \t"
gdb_test_multiple "" $tst {
-re ".*break -$full " {
send_gdb "\n"
gdb_test_multiple "" $tst {
-re ".*Source filename requires function, label, or line offset\..*$gdb_prompt " {
if {[string equal $full "source"]} {
pass $tst
} else {
fail $tst
}
}
-re "missing argument for \"-$full\".*$gdb_prompt " {
pass $tst
}
}
}
}
}
set tst "complete unique function name"
send_gdb "break -function mai\t"
gdb_test_multiple "" $tst {
"break -function mai\\\x07n" {
send_gdb "\n"
gdb_test "" ".*Breakpoint \[0-9\]+.*" $tst
gdb_test_no_output "delete \$bpnum" "delete $tst breakpoint"
}
}
set tst "complete non-unique function name"
send_gdb "break -function myfunc\t"
gdb_test_multiple "" $tst {
"break -function myfunc\\\x07tion" {
send_gdb "\t\t"
gdb_test_multiple "" $tst {
-re "\\\x07\r\nmyfunction\[ \t\]+myfunction2\[ \t\]+myfunction3\[ \t\]+myfunction4\[ \t\]+\r\n$gdb_prompt " {
gdb_test "2" ".*Breakpoint \[0-9\]+.*" $tst
gdb_test_no_output "delete \$bpnum" "delete $tst breakpoint"
}
}
}
}
set tst "complete non-existant function name"
send_gdb "break -function foo\t"
gdb_test_multiple "" $tst {
"break -function foo\\\x07" {
send_gdb "\t\t"
gdb_test_multiple "" $tst {
-re "\\\x07\\\x07" {
send_gdb "\n"
gdb_test "" {Function "foo" not defined.} $tst
}
}
}
}
set tst "complete unique file name"
send_gdb "break -source 3ex\t"
gdb_test_multiple "" $tst {
"break -source 3explicit.c " {
send_gdb "\n"
gdb_test "" \
{Source filename requires function, label, or line offset.} $tst
}
}
set tst "complete non-unique file name"
send_gdb "break -source exp\t"
gdb_test_multiple "" $tst {
"break -source exp\\\x07licit" {
send_gdb "\t\t"
gdb_test_multiple "" $tst {
-re "\\\x07\r\nexplicit.c\[ \t\]+explicit2.c\[ \t\]+\r\n$gdb_prompt" {
send_gdb "\n"
gdb_test "" \
{Source filename requires function, label, or line offset.} \
$tst
}
}
}
"break -source exp\\\x07l" {
# This pattern may occur when glibc debuginfo is installed.
send_gdb "\t\t"
gdb_test_multiple "" $tst {
-re "\\\x07\r\nexplicit.c\[ \t\]+explicit2.c\[ \t\]+expl.*\r\n$gdb_prompt" {
send_gdb "\n"
gdb_test "" \
{Source filename requires function, label, or line offset.} \
$tst
}
}
}
}
set tst "complete non-existant file name"
send_gdb "break -source foo\t"
gdb_test_multiple "" $tst {
"break -source foo" {
send_gdb "\t\t"
gdb_test_multiple "" $tst {
"\\\x07\\\x07" {
send_gdb "\n"
gdb_test "" \
{Source filename requires function, label, or line offset.} \
$tst
}
}
}
}
set tst "complete filename and unique function name"
send_gdb "break -source explicit.c -function ma\t"
gdb_test_multiple "" $tst {
"break -source explicit.c -function main " {
send_gdb "\n"
gdb_test "" ".*Breakpoint .*" $tst
gdb_test_no_output "delete \$bpnum" "delete $tst breakpoint"
}
}
set tst "complete filename and non-unique function name"
send_gdb "break -so 3explicit.c -func myfunc\t"
gdb_test_multiple "" $tst {
"break -so 3explicit.c -func myfunc\\\x07tion" {
send_gdb "\t\t"
gdb_test_multiple "" $tst {
-re "\\\x07\r\nmyfunction3\[ \t\]+myfunction4\[ \t\]+\r\n$gdb_prompt " {
gdb_test "3" ".*Breakpoint \[0-9\]+.*" $tst
gdb_test_no_output "delete \$bpnum" "delete $tst breakpoint"
}
}
}
}
set tst "complete filename and non-existant function name"
send_gdb "break -sou 3explicit.c -fun foo\t"
gdb_test_multiple "" $tst {
"break -sou 3explicit.c -fun foo\\\x07" {
send_gdb "\t\t"
gdb_test_multiple "" $tst {
"\\\x07\\\x07" {
send_gdb "\n"
gdb_test "" \
{Function "foo" not defined in "3explicit.c".} $tst
}
}
}
}
set tst "complete filename and function reversed"
send_gdb "break -func myfunction4 -source 3ex\t"
gdb_test_multiple "" $tst {
"break -func myfunction4 -source 3explicit.c " {
send_gdb "\n"
gdb_test "" "Breakpoint \[0-9\]+.*" $tst
gdb_test_no_output "delete \$bpnum" "delete $tst breakpoint"
}
}
# NOTE: We don't bother testing more elaborate combinations of options,
# such as "-func main -sour 3ex\t" (main is defined in explicit.c).
# The completer cannot handle these yet.
}
# End of completion tests.
# Test pending explicit breakpoints
gdb_exit
gdb_start
set tst "pending invalid conditional explicit breakpoint"
if {![gdb_breakpoint "-func myfunction if foofoofoo == 1" \
allow-pending]} {
fail "set $tst"
} else {
gdb_test "info break" ".*PENDING.*myfunction if foofoofoo == 1.*" $tst
}
gdb_exit
gdb_start
set tst "pending valid conditional explicit breakpoint"
if {![gdb_breakpoint "-func myfunction if arg == 0" \
allow-pending]} {
fail "set $tst"
} else {
gdb_test "info break" ".*PENDING.*myfunction if arg == 0" $tst
gdb_load [standard_output_file $exefile]
gdb_test "info break" \
".*in myfunction at .*$srcfile:.*stop only if arg == 0.*" \
"$tst resolved"
}
# Test interaction of condition command and explicit linespec conditons.
gdb_exit
gdb_start
gdb_load [standard_output_file $exefile]
set tst "condition_command overrides explicit linespec condition"
if {![runto main]} {
fail $tst
} else {
if {![gdb_breakpoint "-func myfunction if arg == 1"]} {
fail "set breakpoint with condition 'arg == 1'"
} else {
gdb_test_no_output "cond 2 arg == 0" \
"set new breakpoint condition for explicit linespec"
gdb_continue_to_breakpoint $tst $location(normal)
}
}
gdb_test "cond 2" [string_to_regexp "Breakpoint 2 now unconditional."] \
"clear condition for explicit breakpoint"
set tst "info break of cleared condition of explicit breakpoint"
gdb_test_multiple "info break" $tst {
-re ".*in myfunction at .*$srcfile:.*stop only if arg == 0.*" {
fail $tst
}
-re ".*in myfunction at .*$srcfile:.*$gdb_prompt $" {
pass $tst
}
}
# Test explicit "ranges." Make sure that using explicit
# locations doesn't alter the expected outcome.
gdb_test "list main" ".*" "list main 1"
set list_result [capture_command_output "list -,+" ""]
gdb_test "list main" ".*" "list main 2"
gdb_test "list -line -,-line +" [string_to_regexp $list_result]
# Ditto for the reverse (except that no output is expected).
gdb_test "list myfunction" ".*" "list myfunction 1"
gdb_test_no_output "list +,-"
gdb_test "list myfunction" ".*" "list myfunction 2"
gdb_test_no_output "list -line +, -line -"
}
namespace delete $testfile