| # 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 } { |
| 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 |
| } |
| } |
| } |