Improved test suite from bash-completion-lib

Run the tests with:
$ cd test
$ ./runCompletionUnit
$ ./runCompletionCompletion

The last test of unit/_known_hosts gives UNRESOLVED and needs fixing.
master
Freddy Vulto 2009-06-09 22:49:53 +02:00
parent 468ba8f150
commit e847d57e50
29 changed files with 1001 additions and 15 deletions

View File

@ -1064,7 +1064,7 @@ _known_hosts()
_known_hosts_real()
{
local configfile
local configfile flag
local curd ocur user suffix aliases global_kh user_kh hosts i host
local -a kh khd config
local IFS=$'\n'
@ -1199,6 +1199,8 @@ _known_hosts_real()
COMPREPLY=( $( compgen -A hostname -S "$suffix" -- $cur ) )
fi
[ $ocur ] && cur=$ocur || unset -v cur
return 0
}
complete -F _known_hosts traceroute traceroute6 tracepath tracepath6 \

View File

@ -80,7 +80,7 @@ _ssh()
-N -n -q -s -T -t -V -v -X -v -Y -y -b -b -c -D -e -F \
-i -L -l -m -O -o -p -R -S -w' -- $cur ) )
else
if [ $COMP_CWORD -eq 1 ]; then
#if [ $COMP_CWORD -eq 1 ]; then
# Search COMP_WORDS for '-F configfile' argument
set -- "${COMP_WORDS[@]}"
while [ $# -gt 0 ]; do
@ -96,9 +96,9 @@ _ssh()
shift
done
_known_hosts_real -a "$optconfigfile"
else
#else
COMPREPLY=( "${COMPREPLY[@]}" $( compgen -c -- $cur ) )
fi
#fi
fi
return 0

1
doc/bashrc Symbolic link
View File

@ -0,0 +1 @@
../test/config/bashrc

155
doc/html~/main.html Normal file

File diff suppressed because one or more lines are too long

1
doc/inputrc Symbolic link
View File

@ -0,0 +1 @@
../test/config/inputrc

View File

@ -37,22 +37,23 @@ Main areas (DejaGnu tools)
The tests are grouped into different areas, called _tool_ in DejaGnu:
*install*::
Functional tests for installation and caching of the main bash-completion package.
*completion*::
Functional tests per completion.
*install*::
Functional tests for installation and caching of the main bash-completion package.
*unit*::
Unit tests for bash-completion helper functions.
Each tool has a slightly different way of loading the test fixtures, see <<Test_context,Test context>> below.
Running the tests
~~~~~~~~~~~~~~~~~
The tests are run by calling `runtest` in the test directory:
-----------------------
runtest --outdir=log --tool completion
runtest --outdir=log --tool install
runtest --outdir=log --tool unit
runtest --outdir log --tool completion
runtest --outdir log --tool install
runtest --outdir log --tool unit
-----------------------
The commands above are already wrapped up in shell scripts within the `test` directory:
-----------------------
@ -74,7 +75,178 @@ Adding a completion test
You can add script/generate to add a test.
Fixing a completion test
~~~~~~~~~~~~~~~~~~~~~~~~
Let's consider this real-life example where an ssh completion bug is fixed. First you're triggered by unsuccessful tests:
----------------------------------
$ ./runCompletion
...
=== completion Summary ===
# of expected passes 283
# of unexpected failures 8
# of unresolved testcases 2
# of unsupported tests 47
----------------------------------
Take a look in `log/completion.log` to find out which specific command is failing.
-----------------------
$ vi log/completion.log
-----------------------
Search for `UNRESOLVED` or `FAIL`. From there scroll up to see which `.exp` test is failing:
---------------------------------------------------------
/@Running ./completion/ssh.exp ...
...
UNRESOLVED: Tab should complete ssh known-hosts at prompt
---------------------------------------------------------
In this case it appears `ssh.exp` is causing the problem. Isolate the `ssh` tests by specifying just `ssh.exp` to run. Furthermore add the `--debug` flag, so output gets logged in `dbg.log`:
----------------------------------
$ ./runCompletion ssh.exp --debug
...
=== completion Summary ===
# of expected passes 1
# of unresolved testcases 1
----------------------------------
Now we can have a detailed look in `dbg.log` to find out what's going wrong. Open `dbg.log` and search for `UNRESOLVED` (or `FAIL` if that's what you're looking for):
---------------------------------------------------------
UNRESOLVED: Tab should complete ssh known-hosts at prompt
---------------------------------------------------------
From there, search up for the first line saying:
-------------------------------------------------
expect: does "..." match regular expression "..."
-------------------------------------------------
This tells you where the actual output differs from the expected output. In this case it looks like the test "ssh -F fixtures/ssh/config <TAB>" is expecting just hostnames, whereas the actual completion is containing commands - but no hostnames.
So what should be expected after "ssh -F fixtures/ssh/config <TAB>" are *both* commands and hostnames. This means both the test and the completion need fixing. Let's start with the test.
----------------------------
$ vi lib/completions/ssh.exp
----------------------------
Search for the test "Tab should complete ssh known-hosts". Here you could've seen that what was expected were hostnames ($hosts):
-----------------------------------------
set expected "^$cmd\r\n$hosts\r\n/@$cmd$"
-----------------------------------------
Adding *all* commands (which could well be over 2000) to 'expected', seems a bit overdone so we're gonna change things here. Lets expect the unit test for `_known_hosts` assures all hosts are returned. Then all we need to do here is expect one host and one command, just to be kind of sure that both hosts and commands are completed.
Looking in the fixture for ssh:
-----------------------------
$ vi fixtures/ssh/known_hosts
-----------------------------
it looks like we can add an additional host 'ls_known_host'. Now if we would perform the test "ssh -F fixtures/ssh/config ls<TAB>" both the command `ls` and the host `ls_known_host` should come up. Let's modify the test so:
--------------------------------------------------------
$ vi lib/completions/ssh.exp
...
set expected "^$cmd\r\n.*ls.*ls_known_host.*\r\n/@$cmd$"
--------------------------------------------------------
Running the test reveals we still have an unresolved test:
----------------------------------
$ ./runCompletion ssh.exp --debug
...
=== completion Summary ===
# of expected passes 1
# of unresolved testcases 1
----------------------------------
But if now look into the log file `dbg.log` we can see the completion only returns commands starting with 'ls' but fails to match our regular expression which also expects the hostname `ls_known_host':
-----------------------
$ vi dbg.log
...
expect: does "ssh -F fixtures/ssh/config ls\r\nls lsattr lsb_release lshal lshw lsmod lsof lspci lspcmcia lspgpot lss16toppm\r\nlsusb\r\n/@ssh -F fixtures/ssh/config ls" (spawn_id exp9) match regular expression "^ssh -F fixtures/ssh/config ls\r\n.*ls.*ls_known_host.*\r\n/@ssh -F fixtures/ssh/config ls$"? no
-----------------------
Now let's fix ssh completion:
-------------------
$ vi ../contrib/ssh
...
-------------------
until the test shows:
----------------------------------
$ ./runCompletion ssh.exp
...
=== completion Summary ===
# of expected passes 2
----------------------------------
Fixing a unit test
~~~~~~~~~~~~~~~~~~
Now let's consider a unit test failure. First you're triggered by unsuccessful tests:
----------------------------------
$ ./runUnit
...
=== unit Summary ===
# of expected passes 1
# of unexpected failures 1
----------------------------------
Take a look in `log/unit.log` to find out which specific command is failing.
-----------------
$ vi log/unit.log
-----------------
Search for `UNRESOLVED` or `FAIL`. From there scroll up to see which `.exp` test is failing:
------------------------------------------
/@Running ./unit/_known_hosts_real.exp ...
...
FAIL: Environment should stay clean
------------------------------------------
In this case it appears `_known_hosts_real.exp` is causing the problem. Isolate the `_known_hosts_real` test by specifying just `_known_hosts_real.exp` to run. Furthermore add the `--debug` flag, so output gets logged in `dbg.log`:
----------------------------------
$ ./runUnit _known_hosts_real.exp --debug
...
=== completion Summary ===
# of expected passes 1
# of unexpected failures 1
----------------------------------
Now, if we haven't already figured out the problem, we can have a detailed look in `dbg.log` to find out what's going wrong. Open `dbg.log` and search for `UNRESOLVED` (or `FAIL` if that's what you're looking for):
-----------------------------------
FAIL: Environment should stay clean
-----------------------------------
From there, search up for the first line saying:
-------------------------------------------------
expect: does "..." match regular expression "..."
-------------------------------------------------
This tells you where the actual output differs from the expected output. In this case it looks like the the function `_known_hosts_real` is unexpectedly modifying global variables `cur` and `flag`. In case you need to modify the test:
-----------------------------------
$ vi lib/unit/_known_hosts_real.exp
-----------------------------------
Rationale
---------
@ -100,16 +272,109 @@ The name and location of this code generation script come from Ruby on Rails' ht
Within test scripts the following library functions can be used:
== The test environment
[[Test_context]]
== Test context
The tests run in a specially prepared bash environment. The following files are used:
* bashrch
* inputrc
* fixtures
The test environment needs to be put to fixed states when testing. For instance the bash prompt (PS1) is set to the current test directory, followed by an ampersand (@). The default settings for `bash` reside in `config/bashrc` and `config/inputrc`.
For each tool (completion, install, unit) a slightly different context is in effect.
=== What happens when tests are run?
==== completion
When the completions are tested, invoking DejaGnu will result in a call to `completion_start()` which in turn will start `bash --rcfile config/bashrc`.
.What happens when completion tests are run?
----
| runtest --tool completion
V
+----------+-----------+
| lib/completion.exp |
| lib/library.exp |
| config/default.exp |
+----------+-----------+
:
V
+----------+-----------+ +---------------+ +----------------+
| completion_start() +<---+ config/bashrc +<---| config/inputrc |
| (lib/completion.exp) | +---------------+ +----------------+
+----------+-----------+
| ,+----------------------------+
| ,--+-+ "Actual completion tests" |
V / +------------------------------+
+----------+-----------+ +-----------------------+
| completion/*.exp +<---| lib/completions/*.exp |
+----------+-----------+ +-----------------------+
| \ ,+--------------------------------+
| `----------------------+-+ "Completion invocation tests" |
V +----------------------------------+
+----------+-----------+
| completion_exit() |
| (lib/completion.exp) |
+----------------------+
----
Setting up bash once within `completion_start()` has the speed advantage that bash - and bash-completion - need only initialize once when testing multiple completions, e.g.:
----
runtest --tool completion alias.exp cd.exp
----
==== install
.What happens when install tests are run?
----
| runtest --tool install
V
+----+----+
| DejaGnu |
+----+----+
|
V
+------------+---------------+
| (file: config/default.exp) |
+------------+---------------+
|
V
+------------+------------+
| (file: lib/install.exp) |
+-------------------------+
----
==== unit
.What happens when unit tests are run?
----
| runtest --tool unit
V
+----+----+
| DejaGnu |
+----+----+
|
V
+----------+-----------+
| - |
| (file: lib/unit.exp) |
+----------------------+
----
=== bashrc
Contents of bashrc:
This is the bash configuration file (bashrc) used for testing:
[source,bash]
---------------------------------------------------------------------
include::bashrc[]
---------------------------------------------------------------------
=== inputrc
This is the readline configuration file (inputrc) used for testing:
[source,bash]
---------------------------------------------------------------------
include::inputrc[]
---------------------------------------------------------------------
Index
=====

1
test/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
dbg.log

6
test/completion/ssh.exp Normal file
View File

@ -0,0 +1,6 @@
source "lib/completions/ssh.exp"
# TODO: Dynamic loading of completions. After the tests have the first time and
# real completion is installed, the tests can be run a second time.
#
# source "lib/completions/ssh.exp"

23
test/config/bashrc Normal file
View File

@ -0,0 +1,23 @@
# -*- mode: shell-script; sh-basic-offset: 8; indent-tabs-mode: t -*-
# ex: ts=8 sw=8 noet filetype=sh
#
# bashrc file for DejaGnu testsuite
# Use emacs key bindings
set -o emacs
# Use bash strict mode
set -o posix
# Unset `command_not_found_handle' as defined on Debian/Ubuntu, because this
# troubles and slows down testing
unset -f command_not_found_handle
# Set prompt to ignore current root directory; display path starting
# from here. E.g. prompt: /fixtures/@
TESTDIR=$(pwd)
export PS1='$(wd=$(pwd); echo ${wd#$TESTDIR}/)@'
export PS2='> '
# Configure readline
export INPUTRC=$TESTDIR/config/inputrc
# Ensure enough columns so expect doesn't have to care about line breaks
stty columns 150
. lib/library.sh

11
test/config/default.exp Normal file
View File

@ -0,0 +1,11 @@
# Set default expect fallback routines
expect_after {
eof { fail "$test at eof" }
timeout { fail "$test at timeout" }
}; # expect_after()
# Call tool_start(), if available
if { [info procs "${tool}_start"] != "" } {
${tool}_start
}; # if

16
test/config/inputrc Normal file
View File

@ -0,0 +1,16 @@
# -*- mode: shell-script; sh-basic-offset: 8; indent-tabs-mode: t -*-
# ex: ts=8 sw=8 noet filetype=sh
#
# Readline init file for DejaGnu testsuite
# See: info readline
# Press TAB once (instead of twice) to auto-complete
set show-all-if-ambiguous on
# No bell. No ^G in output
set bell-style none
# Don't query user about viewing the number of possible completions
set completion-query-items -1
# Display completions sorted horizontally, not vertically
set print-completions-horizontally on
# Don't use pager when showing completions
set page-completions off

6
test/fixtures/_known_hosts/config vendored Normal file
View File

@ -0,0 +1,6 @@
UserKnownHostsFile fixtures/_known_hosts/known_hosts
# Unindented
Host gee
# Indented
Host hus # With comment

View File

@ -0,0 +1,4 @@
|1|abc
|1|def
doo
ike ssh-rsa qwerty1234/Qwerty+1234==

View File

@ -0,0 +1 @@
two

View File

@ -0,0 +1,9 @@
# Unindented
Host gee
UserKnownHostsFile "fixtures/_known_hosts/spaced known_hosts"
# Indented
Host hus # With comment
UserKnownHostsFile "fixtures/_known_hosts/known_hosts2"

View File

@ -0,0 +1,4 @@
|1|abc
|1|def
doo
ike ssh-rsa qwerty1234/Qwerty+1234==

1
test/fixtures/ssh/config vendored Normal file
View File

@ -0,0 +1 @@
UserKnownHostsFile fixtures/ssh/known_hosts

5
test/fixtures/ssh/known_hosts vendored Normal file
View File

@ -0,0 +1,5 @@
|1|abc
|1|def
doo
ike ssh-rsa qwerty1234/Qwerty+1234==
ls_known_host

27
test/lib/completion.exp Normal file
View File

@ -0,0 +1,27 @@
source lib/library.exp
proc completion_exit {} {
# Exit bash
send "\rexit\r"
}; # completion_exit()
proc completion_start {} {
global TESTDIR spawn_id
set test "completion_start"
set TESTDIR [pwd]
# Start bash and load bash-completion
exp_spawn bash --rcfile config/bashrc
assert_bash_exec {} "bash --rcfile config/bashrc"
assert_bash_exec {BASH_COMPLETION_DIR=$(cd ..; pwd)/contrib}
assert_bash_exec {BASH_COMPLETION=$(cd ..; pwd)/bash_completion}
assert_bash_exec {source $BASH_COMPLETION}
}; # completion_start()
proc completion_version {} {
puts "bash-completion-git"
}

View File

@ -0,0 +1,45 @@
proc setup {} {
save_env
}; # setup()
proc teardown {} {
assert_env_unmodified
}; # teardown()
setup
set test "Tab should complete both commands and hostnames"
# Try completion
set cmd "ssh -F fixtures/ssh/config ls"
send "$cmd\t"
set expected "^$cmd\r\n.*ls.*ls_known_host.*\r\n/@$cmd$"
expect {
-re $expected { pass "$test" }
-re /@ { unresolved "$test at prompt" }
default { unresolved "$test" }
}; # expect
sync_after_int
set test "-F without space shouldn't error"
# Try completion
set cmd "ssh -F"
send "$cmd\t "
set expected "^$cmd $"
expect {
-re "^${cmd}bash: option requires an argument -- F" { fail "$test" }
-re $expected { pass "$test" }
-re /@ { unresolved "$test at prompt" }
default { unresolved "$test" }
}; # expect
sync_after_int
teardown

264
test/lib/library.exp Normal file
View File

@ -0,0 +1,264 @@
# Execute a bash command and make sure the exit status is succesful.
# If not, output the error message.
# @param string $cmd Bash command line to execute. If emptry string (""), the
# exit status of the previously executed bash command will be
# checked; specify `title' to adorn the error message.
# @param string $title (optional) Command title. If empty, `cmd' is used.
proc assert_bash_exec {{aCmd ""} {title ""}} {
if {[string length $aCmd] != 0} {
send "$aCmd\r"
expect -ex "$aCmd\r\n"
}; # if
if {[string length $title] == 0} {set title $aCmd}
expect -ex "/@"
set out $expect_out(buffer); # Catch (non-expected) output
set cmd "echo $?"
send "$cmd\r"
expect {
-ex "$cmd\r\n0\r\n/@" {}
/@ {
if {[info exists multipass_name]} {
fail "ERROR executing bash command \"$title\""
}; # if
send_user "ERROR executing bash command \"$title\"\n$out"
}
}; # expect
}; # assert_bash_exec()
# Test `type ...' in bash
# Indicate "unsupported" if `type' exits with error status.
# @param string $command Command to locate
proc assert_bash_type {command} {
set test "$command should be available in bash"
set cmd "type $command &> /dev/null && echo -n 0 || echo -n 1"
send "$cmd\r"
expect "$cmd\r\n"
expect {
-ex 0 { set result true }
-ex 1 { set result false; unsupported "$test" }
}; # expect
expect "/@"
return $result
}; # assert_bash_type()
# Make sure the expected items are also returned by TAB-completing the
# specified command.
# Break items into chunks because `expect' seems to have a limited buffer size
# @param list $expected
# @param string $cmd Command given to generate items
# @param string $test (optional) Test titel. Default is "$cmd<TAB> should show completions"
# @param integer $size (optional) Chunk size. Default is 20.
# @result boolean True if successful, False if not
proc assert_complete {expected cmd {test ""} {prompt /@} {size 20}} {
if {$test == ""} {set test "$cmd should show completions"}
send "$cmd\t"
expect -ex "$cmd\r\n"
if {[match_items $expected $test]} {
expect {
-re "$prompt$cmd$" { pass "$test" }
-re $prompt { unresolved "$test at prompt" }
-re eof { unresolved "eof" }
}
} else {
fail "$test"
}; # if
}; # assert_complete()
# Make sure the bash environment hasn't changed between now and the last call
# to `save_env()'.
# @param string $sed Sed commands to preprocess diff output.
# E.g.: s/COMP_PATH=.*/COMP_PATH=PATH/
# @param string $file Filename to generate environment save file from. See
# `gen_env_filename()'.
# @param string $diff Expected diff output (after being processed by $sed)
# @see save_env()
proc assert_env_unmodified {{sed ""} {file ""} {diff ""}} {
set test "Environment should not be modified"
_save_env [gen_env_filename $file 2]
# Prepare sed script
# Escape special bash characters ("\)
regsub -all {([\"\\])} $sed {\\\1} sed
# Escape newlines
regsub -all {\n} [string trim $sed] "\r\n" sed
# Mark end of sed script, so that `expect' can match on that
append sed "# End of sed script"
# Prepare diff script
# If diff is filled, escape newlines and make sure it ends with a newline
if {[string length [string trim $diff]]} {
regsub -all {\n} [string trim $diff] "\r\n" diff
append diff "\r\n"
} else {
set diff ""
}; # if
# Execute diff
set cmd "diff_env \"[gen_env_filename $file 1]\" \"[gen_env_filename $file 2]\" \"$sed\""
send "$cmd\r"
expect "# End of sed script\"\r\n"
expect {
-re "^$diff[wd]@$" { pass "$test" }
-re [wd]@ {
fail "$test"
# Show diff to user
set diff $expect_out(buffer)
# Remove possible `\r\n[wd]@' from end of diff
if {[string last "\r\n[wd]@" $diff] == [string length $diff] - [string length "\r\n[wd]@"]} {
set diff [string range $diff 0 [expr [string last "\r\n[wd]@" $diff] - 1]]
}; # if
send_user $diff;
}
}; # expect
}; # assert_env_unmodified()
# Make sure the specified command executed from within Tcl/Expect.
# Fail the test with status UNSUPPORTED if Tcl fails with error "POSIX/ENOENT
# (No such file or directory)", or UNRESOLVED if other error occurs.
# NOTE: Further tests are assumed if executing the command is successful. The
# test isn't immediately declared to have PASSED if the command is
# executed successful.
# @param string $command
# @param string $stdout (optional) Reference to variable to hold stdout.
# @param string $test (optional) Test titel
# @see assert_bash_exec()
proc assert_exec {cmd {stdout ''} {test ''}} {
if {$test == ""} {set test "$cmd should execute successful"}
upvar $stdout results
set status [catch {eval exec $cmd} results]
if {$status == 0} {
set result true
} else {
set result false
# Command not found (POSIX/ENOENT = no such file or directory)?
if {[lindex $::errorCode 0] == "POSIX" && [lindex $::errorCode 1] == "ENOENT"} {
# Yes, command not found;
# Indicate test is unsupported
unsupported "$test"
} else {
unresolved "$test"
}; # if
}; # if
return $result
}; # assert_exec()
# Expect items.
# Break items into chunks because `expect' seems to have a limited buffer size
# @param list $items
# @param integer $size Chunk size
# @result boolean True if successful, False if not
proc match_items {items test {size 20}} {
set result false
for {set i 0} {$i < [llength $items]} {set i [expr {$i + $size}]} {
set expected ""
for {set j 0} {$j < $size && $i + $j < [llength $items]} {incr j} {
set item "[lindex $items [expr {$i + $j}]]"
# Escape special regexp characters
regsub -all {([\[\]\(\)\.\\\+])} $item {\\\1} item
set expected "${expected}$item\\s+"
}; # for
expect {
-re "$expected" { set result true }
default { set result false; break }
timeout { set result false; break }
}; # expect
}; # for
return $result
}; # match_items()
# Get real command.
# - arg: $1 Command
# - stdout: Filename of command in PATH with possible symbolic links resolved.
# - return: Command found, empty string if not found
proc realcommand {cmd} {
set result ""
if [string length [set path [auto_execok $cmd]]] {
if {[string length [auto_execok realpath]]} {
set result [exec realpath $path]
} elseif {[string length [auto_execok readlink]]} {
set result [exec readlink -f $path]
} else {
set result $path
}; # if
}; # if
return $result
}; # realcommand()
# Generate filename to save environment to.
# @param string $file File-basename to save environment to. If the file has a
# `.exp' suffix, it is removed. E.g.:
# - "file.exp" becomes "file.env1~"
# - "" becomes "env.env1~"
# - "filename" becomes "filename.env1~"
# The file will be stored in the $TESTDIR/tmp directory.
# @param integer $seq Sequence number. Must be either 1 or 2.
proc gen_env_filename {{file ""} {seq 1}} {
if {[string length $file] == 0} {
set file "env"
} else {
# Remove possible directories
set file [file tail $file]
# Remove possible '.exp' suffix from filename
if {[string last ".exp" $file] == [string length $file] - [string length ".exp"]} {
set file [string range $file 0 [expr [string last ".exp" $file] - 1]]
}; # if
}; # if
return "\$TESTDIR/tmp/$file.env$seq~"
}; # gen_env_filename()
# Save the environment for later comparison
# @param string $file Filename to generate environment save file from. See
# `gen_env_filename()'.
proc save_env {{file ""}} {
_save_env [gen_env_filename $file 1]
}; # save_env()
# Save the environment for later comparison
# @param string File to save the environment to. Default is "$TESTDIR/tmp/env1~".
# @see assert_env_unmodified()
proc _save_env {{file ""}} {
assert_bash_exec "{ set; declare -F; } > $file"
}; # save_env()
# Interrupt completion and sync with prompt.
# Send signals QUIT & INT.
proc sync_after_int {} {
set test "Sync after INT"
sleep .1
send \031\003; # QUIT/INT
expect /@
}; # sync_after_int()
proc sync_after_tab {} {
# NOTE: Wait in case completion returns nothing - because `units' isn't
# installed, so that "^$cdm.*$" doesn't match too early - before
# comp_install has finished
sleep .4
}; # sync_after_tab()
# Return current working directory with `TESTDIR' stripped
# @return string Working directory. E.g. /, or /fixtures/
proc wd {} {
global TESTDIR
# Remove `$TESTDIR' prefix from current working directory
set wd [string replace [pwd] 0 [expr [string length $TESTDIR] - 1]]/
}

26
test/lib/library.sh Normal file
View File

@ -0,0 +1,26 @@
# -*- mode: shell-script; sh-basic-offset: 8; indent-tabs-mode: t -*-
# ex: ts=8 sw=8 noet filetype=sh
#
# Bash library for bash-completion DejaGnu testsuite
# Diff environment files to detect if environment is unmodified
# @param $1 File 1
# @param $2 File 2
# @param $1 Additional sed script
diff_env() {
diff "$1" "$2" | sed -e "
/^[0-9]\+[acd]/d # Remove diff line indicators
/---/d # Remove diff block separators
/[<>] _=/d # Remove underscore variable
/[<>] PPID=/d # Remove PPID bash variable
$3"
} # diff_env()
# Output array elements, sorted and separated by newline
# @param $1 Name of array variable to process
echo_array() {
local IFS=$'\n'
eval echo \"\${$1[*]}\" | sort
}

27
test/lib/unit.exp Normal file
View File

@ -0,0 +1,27 @@
source lib/library.exp
proc unit_exit {} {
# Exit bash
send "\rexit\r"
}; # unit_exit()
proc unit_start {} {
global TESTDIR spawn_id
set test "unit_start"
set TESTDIR [pwd]
# Start bash and load bash-completion
exp_spawn bash --rcfile config/bashrc
assert_bash_exec {} "bash --rcfile config/bashrc"
assert_bash_exec {BASH_COMPLETION_DIR=$(cd ..; pwd)/contrib}
assert_bash_exec {BASH_COMPLETION=$(cd ..; pwd)/bash_completion}
assert_bash_exec {source $BASH_COMPLETION}
}; # unit_start()
proc unit_version {} {
puts "bash-completion-git"
}

1
test/log/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
*

7
test/runCompletion Executable file
View File

@ -0,0 +1,7 @@
#!/bin/bash
# NOTE: I tried setting up bash_completion_lib within ./lib files, but DejaGnu
# isn't initialized at that point (i.e. output of `expect' is shown on
# stdout - `open_logs' hasn't run yet?). And running code from a library
# file isn't probably a good idea either.
runtest --outdir log --tool completion $*

7
test/runInstall Executable file
View File

@ -0,0 +1,7 @@
#!/bin/bash
# NOTE: I tried setting up bash_completion_lib within ./lib files, but DejaGnu
# isn't initialized at that point (i.e. output of `expect' is shown on
# stdout - `open_logs' hasn't run yet?). And running code from a library
# file isn't probably a good idea either.
runtest --outdir log --tool install $*

7
test/runUnit Executable file
View File

@ -0,0 +1,7 @@
#!/bin/bash
# NOTE: I tried setting up bash_completion_lib within ./lib files, but DejaGnu
# isn't initialized at that point (i.e. output of `expect' is shown on
# stdout - `open_logs' hasn't run yet?). And running code from a library
# file isn't probably a good idea either.
runtest --outdir log --tool unit $*

1
test/tmp/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
*

View File

@ -0,0 +1,63 @@
proc setup {} {
save_env
}; # setup()
proc teardown {} {
assert_env_unmodified {/COMPREPLY=/d}
}; # teardown()
setup
set test "Hosts should be put in COMPREPLY"
# Build string list of hostnames, separated by regexp whitespace marker (\s+).
# Example string: host1\s+host2\s+host3
set hosts [exec bash -c "compgen -A hostname"]
# Hosts `gee' and `hus' are defined in ./fixtures/_known_hosts/config
# Hosts `doo' and `ike' are defined in ./fixtures/_known_hosts/known_hosts
lappend hosts doo gee hus ike
set hosts [lsort -ascii $hosts]
set hosts [join $hosts "\\s+"]
# Call _known_hosts
set cmd {_known_hosts -aF fixtures/_known_hosts/config; echo_array COMPREPLY}
send "$cmd\r"
expect -ex "$cmd\r\n"
expect {
-re "^$hosts\r\n/@$" { pass "$test" }
-re /@ { unresolved "$test at prompt" }
default { unresolved "$test" }
}; # expect
sync_after_int
set test "Config file containing space should work"
# Build string list of hostnames, separated by regexp whitespace marker (\s+).
# Example string: host1\s+host2\s+host3
set hosts [exec bash -c "compgen -A hostname"]
# Hosts `gee' and `hus' are defined in ./fixtures/_known_hosts/spaced conf
# Hosts `doo' and `ike' are defined in ./fixtures/_known_hosts/known_hosts
# Host `two' is defined in ./fixtures/_known_hosts/known_hosts2
lappend hosts gee hus
set hosts [lsort -ascii $hosts]
set hosts [join $hosts "\\s+"]
# Call _known_hosts
set cmd {_known_hosts -F 'fixtures/_known_hosts/spaced conf'; echo_array COMPREPLY}
send "$cmd\r"
expect -ex "$cmd\r\n"
expect {
-re "^$hosts\r\n/@$" { pass "$test" }
-re /@ { unresolved "$test at prompt" }
default { unresolved "$test" }
}; # expect
sync_after_int
teardown