blob: 62fb49570a64f2ee0dab3bdf39ed3ab89c88fad3 [file] [log] [blame]
# Copyright 2024 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 filename completion. Create a directory tree on the test
# machine and try completing filenames within the tree.
load_lib completion-support.exp
# Setup a directory tree in which completion tests can be run. The
# structure is:
#
# root/ [ DIRECTORY ]
# aaa/ [ DIRECTORY ]
# aa bb [ FILE ]
# aa cc [ FILE ]
# aaa/ [ DIRECTORY ]
# bb1/ [ DIRECTORY ]
# bb2/ [ DIRECTORY ]
# dir 1/ [ DIRECTORY ]
# unique file [ FILE ]
# dir 2/ [ DIRECTORY ]
# file 1 [ FILE ]
# file 2 [ FILE ]
# cc1/ [ DIRECTORY ]
# cc2 [ FILE ]
proc setup_directory_tree {} {
set root [standard_output_file "root"]
remote_exec host "mkdir -p ${root}"
remote_exec host "mkdir -p ${root}/aaa"
remote_exec host "mkdir -p ${root}/bb1"
remote_exec host "mkdir -p ${root}/bb2"
remote_exec host "mkdir -p ${root}/cc1"
remote_exec host "touch ${root}/cc2"
remote_exec host "touch \"${root}/aaa/aa bb\""
remote_exec host "touch \"${root}/aaa/aa cc\""
remote_exec host "mkdir -p \"${root}/bb2/dir 1\""
remote_exec host "mkdir -p \"${root}/bb2/dir 2\""
remote_exec host "touch \"${root}/bb2/dir 1/unique file\""
remote_exec host "touch \"${root}/bb2/dir 2/file 1\""
remote_exec host "touch \"${root}/bb2/dir 2/file 2\""
remote_exec host "touch \"${root}/bb1/aa\\\"bb\""
remote_exec host "touch \"${root}/bb1/aa'bb\""
return $root
}
# This proc started as a copy of test_gdb_complete_multiple, however, this
# version does some extra work. See the original test_gdb_complete_multiple
# for a description of all the arguments.
#
# When using the 'complete' command with filenames, GDB will add a trailing
# quote for filenames, and a trailing "/" for directory names. As the
# trailing "/" is also added in the tab-completion output the
# COMPLETION_LIST will include the "/" character, but the trailing quote is
# only added when using the 'complete' command.
#
# Pass the trailing quote will be passed as END_QUOTE_CHAR, this proc will
# run the tab completion test, and will then add the trailing quote to those
# entries in COMPLETION_LIST that don't have a trailing "/" before running
# the 'complete' command test.
proc test_gdb_complete_filename_multiple {
cmd_prefix completion_word add_completed_line completion_list
{start_quote_char ""} {end_quote_char ""} {max_completions false}
{testname ""}
} {
if { [readline_is_used] } {
test_gdb_complete_tab_multiple "$cmd_prefix$completion_word" \
$add_completed_line $completion_list $max_completions $testname
}
if { $start_quote_char eq "" } {
set updated_completion_list {}
foreach entry $completion_list {
# If ENTRY is quoted with double quotes, then any double
# quotes within the entry need to be escaped.
if { $end_quote_char eq "\"" } {
regsub -all "\"" $entry "\\\"" entry
}
if { $end_quote_char eq "" } {
regsub -all " " $entry "\\ " entry
regsub -all "\"" $entry "\\\"" entry
regsub -all "'" $entry "\\'" entry
}
if {[string range $entry end end] ne "/"} {
set entry $entry$end_quote_char
}
lappend updated_completion_list $entry
}
set completion_list $updated_completion_list
set end_quote_char ""
}
test_gdb_complete_cmd_multiple $cmd_prefix $completion_word \
$completion_list $start_quote_char $end_quote_char $max_completions \
$testname
}
# Run filename completetion tests for those command that accept quoting and
# escaping of the filename argument.
#
# ROOT is the base directory as returned from setup_directory_tree, though,
# if ROOT is a sub-directory of the user's home directory ROOT might have
# been modified to replace the $HOME prefix with a single "~" character.
proc run_quoting_and_escaping_tests { root } {
# Test all the commands which allow quoting of filenames, and
# which require whitespace to be escaped in unquoted filenames.
foreach_with_prefix cmd { file exec-file symbol-file add-symbol-file \
remove-symbol-file } {
gdb_start
# Completing 'thread apply all ...' commands uses a custom word
# point. At one point we had a bug where doing this would break
# completion of quoted filenames that contained white space.
test_gdb_complete_unique "thread apply all hel" \
"thread apply all help" " " false \
"complete a 'thread apply all' command"
foreach_with_prefix qc [list "" "'" "\""] {
test_gdb_complete_none "$cmd ${qc}${root}/xx" \
"expand a non-existent filename"
test_gdb_complete_unique "$cmd ${qc}${root}/a" \
"$cmd ${qc}${root}/aaa/" "" false \
"expand a unique directory name"
test_gdb_complete_unique "$cmd ${qc}${root}/cc2" \
"$cmd ${qc}${root}/cc2${qc}" " " false \
"expand a unique filename"
test_gdb_complete_filename_multiple "$cmd ${qc}${root}/" \
"b" "b" {
"bb1/"
"bb2/"
} "" "${qc}" false \
"expand multiple directory names"
test_gdb_complete_filename_multiple "$cmd ${qc}${root}/" \
"c" "c" {
"cc1/"
"cc2"
} "" "${qc}" false \
"expand mixed directory and file names"
if { $qc ne "" } {
set sp " "
} else {
set sp "\\ "
}
if { $qc eq "'" } {
set dq "\""
} else {
set dq "\\\""
}
test_gdb_complete_unique "${cmd} ${qc}${root}/bb2/dir${sp}1/" \
"${cmd} ${qc}${root}/bb2/dir${sp}1/unique${sp}file${qc}" " " \
false \
"expand a unique file name in a directory containing a space"
test_gdb_complete_filename_multiple "$cmd ${qc}${root}/bb2/" \
"d" "ir${sp}" {
"dir 1/"
"dir 2/"
} "" "${qc}" false \
"expand multiple directory names containing spaces"
test_gdb_complete_filename_multiple "${cmd} ${qc}${root}/bb2/dir${sp}2/" \
"f" "ile${sp}" {
"file 1"
"file 2"
} "" "${qc}" false \
"expand contents of a directory containing a space"
test_gdb_complete_filename_multiple "$cmd ${qc}${root}/aaa/" \
"a" "a${sp}" {
"aa bb"
"aa cc"
} "" "${qc}" false \
"expand filenames containing spaces"
test_gdb_complete_filename_multiple "$cmd ${qc}${root}/bb1/" \
"a" "a" {
"aa\"bb"
"aa'bb"
} "" "${qc}" false \
"expand filenames containing quotes"
test_gdb_complete_unique "$cmd ${qc}${root}/bb1/aa${dq}" \
"$cmd ${qc}${root}/bb1/aa${dq}bb${qc}" " " false \
"expand unique filename containing double quotes"
# It is not possible to include a single quote character
# within a single quoted string. However, GDB does not do
# anything smart if a user tries to do this. Avoid testing
# this case. Maybe in the future we'll figure a way to avoid
# this situation.
if { $qc ne "'" } {
if { $qc eq "" } {
set sq "\\'"
} else {
set sq "'"
}
test_gdb_complete_unique "$cmd ${qc}${root}/bb1/aa${sq}" \
"$cmd ${qc}${root}/bb1/aa${sq}bb${qc}" " " false \
"expand unique filename containing single quote"
}
}
gdb_exit
}
}
# Helper for run_unquoted_tests. ROOT is the root directory as setup
# by setup_directory_tree. CMD is the GDB command to test. PREFIX is
# a possible prefix filename to prepend to the filename being
# completed.
proc run_unquoted_tests_core { root cmd { prefix "" } } {
gdb_start
if { $prefix != "" } {
# Platform specific path separator (':' on UNIX, ';' on MS-DOS).
set pathsep $::tcl_platform(pathSeparator)
set prefix ${prefix}${pathsep}
}
test_gdb_complete_none "$cmd ${prefix}${root}${root}/xx" \
"expand a non-existent filename"
test_gdb_complete_unique "$cmd ${prefix}${root}/a" \
"$cmd ${prefix}${root}/aaa/" "" false \
"expand a unique filename"
test_gdb_complete_unique "$cmd ${prefix}${root}/bb2/dir 1/uni" \
"$cmd ${prefix}${root}/bb2/dir 1/unique file" " " false \
"expand a unique filename containing whitespace"
test_gdb_complete_multiple "$cmd ${prefix}${root}/" \
"b" "b" {
"bb1/"
"bb2/"
} "" "" false \
"expand multiple directory names"
test_gdb_complete_multiple "$cmd ${prefix}${root}/" \
"c" "c" {
"cc1/"
"cc2"
} "" "" false \
"expand mixed directory and file names"
test_gdb_complete_multiple "$cmd ${prefix}${root}/aaa/" \
"a" "a " {
"aa bb"
"aa cc"
} "" "" false \
"expand filenames containing spaces"
test_gdb_complete_multiple "$cmd ${prefix}${root}/bb2/dir 2/" \
"fi" "le " {
"file 1"
"file 2"
} "" "" false \
"expand filenames containing spaces in path"
gdb_exit
}
# Run filename completetion tests for a sample of commands that take an
# unquoted, unescaped filename as an argument. Only a sample of commands
# are (currently) tested as there's a lot of commands that accept this style
# of filename argument.
#
# ROOT is the base directory as returned from setup_directory_tree, though,
# if ROOT is a sub-directory of the user's home directory ROOT might have
# been modified to replace the $HOME prefix with a single "~" character.
proc run_unquoted_tests { root } {
# Test all the commands which allow quoting of filenames, and
# which require whitespace to be escaped in unquoted filenames.
foreach_with_prefix cmd { "maint print c-tdesc" "set logging file" \
"target core" "add-auto-load-safe-path" } {
run_unquoted_tests_core $root $cmd
}
foreach prefix [list \
"${root}/bb2/dir 1" \
"${root}/bb2/dir 1/unique file" \
"${root}/cc1" \
"${root}/cc2"] {
# Don't use the full path in the test name, just use the
# part after the ROOT directory.
set id [string range $prefix [string length ${root}] end]
with_test_prefix "prefix=$id" {
foreach_with_prefix cmd { "add-auto-load-safe-path" "path" } {
run_unquoted_tests_core $root $cmd $prefix
}
}
}
}
set root [setup_directory_tree]
run_quoting_and_escaping_tests $root
run_unquoted_tests $root
# This test relies on using the $HOME directory. We could make this
# work for remote hosts, but right now, this isn't supported.
if {![is_remote host]} {
# The users home directory.
set home $::env(HOME)
# Check if ROOT is within the $HOME directory. If it is then we can
# rerun the tests, but replacing the $HOME part with "~".
if { [string compare -length [string length $home] $root $home] == 0 } {
# Convert the $HOME prefix in to ~.
set tilde_root "~[string range $root [string length $home] end]"
with_test_prefix "with tilde" {
# And rerun the tests.
run_quoting_and_escaping_tests $tilde_root
run_unquoted_tests $tilde_root
}
}
}