summaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
authorGabriel F. T. Gomes <gabriel@inconstante.net.br>2020-08-03 18:43:13 -0300
committerGabriel F. T. Gomes <gabriel@inconstante.net.br>2020-08-03 18:43:13 -0300
commit95623d39d6029ba78ec96ad5ea08e9ac12629b91 (patch)
treeea0fe36eb5e6f40e0a1f765d44c4b0c0b2bfb089 /test
parent019f3cc463db63abc6460f97deb488deec43840b (diff)
downloadbash-completion-95623d39d6029ba78ec96ad5ea08e9ac12629b91.tar.gz
New upstream version 2.11upstream/2.11upstream
Diffstat (limited to 'test')
-rw-r--r--test/.gitignore5
-rw-r--r--test/Makefile.am15
-rw-r--r--test/completion/alias.exp1
-rw-r--r--test/completion/cd.exp1
-rw-r--r--test/completion/chown.exp1
-rw-r--r--test/completion/finger.exp1
-rw-r--r--test/completion/scp.exp1
-rw-r--r--test/completion/sftp.exp1
-rw-r--r--test/completion/slapt-get.exp1
-rw-r--r--test/completion/slapt-src.exp1
-rw-r--r--test/completion/ssh.exp1
-rw-r--r--test/completion/sudo.exp1
-rw-r--r--test/completion/umount.exp1
-rw-r--r--test/completion/upgradepkg.exp1
-rw-r--r--test/completion/xhost.exp1
-rw-r--r--test/config/bashrc17
-rw-r--r--test/config/default.exp21
-rw-r--r--test/config/inputrc18
-rwxr-xr-xtest/docker/docker-script.sh18
-rw-r--r--test/fixtures/_known_hosts_real/.ssh/config_asterisk_11
-rw-r--r--test/fixtures/_known_hosts_real/.ssh/config_asterisk_21
-rw-r--r--test/fixtures/_known_hosts_real/.ssh/config_question_mark1
-rw-r--r--test/fixtures/_known_hosts_real/config6
-rw-r--r--test/fixtures/_known_hosts_real/config_include2
-rw-r--r--test/fixtures/_known_hosts_real/config_tilde4
-rw-r--r--test/fixtures/_known_hosts_real/gee-filename-canary (renamed from test/fixtures/slackware/etc/slapt-get/slapt-getrc)0
-rw-r--r--test/fixtures/_known_hosts_real/localhost_config2
-rw-r--r--test/fixtures/_known_hosts_real/spaced conf7
-rw-r--r--test/fixtures/_longopt/various.txt5
-rw-r--r--test/fixtures/ant/.gitignore3
-rw-r--r--test/fixtures/dpkg/bash-completion-test-nonsubject.txt (renamed from test/fixtures/slackware/etc/slapt-get/slapt-srcrc)0
-rw-r--r--test/fixtures/lftp/.lftp/bookmarks2
-rw-r--r--test/fixtures/lilo/lilo.conf34
-rw-r--r--test/fixtures/nmap/nmap-h.txt114
-rw-r--r--test/fixtures/perl/Devel/BashCompletion.pm2
-rw-r--r--test/fixtures/perldoc/BashCompletionModule.pm4
-rw-r--r--test/fixtures/pytest/test_async.py17
-rw-r--r--test/fixtures/ssh-copy-id/.ssh/id_rsa0
-rw-r--r--test/lib/completion.exp24
-rw-r--r--test/lib/completions/alias.exp32
-rw-r--r--test/lib/completions/cd.exp31
-rw-r--r--test/lib/completions/chown.exp43
-rw-r--r--test/lib/completions/finger.exp41
-rw-r--r--test/lib/completions/scp.exp117
-rw-r--r--test/lib/completions/sftp.exp60
-rw-r--r--test/lib/completions/slapt-get.exp32
-rw-r--r--test/lib/completions/slapt-src.exp29
-rw-r--r--test/lib/completions/ssh.exp61
-rw-r--r--test/lib/completions/sudo.exp42
-rw-r--r--test/lib/completions/umount.exp95
-rw-r--r--test/lib/completions/upgradepkg.exp26
-rw-r--r--test/lib/completions/xhost.exp95
-rw-r--r--test/lib/library.exp970
-rw-r--r--test/lib/library.sh38
-rw-r--r--test/lib/unit.exp25
-rw-r--r--test/requirements-dev.txt4
-rw-r--r--test/requirements.txt2
-rwxr-xr-xtest/run67
-rwxr-xr-xtest/run-shellcheck4
-rwxr-xr-xtest/runCompletion8
-rwxr-xr-xtest/runInstall7
-rwxr-xr-xtest/runLint14
-rwxr-xr-xtest/runUnit8
-rw-r--r--test/setup.cfg9
-rw-r--r--test/t/Makefile.am9
-rw-r--r--test/t/conftest.py367
-rw-r--r--test/t/test_2to3.py2
-rw-r--r--test/t/test_7z.py5
-rw-r--r--test/t/test_alias.py4
-rw-r--r--test/t/test_ant.py13
-rw-r--r--test/t/test_apt_cache.py6
-rw-r--r--test/t/test_apt_get.py6
-rw-r--r--test/t/test_aptitude.py16
-rw-r--r--test/t/test_arpspoof.py7
-rw-r--r--test/t/test_bmake.py7
-rw-r--r--test/t/test_ccache.py6
-rw-r--r--test/t/test_cd.py6
-rw-r--r--test/t/test_chown.py34
-rw-r--r--test/t/test_complete.py4
-rw-r--r--test/t/test_cpan2dist.py4
-rw-r--r--test/t/test_cpio.py12
-rw-r--r--test/t/test_cppcheck.py6
-rw-r--r--test/t/test_crontab.py9
-rw-r--r--test/t/test_curl.py8
-rw-r--r--test/t/test_cvs.py2
-rw-r--r--test/t/test_dd.py2
-rw-r--r--test/t/test_dmypy.py6
-rw-r--r--test/t/test_dnssec_keygen.py2
-rw-r--r--test/t/test_dpkg_deb.py4
-rw-r--r--test/t/test_dpkg_query.py18
-rw-r--r--test/t/test_feh.py4
-rw-r--r--test/t/test_find.py13
-rw-r--r--test/t/test_finger.py24
-rw-r--r--test/t/test_gcc.py11
-rw-r--r--test/t/test_ip.py4
-rw-r--r--test/t/test_ipcalc.py23
-rw-r--r--test/t/test_irb.py2
-rw-r--r--test/t/test_iscsiadm.py4
-rw-r--r--test/t/test_isort.py2
-rw-r--r--test/t/test_jsonschema.py4
-rw-r--r--test/t/test_kcov.py2
-rw-r--r--test/t/test_ldd.py4
-rw-r--r--test/t/test_less.py4
-rw-r--r--test/t/test_lftp.py14
-rw-r--r--test/t/test_lilo.py9
-rw-r--r--test/t/test_ls.py2
-rw-r--r--test/t/test_lspci.py4
-rw-r--r--test/t/test_make.py19
-rw-r--r--test/t/test_man.py26
-rw-r--r--test/t/test_mkdir.py3
-rw-r--r--test/t/test_modprobe.py2
-rw-r--r--test/t/test_mount.py2
-rw-r--r--test/t/test_mr.py13
-rw-r--r--test/t/test_mypy.py2
-rw-r--r--test/t/test_nmap.py44
-rw-r--r--test/t/test_openssl.py5
-rw-r--r--test/t/test_perl.py2
-rw-r--r--test/t/test_pgrep.py22
-rw-r--r--test/t/test_postfix.py16
-rw-r--r--test/t/test_printenv.py19
-rw-r--r--test/t/test_protoc.py9
-rw-r--r--test/t/test_pydocstyle.py4
-rw-r--r--test/t/test_pylint.py2
-rw-r--r--test/t/test_pytest.py39
-rw-r--r--test/t/test_python.py4
-rw-r--r--test/t/test_python3.py4
-rw-r--r--test/t/test_ri.py2
-rw-r--r--test/t/test_sbcl.py3
-rw-r--r--test/t/test_sbcl_mt.py3
-rw-r--r--test/t/test_scp.py79
-rw-r--r--test/t/test_screen.py8
-rw-r--r--test/t/test_secret_tool.py12
-rw-r--r--test/t/test_sftp.py37
-rw-r--r--test/t/test_slapt_get.py28
-rw-r--r--test/t/test_slapt_src.py31
-rw-r--r--test/t/test_ssh.py28
-rw-r--r--test/t/test_ssh_keygen.py51
-rw-r--r--test/t/test_sudo.py36
-rw-r--r--test/t/test_tar.py20
-rw-r--r--test/t/test_totem.py7
-rw-r--r--test/t/test_tshark.py9
-rw-r--r--test/t/test_tsig_keygen.py12
-rw-r--r--test/t/test_umount.py78
-rw-r--r--test/t/test_upgradepkg.py17
-rw-r--r--test/t/test_userdel.py4
-rw-r--r--test/t/test_valgrind.py4
-rw-r--r--test/t/test_wol.py7
-rw-r--r--test/t/test_write.py4
-rw-r--r--test/t/test_xfreerdp.py32
-rw-r--r--test/t/test_xgamma.py2
-rw-r--r--test/t/test_xhost.py22
-rw-r--r--test/t/unit/Makefile.am5
-rw-r--r--test/t/unit/test_unit_count_args.py4
-rw-r--r--test/t/unit/test_unit_expand.py20
-rw-r--r--test/t/unit/test_unit_expand_tilde_by_ref.py32
-rw-r--r--test/t/unit/test_unit_filedir.py138
-rw-r--r--test/t/unit/test_unit_get_comp_words_by_ref.py101
-rw-r--r--test/t/unit/test_unit_get_cword.py25
-rw-r--r--test/t/unit/test_unit_init_completion.py16
-rw-r--r--test/t/unit/test_unit_known_hosts_real.py158
-rw-r--r--test/t/unit/test_unit_longopt.py18
-rw-r--r--test/t/unit/test_unit_quote.py2
-rw-r--r--test/t/unit/test_unit_quote_readline.py15
-rw-r--r--test/t/unit/test_unit_variables.py10
-rw-r--r--test/t/unit/test_unit_xinetd_services.py22
-rw-r--r--test/test-cmd-list.txt687
-rw-r--r--test/unit/__expand_tilde_by_ref.exp65
-rw-r--r--test/unit/_expand.exp33
-rw-r--r--test/unit/_filedir.exp124
-rw-r--r--test/unit/_get_comp_words_by_ref.exp91
-rw-r--r--test/unit/_get_cword.exp37
-rw-r--r--test/unit/_known_hosts_real.exp171
-rwxr-xr-xtest/update-test-cmd-list13
173 files changed, 2620 insertions, 2831 deletions
diff --git a/test/.gitignore b/test/.gitignore
index aa9a8096..c428b949 100644
--- a/test/.gitignore
+++ b/test/.gitignore
@@ -1,7 +1,2 @@
-log/
tmp/
-dbg.log
-xtrace.log
-site.exp
-site.bak
pytestdebug.log
diff --git a/test/Makefile.am b/test/Makefile.am
index 003ec132..591c8f7c 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -1,21 +1,14 @@
-AUTOMAKE_OPTIONS = dejagnu
-DEJATOOL = completion install unit
-AM_RUNTESTFLAGS = --outdir log --ignore $(PACKAGE).log
-
SUBDIRS = t
-EXTRA_DIST = completion \
- config \
+EXTRA_DIST = config \
fixtures \
- lib \
- setup.cfg \
- unit
+ setup.cfg
all:
- $(MKDIR_P) log tmp
+ $(MKDIR_P) tmp
CLEANFILES = \
fixtures/make/extra_makefile
clean-local:
- $(RM) -rf log tmp
+ $(RM) -rf tmp
diff --git a/test/completion/alias.exp b/test/completion/alias.exp
deleted file mode 100644
index ee7cf4bc..00000000
--- a/test/completion/alias.exp
+++ /dev/null
@@ -1 +0,0 @@
-assert_source_completions alias
diff --git a/test/completion/cd.exp b/test/completion/cd.exp
deleted file mode 100644
index 94c3c598..00000000
--- a/test/completion/cd.exp
+++ /dev/null
@@ -1 +0,0 @@
-assert_source_completions cd
diff --git a/test/completion/chown.exp b/test/completion/chown.exp
deleted file mode 100644
index 53d497c2..00000000
--- a/test/completion/chown.exp
+++ /dev/null
@@ -1 +0,0 @@
-assert_source_completions chown
diff --git a/test/completion/finger.exp b/test/completion/finger.exp
deleted file mode 100644
index 7c7b8a26..00000000
--- a/test/completion/finger.exp
+++ /dev/null
@@ -1 +0,0 @@
-assert_source_completions finger
diff --git a/test/completion/scp.exp b/test/completion/scp.exp
deleted file mode 100644
index e025a9dd..00000000
--- a/test/completion/scp.exp
+++ /dev/null
@@ -1 +0,0 @@
-assert_source_completions scp
diff --git a/test/completion/sftp.exp b/test/completion/sftp.exp
deleted file mode 100644
index 448cd218..00000000
--- a/test/completion/sftp.exp
+++ /dev/null
@@ -1 +0,0 @@
-assert_source_completions sftp
diff --git a/test/completion/slapt-get.exp b/test/completion/slapt-get.exp
deleted file mode 100644
index 6c37d523..00000000
--- a/test/completion/slapt-get.exp
+++ /dev/null
@@ -1 +0,0 @@
-assert_source_completions slapt-get
diff --git a/test/completion/slapt-src.exp b/test/completion/slapt-src.exp
deleted file mode 100644
index 90abfd5f..00000000
--- a/test/completion/slapt-src.exp
+++ /dev/null
@@ -1 +0,0 @@
-assert_source_completions slapt-src
diff --git a/test/completion/ssh.exp b/test/completion/ssh.exp
deleted file mode 100644
index 0477cba5..00000000
--- a/test/completion/ssh.exp
+++ /dev/null
@@ -1 +0,0 @@
-assert_source_completions ssh
diff --git a/test/completion/sudo.exp b/test/completion/sudo.exp
deleted file mode 100644
index 2a8015ff..00000000
--- a/test/completion/sudo.exp
+++ /dev/null
@@ -1 +0,0 @@
-assert_source_completions sudo
diff --git a/test/completion/umount.exp b/test/completion/umount.exp
deleted file mode 100644
index 39c4d114..00000000
--- a/test/completion/umount.exp
+++ /dev/null
@@ -1 +0,0 @@
-assert_source_completions umount
diff --git a/test/completion/upgradepkg.exp b/test/completion/upgradepkg.exp
deleted file mode 100644
index 4b181a86..00000000
--- a/test/completion/upgradepkg.exp
+++ /dev/null
@@ -1 +0,0 @@
-assert_source_completions upgradepkg
diff --git a/test/completion/xhost.exp b/test/completion/xhost.exp
deleted file mode 100644
index 159782b2..00000000
--- a/test/completion/xhost.exp
+++ /dev/null
@@ -1 +0,0 @@
-assert_source_completions xhost
diff --git a/test/config/bashrc b/test/config/bashrc
index dad96335..141dddc5 100644
--- a/test/config/bashrc
+++ b/test/config/bashrc
@@ -1,7 +1,7 @@
# bashrc file for bash-completion test suite
# Note that we do some initialization that would be too late to do here in
-# library.exp's start_bash() and conftest.py.
+# conftest.py.
# Use emacs key bindings
set -o emacs
@@ -9,6 +9,9 @@ set -o emacs
# Use bash strict mode
set -o posix
+# Raise error on uninitialized variables
+set -o nounset
+
# Unset `command_not_found_handle' as defined on Debian/Ubuntu, because this
# troubles and slows down testing
unset -f command_not_found_handle
@@ -32,7 +35,10 @@ export BASH_COMPLETION_USER_FILE=/dev/null
# but simple xspec completions are only installed if a separate one is not
# found in any completion dirs. Therefore we also point the "system" dirs to
# locations that should not yield valid completions and helpers paths either.
-export BASH_COMPLETION_USER_DIR=$(cd "$SRCDIR/.."; pwd)
+export BASH_COMPLETION_USER_DIR=$(
+ cd "$SRCDIR/.." || exit 1
+ pwd
+)
# /var/empty isn't necessarily actually always empty :P
export BASH_COMPLETION_COMPAT_DIR=/var/empty/bash_completion.d
export XDG_DATA_DIRS=/var/empty
@@ -44,8 +50,11 @@ unset -v \
COMP_KNOWN_HOSTS_WITH_HOSTFILE \
COMP_TAR_INTERNAL_PATHS
-# Load bash testsuite helper functions
-. $SRCDIR/lib/library.sh
+# @param $1 Char to add to $COMP_WORDBREAKS
+add_comp_wordbreak_char()
+{
+ [[ "${COMP_WORDBREAKS//[^$1]/}" ]] || COMP_WORDBREAKS+=$1
+}
# Local variables:
# mode: shell-script
diff --git a/test/config/default.exp b/test/config/default.exp
deleted file mode 100644
index 246499b4..00000000
--- a/test/config/default.exp
+++ /dev/null
@@ -1,21 +0,0 @@
-# Set default expect fallback routines
-expect_after {
- eof {
- if {[info exists test]} {
- fail "$test at eof"
- } elseif {[info level] > 0} {
- fail "[info level 1] at eof"
- } else {
- fail "eof"
- }
- }
- timeout {
- if {[info exists test]} {
- fail "$test at timeout"
- } elseif {[info level] > 0} {
- fail "[info level 1] at timeout"
- } else {
- fail "timeout"
- }
- }
-}
diff --git a/test/config/inputrc b/test/config/inputrc
index 5992491a..da896f56 100644
--- a/test/config/inputrc
+++ b/test/config/inputrc
@@ -1,17 +1,21 @@
-# Readline init file for DejaGnu testsuite
+# Readline init file for bash-completion test suite
# See: info readline
- # Press TAB once (instead of twice) to auto-complete
+# Press TAB once (instead of twice) to auto-complete
set show-all-if-ambiguous on
- # No bell. No ^G in output
+
+# No bell. No ^G in output
set bell-style none
- # Don't query user about viewing the number of possible completions
+
+# 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
+
+# Don't use pager when showing completions
set page-completions off
+# Print each completion on its own line
+set completion-display-width 0
+
# Local variables:
# mode: shell-script
# End:
diff --git a/test/docker/docker-script.sh b/test/docker/docker-script.sh
index 681f2429..b3f351fa 100755
--- a/test/docker/docker-script.sh
+++ b/test/docker/docker-script.sh
@@ -1,20 +1,5 @@
#!/bin/sh -ex
-if [ $DIST = tools ]; then
- rc=0
- perlcritic helpers/perl; rc=$((rc+$?))
- perltidy -nst -nse helpers/perl; rc=$((rc+$?))
- if [ -e helpers/perl.ERR ]; then
- cat helpers/perl.ERR
- rc=$((rc+1))
- fi
- flake8 helpers/python test test/generate; rc=$((rc+$?))
- black --check -t py27 -t py33 -t py34 -t py35 -t py36 -t py37 -t py38 \
- helpers/python; rc=$((rc+$?))
- black --check test test/generate; rc=$((rc+$?))
- exit $rc
-fi
-
if [ "$BSD" ]; then
PATH=/usr/local/lib/bsd-bin:$PATH
export PATH
@@ -28,5 +13,4 @@ autoreconf -i
make -j
xvfb-run make distcheck \
- PYTESTFLAGS="--numprocesses=auto --dist=loadfile" \
- RUNTESTFLAGS="--all --verbose"
+ PYTESTFLAGS="--verbose --numprocesses=auto --dist=loadfile"
diff --git a/test/fixtures/_known_hosts_real/.ssh/config_asterisk_1 b/test/fixtures/_known_hosts_real/.ssh/config_asterisk_1
new file mode 100644
index 00000000..fc09eb03
--- /dev/null
+++ b/test/fixtures/_known_hosts_real/.ssh/config_asterisk_1
@@ -0,0 +1 @@
+Host asterisk_1
diff --git a/test/fixtures/_known_hosts_real/.ssh/config_asterisk_2 b/test/fixtures/_known_hosts_real/.ssh/config_asterisk_2
new file mode 100644
index 00000000..42243ad2
--- /dev/null
+++ b/test/fixtures/_known_hosts_real/.ssh/config_asterisk_2
@@ -0,0 +1 @@
+Host asterisk_2
diff --git a/test/fixtures/_known_hosts_real/.ssh/config_question_mark b/test/fixtures/_known_hosts_real/.ssh/config_question_mark
new file mode 100644
index 00000000..08e1201f
--- /dev/null
+++ b/test/fixtures/_known_hosts_real/.ssh/config_question_mark
@@ -0,0 +1 @@
+Host question_mark
diff --git a/test/fixtures/_known_hosts_real/config b/test/fixtures/_known_hosts_real/config
index 1231dd79..fe3fb54a 100644
--- a/test/fixtures/_known_hosts_real/config
+++ b/test/fixtures/_known_hosts_real/config
@@ -1,7 +1,7 @@
- UserKnownHostsFile fixtures/_known_hosts_real/known_hosts
+ UserKnownHostsFile _known_hosts_real/known_hosts
# Unindented
-Host gee jar
+Host gee* jar?this-part-we-do-not-complete-at-least-yet
HostName %h.example.com
# Indented
- Host hus # With comment
+ Host hus%%eth0 !negated #not-a-comment
diff --git a/test/fixtures/_known_hosts_real/config_include b/test/fixtures/_known_hosts_real/config_include
index fe6f537e..a1ae7633 100644
--- a/test/fixtures/_known_hosts_real/config_include
+++ b/test/fixtures/_known_hosts_real/config_include
@@ -3,3 +3,5 @@
Include ~/config_full_path
# Include with relative path
Include config_relative_path
+# Include with wildcards, and more than one on same row
+Include config_asterisk* config_?uestion_mark
diff --git a/test/fixtures/_known_hosts_real/config_tilde b/test/fixtures/_known_hosts_real/config_tilde
index 0893515b..4181aaf5 100644
--- a/test/fixtures/_known_hosts_real/config_tilde
+++ b/test/fixtures/_known_hosts_real/config_tilde
@@ -1,4 +1,4 @@
# With quotes and tilde
-UserKnownHostsFile "~/fixtures/_known_hosts_real/known_hosts2"
+UserKnownHostsFile "~/_known_hosts_real/known_hosts2"
# Without quotes, with tilde, and another on the same line
-UserKnownHostsFile ~/fixtures/_known_hosts_real/known_hosts3 fixtures/_known_hosts_real/known_hosts4
+UserKnownHostsFile ~/_known_hosts_real/known_hosts3 _known_hosts_real/known_hosts4
diff --git a/test/fixtures/slackware/etc/slapt-get/slapt-getrc b/test/fixtures/_known_hosts_real/gee-filename-canary
index e69de29b..e69de29b 100644
--- a/test/fixtures/slackware/etc/slapt-get/slapt-getrc
+++ b/test/fixtures/_known_hosts_real/gee-filename-canary
diff --git a/test/fixtures/_known_hosts_real/localhost_config b/test/fixtures/_known_hosts_real/localhost_config
index 1e751338..30b6623b 100644
--- a/test/fixtures/_known_hosts_real/localhost_config
+++ b/test/fixtures/_known_hosts_real/localhost_config
@@ -1 +1 @@
-UserKnownHostsFile fixtures/_known_hosts_real/localhost_hosts
+UserKnownHostsFile _known_hosts_real/localhost_hosts
diff --git a/test/fixtures/_known_hosts_real/spaced conf b/test/fixtures/_known_hosts_real/spaced conf
index f484f0e3..566b92c2 100644
--- a/test/fixtures/_known_hosts_real/spaced conf
+++ b/test/fixtures/_known_hosts_real/spaced conf
@@ -1,9 +1,8 @@
# Unindented
Host gee
- UserKnownHostsFile "fixtures/_known_hosts_real/spaced known_hosts"
+ UserKnownHostsFile "_known_hosts_real/spaced known_hosts"
# Indented
- Host hus # With comment
- UserKnownHostsFile "fixtures/_known_hosts_real/known_hosts2"
-
+ Host hus #not-a-comment
+ UserKnownHostsFile "_known_hosts_real/known_hosts2"
diff --git a/test/fixtures/_longopt/various.txt b/test/fixtures/_longopt/various.txt
new file mode 100644
index 00000000..04c2c256
--- /dev/null
+++ b/test/fixtures/_longopt/various.txt
@@ -0,0 +1,5 @@
+---
+----nonono
+--foo_bar
+--foo-
+--foo=bar
diff --git a/test/fixtures/ant/.gitignore b/test/fixtures/ant/.gitignore
index 459f1019..3a08258b 100644
--- a/test/fixtures/ant/.gitignore
+++ b/test/fixtures/ant/.gitignore
@@ -1,2 +1 @@
-.ant-targets-build.xml
-.ant-targets-named-build.xml
+.ant-targets-*.xml
diff --git a/test/fixtures/slackware/etc/slapt-get/slapt-srcrc b/test/fixtures/dpkg/bash-completion-test-nonsubject.txt
index e69de29b..e69de29b 100644
--- a/test/fixtures/slackware/etc/slapt-get/slapt-srcrc
+++ b/test/fixtures/dpkg/bash-completion-test-nonsubject.txt
diff --git a/test/fixtures/lftp/.lftp/bookmarks b/test/fixtures/lftp/.lftp/bookmarks
index 31ec9303..074f8120 100644
--- a/test/fixtures/lftp/.lftp/bookmarks
+++ b/test/fixtures/lftp/.lftp/bookmarks
@@ -1 +1,3 @@
lftptest ftp://ftp.funet.fi/
+spacetest ftp://ftp.sunet.se/
+badbookmark
diff --git a/test/fixtures/lilo/lilo.conf b/test/fixtures/lilo/lilo.conf
new file mode 100644
index 00000000..c8901758
--- /dev/null
+++ b/test/fixtures/lilo/lilo.conf
@@ -0,0 +1,34 @@
+# global options:
+boot=/dev/hda
+prompt
+timeout=150
+lba32
+compact
+vga=normal
+root=/dev/hda1
+read-only
+menu-title=" John's Computer "
+#
+### bootable kernel images ###
+image=/boot/vmlinuz-2.6.29-1-i386
+ label=try
+ initrd=/boot/initrd.img-2.6.29-1-i386
+#image=/boot/vmlinuz-2.4.33-1-i386
+# label=2.4.33
+image=/tamu/vmlinuz
+ label=tamu
+ initrd=/tamu/initrd.img
+ root=/dev/hdb2
+ vga=ask
+#
+### other operating systems ###
+other=/dev/hda3
+ label=PCDOS
+ boot-as=0x80 # must be C:
+other=/dev/hdb1
+ label=WinXP
+ boot-as=0x80 # must be C:
+other=/dev/hdb5
+ label=oldDOS
+ loader=chain
+ table=/dev/hdb5
diff --git a/test/fixtures/nmap/nmap-h.txt b/test/fixtures/nmap/nmap-h.txt
new file mode 100644
index 00000000..0301d374
--- /dev/null
+++ b/test/fixtures/nmap/nmap-h.txt
@@ -0,0 +1,114 @@
+Nmap 7.60 ( https://nmap.org )
+Usage: nmap [Scan Type(s)] [Options] {target specification}
+TARGET SPECIFICATION:
+ Can pass hostnames, IP addresses, networks, etc.
+ Ex: scanme.nmap.org, microsoft.com/24, 192.168.0.1; 10.0.0-255.1-254
+ -iL <inputfilename>: Input from list of hosts/networks
+ -iR <num hosts>: Choose random targets
+ --exclude <host1[,host2][,host3],...>: Exclude hosts/networks
+ --excludefile <exclude_file>: Exclude list from file
+HOST DISCOVERY:
+ -sL: List Scan - simply list targets to scan
+ -sn: Ping Scan - disable port scan
+ -Pn: Treat all hosts as online -- skip host discovery
+ -PS/PA/PU/PY[portlist]: TCP SYN/ACK, UDP or SCTP discovery to given ports
+ -PE/PP/PM: ICMP echo, timestamp, and netmask request discovery probes
+ -PO[protocol list]: IP Protocol Ping
+ -n/-R: Never do DNS resolution/Always resolve [default: sometimes]
+ --dns-servers <serv1[,serv2],...>: Specify custom DNS servers
+ --system-dns: Use OS's DNS resolver
+ --traceroute: Trace hop path to each host
+SCAN TECHNIQUES:
+ -sS/sT/sA/sW/sM: TCP SYN/Connect()/ACK/Window/Maimon scans
+ -sU: UDP Scan
+ -sN/sF/sX: TCP Null, FIN, and Xmas scans
+ --scanflags <flags>: Customize TCP scan flags
+ -sI <zombie host[:probeport]>: Idle scan
+ -sY/sZ: SCTP INIT/COOKIE-ECHO scans
+ -sO: IP protocol scan
+ -b <FTP relay host>: FTP bounce scan
+PORT SPECIFICATION AND SCAN ORDER:
+ -p <port ranges>: Only scan specified ports
+ Ex: -p22; -p1-65535; -p U:53,111,137,T:21-25,80,139,8080,S:9
+ --exclude-ports <port ranges>: Exclude the specified ports from scanning
+ -F: Fast mode - Scan fewer ports than the default scan
+ -r: Scan ports consecutively - don't randomize
+ --top-ports <number>: Scan <number> most common ports
+ --port-ratio <ratio>: Scan ports more common than <ratio>
+SERVICE/VERSION DETECTION:
+ -sV: Probe open ports to determine service/version info
+ --version-intensity <level>: Set from 0 (light) to 9 (try all probes)
+ --version-light: Limit to most likely probes (intensity 2)
+ --version-all: Try every single probe (intensity 9)
+ --version-trace: Show detailed version scan activity (for debugging)
+SCRIPT SCAN:
+ -sC: equivalent to --script=default
+ --script=<Lua scripts>: <Lua scripts> is a comma separated list of
+ directories, script-files or script-categories
+ --script-args=<n1=v1,[n2=v2,...]>: provide arguments to scripts
+ --script-args-file=filename: provide NSE script args in a file
+ --script-trace: Show all data sent and received
+ --script-updatedb: Update the script database.
+ --script-help=<Lua scripts>: Show help about scripts.
+ <Lua scripts> is a comma-separated list of script-files or
+ script-categories.
+OS DETECTION:
+ -O: Enable OS detection
+ --osscan-limit: Limit OS detection to promising targets
+ --osscan-guess: Guess OS more aggressively
+TIMING AND PERFORMANCE:
+ Options which take <time> are in seconds, or append 'ms' (milliseconds),
+ 's' (seconds), 'm' (minutes), or 'h' (hours) to the value (e.g. 30m).
+ -T<0-5>: Set timing template (higher is faster)
+ --min-hostgroup/max-hostgroup <size>: Parallel host scan group sizes
+ --min-parallelism/max-parallelism <numprobes>: Probe parallelization
+ --min-rtt-timeout/max-rtt-timeout/initial-rtt-timeout <time>: Specifies
+ probe round trip time.
+ --max-retries <tries>: Caps number of port scan probe retransmissions.
+ --host-timeout <time>: Give up on target after this long
+ --scan-delay/--max-scan-delay <time>: Adjust delay between probes
+ --min-rate <number>: Send packets no slower than <number> per second
+ --max-rate <number>: Send packets no faster than <number> per second
+FIREWALL/IDS EVASION AND SPOOFING:
+ -f; --mtu <val>: fragment packets (optionally w/given MTU)
+ -D <decoy1,decoy2[,ME],...>: Cloak a scan with decoys
+ -S <IP_Address>: Spoof source address
+ -e <iface>: Use specified interface
+ -g/--source-port <portnum>: Use given port number
+ --proxies <url1,[url2],...>: Relay connections through HTTP/SOCKS4 proxies
+ --data <hex string>: Append a custom payload to sent packets
+ --data-string <string>: Append a custom ASCII string to sent packets
+ --data-length <num>: Append random data to sent packets
+ --ip-options <options>: Send packets with specified ip options
+ --ttl <val>: Set IP time-to-live field
+ --spoof-mac <mac address/prefix/vendor name>: Spoof your MAC address
+ --badsum: Send packets with a bogus TCP/UDP/SCTP checksum
+OUTPUT:
+ -oN/-oX/-oS/-oG <file>: Output scan in normal, XML, s|<rIpt kIddi3,
+ and Grepable format, respectively, to the given filename.
+ -oA <basename>: Output in the three major formats at once
+ -v: Increase verbosity level (use -vv or more for greater effect)
+ -d: Increase debugging level (use -dd or more for greater effect)
+ --reason: Display the reason a port is in a particular state
+ --open: Only show open (or possibly open) ports
+ --packet-trace: Show all packets sent and received
+ --iflist: Print host interfaces and routes (for debugging)
+ --append-output: Append to rather than clobber specified output files
+ --resume <filename>: Resume an aborted scan
+ --stylesheet <path/URL>: XSL stylesheet to transform XML output to HTML
+ --webxml: Reference stylesheet from Nmap.Org for more portable XML
+ --no-stylesheet: Prevent associating of XSL stylesheet w/XML output
+MISC:
+ -6: Enable IPv6 scanning
+ -A: Enable OS detection, version detection, script scanning, and traceroute
+ --datadir <dirname>: Specify custom Nmap data file location
+ --send-eth/--send-ip: Send using raw ethernet frames or IP packets
+ --privileged: Assume that the user is fully privileged
+ --unprivileged: Assume the user lacks raw socket privileges
+ -V: Print version number
+ -h: Print this help summary page.
+EXAMPLES:
+ nmap -v -A scanme.nmap.org
+ nmap -v -sn 192.168.0.0/16 10.0.0.0/8
+ nmap -v -iR 10000 -Pn -p 80
+SEE THE MAN PAGE (https://nmap.org/book/man.html) FOR MORE OPTIONS AND EXAMPLES
diff --git a/test/fixtures/perl/Devel/BashCompletion.pm b/test/fixtures/perl/Devel/BashCompletion.pm
index 0afc6045..f8e829d8 100644
--- a/test/fixtures/perl/Devel/BashCompletion.pm
+++ b/test/fixtures/perl/Devel/BashCompletion.pm
@@ -1 +1,3 @@
+use strict;
+use warnings;
1;
diff --git a/test/fixtures/perldoc/BashCompletionModule.pm b/test/fixtures/perldoc/BashCompletionModule.pm
index e69de29b..b9208f34 100644
--- a/test/fixtures/perldoc/BashCompletionModule.pm
+++ b/test/fixtures/perldoc/BashCompletionModule.pm
@@ -0,0 +1,4 @@
+package BashCompletionModule;
+use strict;
+use warnings;
+1;
diff --git a/test/fixtures/pytest/test_async.py b/test/fixtures/pytest/test_async.py
new file mode 100644
index 00000000..48f91e08
--- /dev/null
+++ b/test/fixtures/pytest/test_async.py
@@ -0,0 +1,17 @@
+"""Async function pytest completion fixture."""
+
+
+async def test_positive():
+ pass
+
+
+async def non_test_negative():
+ pass
+
+
+class Testing:
+ async def test_positive(self):
+ pass
+
+ async def non_test_negative(self):
+ pass
diff --git a/test/fixtures/ssh-copy-id/.ssh/id_rsa b/test/fixtures/ssh-copy-id/.ssh/id_rsa
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/test/fixtures/ssh-copy-id/.ssh/id_rsa
diff --git a/test/lib/completion.exp b/test/lib/completion.exp
deleted file mode 100644
index 88e92d50..00000000
--- a/test/lib/completion.exp
+++ /dev/null
@@ -1,24 +0,0 @@
-source $::srcdir/lib/library.exp
-
-
-proc completion_exit {} {
- send "\rexit\r"
-}
-
-
-proc completion_init {test_file_name} {
- # Call completion_start() only once
- if {! [info exists ::BASH_VERSINFO]} {
- completion_start
- }
-}
-
-
-proc completion_start {} {
- start_interactive_test
-}
-
-
-proc completion_version {} {
- puts "$::TESTDIR, bash-$::BASH_VERSION"
-}
diff --git a/test/lib/completions/alias.exp b/test/lib/completions/alias.exp
deleted file mode 100644
index c41417f1..00000000
--- a/test/lib/completions/alias.exp
+++ /dev/null
@@ -1,32 +0,0 @@
-proc setup {} {
- assert_bash_exec "unalias -a"; # Remove all aliases
- assert_bash_exec "alias foo=bar"
- assert_bash_exec "alias bar='foo foo'"
- save_env
-}
-
-
-proc teardown {} {
- assert_bash_exec "unalias -a"; # Remove all aliases
- assert_env_unmodified
-}
-
-
-setup
-
-
-set test "Tab should complete alias at cursor position"
- # Try completion
-set cmd "alias foo"
-append cmd \002\002\002; # \002 = ^B = Move cursor left in bash emacs mode
-send "$cmd\t"
-expect {
- -re "^alias foo\b\b\b\r\nbar +foo *\r\n/@alias foo\b\b\b$" { pass "$test" }
- -re "^alias foo\b\b\bfoo=foo\b\b\b$" { fail "$test: Wrong cursor position" }
- -re /@ { unresolved "$test" }
- default { unresolved "$test" }
-}
-sync_after_int
-
-
-teardown
diff --git a/test/lib/completions/cd.exp b/test/lib/completions/cd.exp
deleted file mode 100644
index ded094c3..00000000
--- a/test/lib/completions/cd.exp
+++ /dev/null
@@ -1,31 +0,0 @@
-proc setup {} {
- save_env
-}
-
-
-proc teardown {} {
- assert_env_unmodified {/OLDPWD=/d}
-}
-
-
-setup
-
-
-set test "Tab should complete cd at cursor position"
- # Try completion
-set cmd "cd $::srcdir/fixtures/shared/default/foo"
-append cmd \002\002\002; # \002 = ^B = Move cursor left in bash emacs mode
-#append cmd \033\0133D; # Escape-[-D = Cursor left
-send "$cmd\t"
-expect {
- -re "cd $::srcdir/fixtures/shared/default/foo\b\b\b\r\n(\.svn/ +|)bar bar.d/ +foo.d/ *(\.svn/ *|)\r\n/@cd $::srcdir/fixtures/shared/default/foo\b\b\b$" { pass "$test" }
- -re "^cd $::srcdir/fixtures/shared/default/foo\b\b\bfoo.d/foo\b\b\b$" { fail "$test: Wrong cursor position" }
- -re /@ { unresolved "$test at prompt" }
- default { unresolved "$test" }
-}
-
-
-sync_after_int
-
-
-teardown
diff --git a/test/lib/completions/chown.exp b/test/lib/completions/chown.exp
deleted file mode 100644
index 792d52a9..00000000
--- a/test/lib/completions/chown.exp
+++ /dev/null
@@ -1,43 +0,0 @@
-proc setup {} {
- # fake root command to get all users/groups completed at least for now
- assert_bash_exec {root_command=sudo}
- save_env
-}
-
-proc teardown {} {
- assert_env_unmodified
-}
-
-
-setup
-
-
-# Find user/group suitable for testing.
-set failed_find_unique_completion 0
-foreach ug {user group} {
- # compgen -A is used because it's a bash builtin and available everywhere.
- # The || true part prevents exec from throwing an exception if nothing is
- # found (very very unlikely).
- set list [split [exec bash -c "compgen -A $ug || true"] "\n"]
- if {![find_unique_completion_pair $list part$ug full$ug]} {
- untested "Not running complex chown tests; no suitable test $ug found."
- set failed_find_unique_completion 1
- }
-}
-
-# These tests require an unique completion.
-if {!$failed_find_unique_completion} {
-
- foreach prefix {
- "funky\\ user:" "funky.user:" "funky\\.user:" "fu\\ nky.user:"
- "f\\ o\\ o\\.\\bar:" "foo\\_b\\ a\\.r\\ :"
- } {
- set test "Check preserve special chars in $prefix$partgroup<TAB>"
- #assert_complete_into "chown $prefix$partgroup" "chown $prefix$fullgroup " $test
- assert_complete $prefix$fullgroup "chown $prefix$partgroup" $test
- sync_after_int
- }
-}
-
-
-teardown
diff --git a/test/lib/completions/finger.exp b/test/lib/completions/finger.exp
deleted file mode 100644
index c055f354..00000000
--- a/test/lib/completions/finger.exp
+++ /dev/null
@@ -1,41 +0,0 @@
-proc setup {} {
- save_env
-}
-
-
-proc teardown {} {
- assert_env_unmodified
-}
-
-
-setup
-
-
-sync_after_int
-
-
-set test "Tab should complete partial hostname"
-# Build string list of hostnames, starting with the character of the first
-# host, unless host starts with a COMP_WORDBREAKS character, e.g. a colon (:).
-# Hosts starting with a COMP_WORDBREAKS character are left out because these
-# are exceptional cases, requiring specific tests.
-set hosts {}
-set char ""
-foreach h [get_known_hosts] {
- set first [string range $h 0 0]
- if {$char == "" && [string first $first $::COMP_WORDBREAKS] == -1} {set char $first}
- if {$char != ""} {
- # Only append unique hostnames starting with $char
- if {$first == $char && [lsearch -exact $hosts "test@$h"] == -1} {
- # Prefix hosts with username 'test@'
- lappend hosts "test@$h"
- }
- }
-}
-assert_complete $hosts "finger test@$char" $test -expect-cmd-minus "test@$char"
-
-
-sync_after_int
-
-
-teardown
diff --git a/test/lib/completions/scp.exp b/test/lib/completions/scp.exp
deleted file mode 100644
index 1497a7fb..00000000
--- a/test/lib/completions/scp.exp
+++ /dev/null
@@ -1,117 +0,0 @@
-proc setup {} {
- save_env
- # NOTE: Changing dir to $SRCDIR is necessary because file locations in the
- # ssh config files (e.g. UserKnownHostsFile) are relative to $SRCDIR.
- assert_bash_exec {cd $SRCDIR/fixtures/scp}
-}
-
-
-proc teardown {} {
- assert_bash_exec {cd $TESTDIR}
- assert_env_unmodified {
- /BASH_LINENO=/d
- /BASH_SOURCE=/d
- /OLDPWD=/d
- }
-}
-
-
-setup
-
-
-set test "Tab should complete remote pwd"
-set host bash_completion
-
- # Retrieving home directory (host_pwd) from ssh-host `bash_completion'
- # yields error?
-if {
- [catch {
- exec -- ssh -o "Batchmode yes" -o "ConnectTimeout 1" $host pwd 2>>/dev/null
- } host_pwd]
-} {
- # Yes, retrieving pwd from ssh yields error; reset `host_pwd'
- # Indicate host pwd is unknown and test is unsupported
- # NOTE: To support this test, set the hostname "bash_completion"
- # in `$HOME/.ssh/config' or `/etc/ssh_config'
- set host_pwd ""
- unsupported $test
-}
-
-
- # Try completion
-set cmd "scp $host:"
-send "$cmd\t"
-sync_after_tab
-expect {
- -re "^$cmd$host_pwd.*$" { pass "$test" }
- -re /@ { unresolved "$test at prompt" }
-}
-
-
-sync_after_int
-
-
-set test "Tab should complete known-hosts"
-
- # Build string list of expected completions
- # Get hostnames and give them a colon (:) suffix
- # Hosts `gee' and `hut' are defined in ./fixtures/scp/config
- # Hosts `blah', `doo' and `ike' are defined in ./fixtures/scp/known_hosts
-set expected {}
-foreach host [get_hosts] {
- lappend expected "$host:"
-}
-lappend expected blah: doo: gee: hut: ike:
- # Append local filenames
-lappend expected config known_hosts "spaced\\ \\ conf"
-assert_complete $expected "scp -F config " $test
-
-
-sync_after_int
-
-
-set test "-F without space shouldn't error"
- # Try completion
-set cmd "scp -F"
-send "$cmd\t "
-expect {
- -re "^${cmd}bash: option requires an argument -- F" { fail "$test" }
- -re "^$cmd\r\n.*\r\n/@" { pass "$test" }
- -re /@ { unresolved "$test at prompt" }
- default { unresolved "$test" }
-}
-
-
-sync_after_int
-
-
-set test "Config file containing space should work"
- # Build string list of expected completions
- # Get hostnames and give them a colon (:) suffix
-set expected {}
-foreach host [get_hosts] {
- lappend expected "$host:"
-}
- # Hosts `gee', `hus' and `jar' are defined in "./fixtures/scp/spaced conf"
- # Hosts `blah', `doo' and `ike' are defined in ./fixtures/scp/known_hosts
-lappend expected blah: doo: gee: hus: ike: jar:
- # Append local filenames
-lappend expected config known_hosts "spaced\\ \\ conf"
-set cmd "scp -F 'spaced conf' "
-send "$cmd\t"
-expect -ex "$cmd\r\n"
-if {[match_items [lsort -unique $expected] -bash-sort]} {
- expect {
- -re /@ { pass "$test" }
- -re eof { unresolved "eof" }
- default { fail "$test" }
- }
-}
-sync_after_int
-assert_bash_exec {cd "$TESTDIR"}
-
-
-sync_after_int
-
-
-teardown
diff --git a/test/lib/completions/sftp.exp b/test/lib/completions/sftp.exp
deleted file mode 100644
index c5c0919f..00000000
--- a/test/lib/completions/sftp.exp
+++ /dev/null
@@ -1,60 +0,0 @@
-proc setup {} {
- save_env
- # NOTE: Changing dir to $SRCDIR is necessary because file locations in the
- # ssh config files (e.g. UserKnownHostsFile) are relative to $SRCDIR.
- assert_bash_exec {cd $SRCDIR/fixtures/sftp}
-}
-
-
-proc teardown {} {
- assert_bash_exec {cd $TESTDIR}
- assert_env_unmodified {
- /BASH_LINENO=/d
- /BASH_SOURCE=/d
- /OLDPWD=/d
- }
-}
-
-
-setup
-
-
- # Build string list of expected completions
-set expected [get_hosts]
- # Hosts `gee' and `hut' are defined in ./fixtures/sftp/config
- # Hosts `10.10.10.10', `doo' and `ike' are defined in ./fixtures/sftp/known_hosts
-lappend expected 10.10.10.10 doo gee hut ike
-assert_complete $expected "sftp -F config "
-
-
-sync_after_int
-
-
-set test "-F without space shouldn't error"
- # Try completion
-set cmd "sftp -F"
-send "$cmd\t "
-expect {
- -re "^${cmd}bash: option requires an argument -- F" { fail "$test" }
- -re "^$cmd\r\n.*\r\n/@" { pass "$test" }
- -re /@ { unresolved "$test at prompt" }
- default { unresolved "$test" }
-}
-
-
-sync_after_int
-
-
- # Build string list of expected completions
- # Get hostnames and give them a colon (:) suffix
-set expected [get_hosts]
- # Hosts `gee' and `jar' are defined in "./fixtures/sftp/spaced conf"
- # Hosts `10.10.10.10', `doo' and `ike' are defined in ./fixtures/sftp/known_hosts
-lappend expected 10.10.10.10 doo gee ike jar
-assert_complete $expected "sftp -F spaced\\ \\ conf "
-
-
-sync_after_int
-
-
-teardown
diff --git a/test/lib/completions/slapt-get.exp b/test/lib/completions/slapt-get.exp
deleted file mode 100644
index 4522610d..00000000
--- a/test/lib/completions/slapt-get.exp
+++ /dev/null
@@ -1,32 +0,0 @@
-proc setup {} {
- save_env
-}
-
-
-proc teardown {} {
- assert_env_unmodified
-}
-
-
-setup
-
-
-set test "--install should complete available packages"
-set config $::srcdir/fixtures/slackware/etc/slapt-get/slapt-getrc
-set workdir [file normalize $::srcdir/fixtures/slackware/var/slapt-get/]
-set pkg_data "$workdir/package_data"
-# write simple config
-set f [open $config w]
-puts $f "WORKINGDIR=$workdir"
-puts $f "SOURCE=file:///home/"
-close $f
-set packages [split [exec bash -c "sed -n \
- '/^PACKAGE NAME:/{s/^PACKAGE NAME: \\{1,\\}\\(.*\\).t\[gbxl\]z/\\1/;p}' \
- $pkg_data"] "\n"]
-assert_complete $packages "slapt-get -c $config --install " $test
-
-
-sync_after_int
-
-
-teardown
diff --git a/test/lib/completions/slapt-src.exp b/test/lib/completions/slapt-src.exp
deleted file mode 100644
index b66385ef..00000000
--- a/test/lib/completions/slapt-src.exp
+++ /dev/null
@@ -1,29 +0,0 @@
-proc setup {} {
- save_env
-}
-
-
-proc teardown {} {
- assert_env_unmodified
-}
-
-
-setup
-
-
-set test "--install should complete available packages"
-set config $::srcdir/fixtures/slackware/etc/slapt-get/slapt-srcrc
-set workdir [file normalize $::srcdir/fixtures/slackware/usr/src/slapt-src/]
-set slb_data "$workdir/slackbuilds_data"
-set f [open $config w]; puts $f "BUILDDIR=$workdir"; close $f
-set slackbuilds [split [exec bash -c "sed -n \
- -e '/^SLACKBUILD NAME: /{s/^SLACKBUILD NAME: \\{1,\\}//;p}' \
- -e '/^SLACKBUILD VERSION: /{s/^SLACKBUILD VERSION: \\{1,\\}//;p}' \
- $slb_data | sed -e 'N;s/\\n/:/'"] "\n"]
-assert_complete $slackbuilds "slapt-src --config $config --install " $test
-
-
-sync_after_int
-
-
-teardown
diff --git a/test/lib/completions/ssh.exp b/test/lib/completions/ssh.exp
deleted file mode 100644
index 1702371c..00000000
--- a/test/lib/completions/ssh.exp
+++ /dev/null
@@ -1,61 +0,0 @@
-proc setup {} {
- save_env
- # NOTE: Changing dir to $SRCDIR is necessary because file locations in the
- # ssh config files (e.g. UserKnownHostsFile) are relative to $SRCDIR.
- assert_bash_exec {cd $SRCDIR/fixtures/ssh}
-}
-
-
-proc teardown {} {
- assert_bash_exec {cd $TESTDIR}
- assert_env_unmodified {
- /BASH_LINENO=/d
- /BASH_SOURCE=/d
- /OLDPWD=/d
- }
-}
-
-
-setup
-
-
-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 "^$cmd\r\n.*\r\n/@" { pass "$test" }
- -re /@ { unresolved "$test at prompt" }
- default { unresolved "$test" }
-}
-
-
-sync_after_int
-
-
-set test "First argument should complete partial hostname"
-# Build string list of hostnames, starting with the character of the first
-# host, unless host starts with a COMP_WORDBREAKS character, e.g. a colon (:).
-# Hosts starting with a COMP_WORDBREAKS character are left out because these
-# are exceptional cases, requiring specific tests.
-set hosts {}
-set char ""
-foreach h [get_known_hosts] {
- set first [string range $h 0 0]
- if {$char == "" && [string first $first $::COMP_WORDBREAKS] == -1} {set char $first}
- if {$char != ""} {
- # Only append unique hostnames starting with $char
- if {$first == $char && [lsearch -exact $hosts "$h"] == -1} {
- lappend hosts "$h"
- }
- }
-}
-assert_complete $hosts "ssh $char" $test -ltrim-colon-completions -expect-cmd-minus "$char"
-
-
-sync_after_int
-
-
-teardown
diff --git a/test/lib/completions/sudo.exp b/test/lib/completions/sudo.exp
deleted file mode 100644
index 73e485d6..00000000
--- a/test/lib/completions/sudo.exp
+++ /dev/null
@@ -1,42 +0,0 @@
-proc setup {} {
- save_env
-}
-
-
-proc teardown {} {
- assert_env_unmodified {/OLDPWD/d}
-}
-
-
-setup
-
-
-# Find user/group suitable for testing.
-set failed_find_unique_completion 0
-foreach ug {user group} {
- # compgen -A is used because it's a bash builtin and available everywhere.
- # The || true part prevents exec from throwing an exception if nothing is
- # found (very very unlikely).
- set list [split [exec bash -c "compgen -A $ug || true"] "\n"]
- if {![find_unique_completion_pair $list part$ug full$ug]} {
- untested "Not running complex chown tests; no suitable test $ug found."
- set failed_find_unique_completion 1
- }
-}
-
-# These tests require an unique completion.
-if {!$failed_find_unique_completion} {
-
- foreach prefix {
- "funky\\ user:" "funky.user:" "funky\\.user:" "fu\\ nky.user:"
- "f\\ o\\ o\\.\\bar:" "foo\\_b\\ a\\.r\\ :"
- } {
- set test "Check preserve special chars in $prefix$partgroup<TAB>"
- #assert_complete_into "chown $prefix$partgroup" "chown $prefix$fullgroup " $test
- assert_complete $prefix$fullgroup "sudo chown $prefix$partgroup" $test
- sync_after_int
- }
-}
-
-
-teardown
diff --git a/test/lib/completions/umount.exp b/test/lib/completions/umount.exp
deleted file mode 100644
index 03144355..00000000
--- a/test/lib/completions/umount.exp
+++ /dev/null
@@ -1,95 +0,0 @@
-# umount completion from fstab can't be tested directly because it
-# (correctly) uses absolute paths. So we create a custom completion which
-# reads from a file in our text fixture instead.
-proc setup_dummy_mnt {} {
- assert_bash_exec {unset COMPREPLY cur}
- assert_bash_exec {unset -f _mnt}
-
- assert_bash_exec { \
- _mnt() { \
- local cur=$(_get_cword); \
- _linux_fstab $(_get_pword) < "$SRCDIRABS/fixtures/mount/test-fstab"; \
- }; \
- complete -F _mnt mnt \
- }
-}
-
-
-proc teardown_dummy_mnt {} {
- assert_bash_exec {unset COMPREPLY cur}
- assert_bash_exec {unset -f _mnt}
- assert_bash_exec {complete -r mnt}
-}
-
-
-proc setup {} {
- save_env
- setup_dummy_mnt
-}
-
-
-proc teardown {} {
- teardown_dummy_mnt
- assert_env_unmodified {/OLDPWD/d}
-}
-
-
-setup
-
-
-set test "Testing internal __linux_fstab_unescape function for umount"
-# One round of slashes is for bash.
-assert_bash_exec {var=one\'two\\040three\\}
-assert_bash_exec {__linux_fstab_unescape var}
-set cmd {echo $var}
-send "$cmd\r"
-expect {
- -ex "$cmd\r\none'two three\\" { pass $test }
-# default { fail $test }
-}
-sync_after_int
-assert_bash_exec {unset var}
-
-
-sync_after_int
-
-
-# Begin testing through mnt (see setup_dummy_mnt).
-assert_complete {/mnt/nice-test-path} {mnt /mnt/nice-test-p}
-sync_after_int
-
-assert_complete {/mnt/nice\ test-path} {mnt /mnt/nice\ test-p}
-sync_after_int
-
-assert_complete {/mnt/nice\$test-path} {mnt /mnt/nice\$test-p}
-sync_after_int
-
-assert_complete {/mnt/nice\ test\\path} {mnt /mnt/nice\ test\\p}
-sync_after_int
-
-assert_complete {{/mnt/nice\ test\\path} {/mnt/nice\ test-path}} \
- {mnt /mnt/nice\ } "" -expect-cmd-minus {/mnt/nice\ }
-sync_after_int
-
-assert_complete {/mnt/nice\$test-path} {mnt /mnt/nice\$}
-sync_after_int
-
-assert_complete {/mnt/nice\'test-path} {mnt /mnt/nice\'}
-sync_after_int
-
-assert_complete {/mnt/other\'test\ path} {mnt /mnt/other}
-sync_after_int
-
-assert_complete {Ubuntu\ Karmic} {mnt -L Ubu}
-sync_after_int
-
-assert_complete {Debian-it\'s\ awesome} {mnt -L Deb}
-sync_after_int
-
-# This does not work. Proper support for this requires smarter parsing of
-# $COMP_LINE and it's not worth doing just for umount.
-#assert_complete {$'/mnt/nice\ntest-path'} {mnt $'/mnt/nice\n}
-#sync_after_int
-
-
-teardown
diff --git a/test/lib/completions/upgradepkg.exp b/test/lib/completions/upgradepkg.exp
deleted file mode 100644
index ffb4ba28..00000000
--- a/test/lib/completions/upgradepkg.exp
+++ /dev/null
@@ -1,26 +0,0 @@
-proc setup {} {
- save_env
-}
-
-
-proc teardown {} {
- assert_env_unmodified {/OLDPWD=/d}
-}
-
-
-setup
-
-
-set test "should complete *.t\[gbxl\]z files and dirs after % sign"
-set oldpkg "xx-2.0-i486-2"
-set dir $::srcdir/fixtures/slackware/home
-set files [split [exec bash -c "cd $dir && find . -mindepth 1 -maxdepth 1 \
- \\( -type d -printf '$oldpkg%%%P/\\n' \\) -o \
- \\( -type f -name '*.t\[bglx\]z' -printf '$oldpkg%%%P\\n' \\)"] "\n"]
-assert_complete_dir $files "upgradepkg $oldpkg%" $dir $test
-
-
-sync_after_int
-
-
-teardown
diff --git a/test/lib/completions/xhost.exp b/test/lib/completions/xhost.exp
deleted file mode 100644
index 02aa4cb2..00000000
--- a/test/lib/completions/xhost.exp
+++ /dev/null
@@ -1,95 +0,0 @@
-proc setup {} {
- assert_bash_exec {HOME=$TESTDIR}
- save_env
-}
-
-
-proc teardown {} {
- assert_env_unmodified
-}
-
-
-setup
-
-
-set test "Tab should complete hostnames"
-assert_complete [get_hosts] "xhost " $test
-
-
-sync_after_int
-
-
-set test "Tab should complete partial hostname"
-# Build string list of hostnames, starting with the character of the first hostname
-set hosts {}
-set char ""
-foreach h [get_hosts] {
- if {$char == ""} {set char [string range $h 0 0]}
- # Only append hostname if starting with $char
- if {[string range $h 0 0] == "$char"} {
- lappend hosts $h
- }
-}
-assert_complete $hosts "xhost $char" $test -expect-cmd-minus "$char"
-
-
-sync_after_int
-
-
-set test "Tab should complete hostnames prefixed with +"
-# Build string list of hostnames, prefixed with plus (+)
-set hosts {}
-foreach h [get_hosts] {
- lappend hosts "+$h"
-}
-assert_complete $hosts "xhost \+" $test
-
-
-sync_after_int
-
-
-set test "Tab should complete partial hostname prefixed with +"
- # Build string list of hostnames, starting with character of first host.
-set hosts {}
-foreach h [get_hosts] {
- if {$char == ""} {set char [string range $h 0 0]}
- # Only append hostname if starting with $char
- if {[string range $h 0 0] == "$char"} {
- lappend hosts "+$h"
- }
-}
-assert_complete $hosts "xhost +$char" $test -expect-cmd-minus "\+$char"
-
-
-sync_after_int
-
-
-set test "Tab should complete hostnames prefixed with -"
- # Build string list of hostnames, prefix with minus (-)
-set hosts {}
-foreach h [get_hosts] {
- lappend hosts "-$h"
-}
-assert_complete $hosts "xhost -" $test
-
-
-sync_after_int
-
-
-set test "Tab should complete partial hostname prefixed with -"
- # Build list of hostnames, starting with character of first host
-set hosts {}
-foreach h [get_hosts] {
- if {$char == ""} {set char [string range $h 0 0]}
- # Only append hostname if starting with $char
- if {[string range $h 0 0] == "$char"} {
- lappend hosts "-$h"
- }
-}
-assert_complete $hosts "xhost -$char" $test -expect-cmd-minus "-$char"
-
-
-sync_after_int
-
-
-teardown
diff --git a/test/lib/library.exp b/test/lib/library.exp
deleted file mode 100644
index c90c927c..00000000
--- a/test/lib/library.exp
+++ /dev/null
@@ -1,970 +0,0 @@
-# Source `init.tcl' again to restore the `unknown' procedure
-# NOTE: DejaGnu has an old `unknown' procedure which unfortunately disables
-# tcl auto-loading.
-source [file join [info library] init.tcl]
-package require cmdline
-package require textutil::string
-
-
-
-# Execute a bash command and make sure the exit status is successful.
-# If not, output the error message.
-# @param string $cmd Bash command line to execute. If empty 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.
-# @param string $prompt (optional) Bash prompt. Default is "/@"
-# @param mixed $out (optional) Reference to (tcl) variable to hold output.
-# If variable equals -1 (default) the bash command is expected
-# to return no output. If variable equals 0, any output
-# from the bash command is disregarded.
-proc assert_bash_exec {{aCmd ""} {title ""} {prompt /@} {out -1}} {
- if {$out != 0 && $out != -1} {upvar $out results}
- if {[string length $aCmd] != 0} {
- send "$aCmd\r"
- expect -ex "$aCmd\r\n"
- }
- if {[string length $title] == 0} {set title $aCmd}
- expect -ex $prompt
- set results $expect_out(buffer); # Catch output
- # Remove $prompt suffix from output
- set results [
- string range $results 0 [
- expr [string length $results] - [string length $prompt] - 1
- ]
- ]
- if {$out == -1 && [string length $results] > 0} {
- fail "ERROR Unexpected output from bash command \"$title\""
- }
-
- set cmd "echo $?"
- send "$cmd\r"
- expect {
- -ex "$cmd\r\n0\r\n$prompt" {}
- $prompt {fail "ERROR executing bash command \"$title\""}
- }
-}
-
-
-# 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 "/@"
- return $result
-}
-
-
-# Make sure the expected list matches the real list, as returned by executing
-# the specified bash command.
-# Specify `-sort' if the real list is sorted.
-# @param list $expected Expected list items
-# @param string $cmd Bash command to execute in order to generate real list
-# items
-# @param string $test Test title. Becomes "$cmd should show expected output"
-# if empty string.
-# @param list $args Options:
-# -sort Compare list sorted. Default is unsorted
-# -prompt Bash prompt. Default is `/@'
-# -chunk-size N Compare list N items at a time. Default
-# is 20.
-proc assert_bash_list {expected cmd test {args {}}} {
- array set arg [::cmdline::getoptions args {
- {sort "compare list sorted"}
- {prompt.arg /@ "bash prompt"}
- {chunk-size.arg 20 "compare N list items at a time"}
- }]
- set prompt $arg(prompt)
- if {$test == ""} {set test "$cmd should show expected output"}
- if {[llength $expected] == 0} {
- assert_no_output $cmd $test $prompt
- } else {
- send "$cmd\r"
- expect -ex "$cmd\r\n"
- if {$arg(sort)} {set bash_sort "-bash-sort"} {set bash_sort ""}
- if {[
- eval match_items \$expected $bash_sort -chunk-size \
- \$arg(chunk-size) -end-newline -end-prompt \
- -prompt \$prompt
- ]} {
- pass "$test"
- } else {
- fail "$test"
- }
- }
-}
-
-
-# Make sure the expected list matches the real list, as returned by executing
-# the specified bash command within the specified directory.
-# Specify `-sort' if the real list is sorted.
-# @param list $expected Expected list items
-# @param string $cmd Bash command to generate real list items
-# @param string $dir Directory to execute $cmd within
-# @param string $test Test title. Becomes "$cmd should show expected output"
-# if empty string.
-# @param list $args Options:
-# -sort Compare list sorted. Default is unsorted
-# -prompt Bash prompt. Default is `/@'
-# -chunk-size N Compare list N items at a time. Default
-# is 20.
-proc assert_bash_list_dir {expected cmd dir test {args {}}} {
- array set arg [::cmdline::getoptions args {
- {sort "compare list sorted"}
- {prompt.arg "/@" "bash prompt"}
- {chunk-size.arg 20 "compare N list items at a time"}
- }]
- set prompt $arg(prompt)
- if {$arg(sort)} {set arg_sort "-sort"} else {set arg_sort ""}
- assert_bash_exec "cd $dir" "" $prompt
- assert_bash_list $expected $cmd $test $arg_sort \
- -chunk-size $arg(chunk-size) -prompt $prompt
- sync_after_int $prompt
- assert_bash_exec {cd "$TESTDIR"}
-}
-
-
-# Make sure the expected items are returned by TAB-completing the specified
-# command. If the number of expected items is one, expected is:
-#
-# $cmd<TAB>$expected[<SPACE>]
-#
-# SPACE is not expected if -nospace is specified.
-#
-# If the number of expected items is greater than one, expected is:
-#
-# $cmd<TAB>\n
-# $expected\n
-# $prompt + ($cmd - AUTO) + longest-common-prefix-of-$expected
-#
-# AUTO is calculated like this: If $cmd ends with non-whitespace, and
-# the last argument of $cmd equals the longest-common-prefix of
-# $expected, $cmd minus this argument will be expected.
-#
-# If the algorithm above fails, you can manually specify the CWORD to be
-# subtracted from $cmd specifying `-expect-cmd-minus CWORD'. Known cases where
-# this is useful are when:
-# - the last whitespace is escaped, e.g. "finger foo\ " or "finger
-# 'foo "
-#
-# @param list $expected Expected completions.
-# @param string $cmd Command given to generate items
-# @param string $test Test title
-# @param list $args Options:
-# -prompt PROMPT Bash prompt. Default is `/@'
-# -chunk-size CHUNK-SIZE Compare list CHUNK-SIZE items at
-# a time. Default is 20.
-# -nospace Don't expect space character to be output after completion match.
-# Valid only if a single completion is expected.
-# -ltrim-colon-completions Left-trim completions with cword containing
-# colon (:)
-# -expect-cmd-minus DWORD Expect $cmd minus DWORD to be echoed.
-# Expected is:
-#
-# $cmd<TAB>\n
-# $expected\n
-# $prompt + ($cmd - DWORD) + longest-common-prefix-of-$expected
-#
-proc assert_complete {expected cmd {test ""} {args {}}} {
- set args_orig $args
- array set arg [::cmdline::getoptions args {
- {prompt.arg "/@" "bash prompt"}
- {chunk-size.arg 20 "compare N list items at a time"}
- {nospace "don't expect space after completion"}
- {ltrim-colon-completions "left-trim completions with cword containing :"}
- {expect-cmd-minus.arg "" "Expect cmd minus DWORD after prompt"}
- }]
- if {[llength $expected] == 0} {
- assert_no_complete $cmd $test
- } elseif {[llength $expected] == 1} {
- eval assert_complete_one \$expected \$cmd \$test $args_orig
- } else {
- eval assert_complete_many \$expected \$cmd \$test $args_orig
- }
-}
-
-
-# Make sure the expected multiple items are returned by TAB-completing the
-# specified command.
-# @see assert_complete()
-proc assert_complete_many {expected cmd {test ""} {args {}}} {
- array set arg [::cmdline::getoptions args {
- {prompt.arg "/@" "bash prompt"}
- {chunk-size.arg 20 "compare N list items at a time"}
- {nospace "don't expect space after completion"}
- {ltrim-colon-completions "left-trim completions with cword containing :"}
- {expect-cmd-minus.arg "" "Expect cmd minus CWORD after prompt"}
- }]
- if {$test == ""} {set test "$cmd should show completions"}
- set prompt $arg(prompt)
- set dword ""
- if {$arg(expect-cmd-minus) != ""} {set dword $arg(expect-cmd-minus)}
-
- send "$cmd\t"
- expect -ex "$cmd\r\n"
-
- # Make sure expected items are unique
- set expected [lsort -unique $expected]
-
- # Determine common prefix of completions
- set common [::textutil::string::longestCommonPrefixList $expected]
-
- if {$arg(ltrim-colon-completions)} {
- # If partial contains colon (:), remove partial from begin of items
- _ltrim_colon_completions $cmd expected dword
- }
- set cmd2 [_remove_cword_from_cmd $cmd $dword $common]
-
- set prompt "$prompt$cmd2$common"
- if {$arg(nospace)} {set endspace ""} else {set endspace "-end-space"}
- set endprompt "-end-prompt"
- if {[
- eval match_items \$expected -bash-sort -chunk-size \
- \$arg(chunk-size) $endprompt $endspace -prompt \$prompt
- ]} {
- pass "$test"
- } else {
- fail "$test"
- }
-}
-
-
-# Make sure the expected single item is returned by TAB-completing the
-# specified command.
-# @see assert_complete()
-proc assert_complete_one {expected cmd {test ""} {args {}}} {
- array set arg [::cmdline::getoptions args {
- {prompt.arg "/@" "bash prompt"}
- {chunk-size.arg 20 "compare N list items at a time"}
- {nospace "don't expect space after completion"}
- {ltrim-colon-completions "left-trim completions with cword containing :"}
- {expect-cmd-minus.arg "" "Expect cmd minus CWORD after prompt"}
- }]
- set prompt $arg(prompt)
-
- if {$test == ""} {set test "$cmd should show completion"}
- send "$cmd\t"
- expect -ex "$cmd"
- set trimmed false
- if {$arg(ltrim-colon-completions)} {
- # If partial contains colon (:), remove partial from begin of items
- set trimmed [_ltrim_colon_completions $cmd expected cword]
- }
- if {! $trimmed} {
- set cur ""; # Default to empty word to complete on
- set words [split_words_bash $cmd]
- if {[llength $words] > 1} {
- # Assume last word of `$cmd' is word to complete on.
- set index [expr [llength $words] - 1]
- set cur [lindex $words $index]
- }
- # Remove second word from beginning of $expected
- if {[string first $cur $expected] == 0} {
- set expected [list [string range $expected [string length $cur] end]]
- }
- }
-
- if {$arg(nospace)} {set endspace ""} else {set endspace "-end-space"}
- if {[
- eval match_items \$expected -bash-sort -chunk-size \
- \$arg(chunk-size) $endspace -prompt \$prompt
- ]} {
- pass "$test"
- } else {
- fail "$test"
- }
-}
-
-
-# @param string $cmd Command to remove current-word-to-complete from.
-# @param string $dword (optional) Manually specify current-word-to-complete,
-# i.e. word to remove from $cmd. If empty string (default),
-# `_remove_cword_from_cmd' autodetects if the last argument is the
-# current-word-to-complete by checking if $cmd doesn't end with whitespace.
-# Specifying `dword' is only necessary if this autodetection fails, e.g.
-# when the last whitespace is escaped or quoted, e.g. "finger foo\ " or
-# "finger 'foo "
-# @param string $common (optional) Common prefix of expected completions.
-# @return string Command with current-word-to-complete removed
-proc _remove_cword_from_cmd {cmd {dword ""} {common ""}} {
- set cmd2 $cmd
- # Is $dword specified?
- if {[string length $dword] > 0} {
- # Remove $dword from end of $cmd
- if {[string last $dword $cmd] == [string length $cmd] - [string length $dword]} {
- set cmd2 [string range $cmd 0 [expr [string last $dword $cmd] - 1]]
- }
- } else {
- # No, $dword not specified;
- # Check if last argument is really a word-to-complete, i.e.
- # doesn't end with whitespace.
- # NOTE: This check fails if trailing whitespace is escaped or quoted,
- # e.g. "finger foo\ " or "finger 'foo ". Specify parameter
- # $dword in those cases.
- # Is last char whitespace?
- if {! [string is space [string range $cmd end end]]} {
- # No, last char isn't whitespace;
- set cmds [split $cmd]
- # Does word-to-complete start with $common?
- if {[string first $common [lrange $cmds end end]] == 0} {
- # Remove word-to-complete from end of $cmd
- set cmd2 [lrange $cmds 0 end-1]
- append cmd2 " "
- }
- }
- }
- return $cmd2
-}
-
-
-# Escape regexp special characters
-proc _escape_regexp_chars {var} {
- upvar $var str
- regsub -all {([\^$+*?.|(){}[\]\\])} $str {\\\1} str
-}
-
-# Make sure any completions are returned
-proc assert_complete_any {cmd {test ""} {prompt /@}} {
- if {$test == ""} {set test "$cmd should show completions"}
- send "$cmd\t"
- expect -ex "$cmd"
- _escape_regexp_chars cmd
- expect {
- -timeout 1
- # Match completions, multiple words
- # NOTE: The `\S*' (zero or more non-whitespace characters) matches a
- # longest common prefix of the completions shown.
- # E.g. `fmt -' becomes `fmt --' (two dashes) when completing
- -re "^\r\n.*$prompt$cmd\\S*$" { pass "$test" }
- timeout {
- expect {
- # Match completion, single word. This word is shown on the
- # same line as the command.
- -re "^\\S* $" { pass "$test" }
- # Try matching multiple words again, with new timeout
- -re "^\r\n.*$prompt$cmd\\S*$" { pass "$test" }
- }
- }
- -re $prompt { unresolved "$test at prompt" }
- eof { unresolved "eof" }
- }
-}
-
-
-# Make sure the expected files are returned by TAB-completing the specified
-# command in the specified subdirectory. Be prepared to filter out OLDPWD
-# changes when calling assert_env_unmodified() after using this procedure.
-# @param list $expected
-# @param string $cmd Command given to generate items
-# @param string $dir Subdirectory to attempt completion in. The directory must be relative from the $TESTDIR and without a trailing slash. E.g. `fixtures/evince'
-# @param string $test Test title
-# @param list $args See: assert_complete()
-# @result boolean True if successful, False if not
-proc assert_complete_dir {expected cmd dir {test ""} {args {}}} {
- set prompt "/@"
- assert_bash_exec "cd $dir" "" $prompt
- eval assert_complete \$expected \$cmd \$test $args
- sync_after_int $prompt
- assert_bash_exec {cd "$TESTDIR"}
-}
-
-
-
-# If cword contains colon (:), left-trim completions with cword
-# @param string $cmd Command to complete
-# @param list $items Reference to list of completions to trim
-# @param string $dword Reference to variable to contain word to remove from
-# expected cmd.
-# See also: bash_completion._ltrim_colon_completions
-proc _ltrim_colon_completions {cmd items dword} {
- upvar 1 $items items_out
- upvar 1 $dword dword_out
-
- set cur ""; # Default to empty word to complete on
- set words [split_words_bash $cmd]
- if {[llength $words] > 1} {
- # Assume last word of `$cmd' is word to complete on.
- set index [expr [llength $words] - 1]
- set cur [lindex $words $index]
- }
- # If word-to-complete contains a colon,
- # and COMP_WORDBREAKS contains a colon
- if {
- [string first : $cur] > -1 && [string first ":" $::COMP_WORDBREAKS] > -1
- } {
- set dword_out $cur
- for {set i 0} {$i < [llength $items_out]} {incr i} {
- set item [lindex $items_out $i]
- if {[string first $cur $item] == 0} {
- # Strip colon-prefix
- lset items_out $i [string range $item [string length $cur] end]
- }
- }
- return true
- }
- return false
-}
-
-
-# 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.
-# Example calls:
-#
-# # Replace `COMP_PATH=.*' with `COMP_PATH=PATH'
-# assert_env_unmodified {s/COMP_PATH=.*/COMP_PATH=PATH/}
-#
-# # Remove lines containing `OLDPWD='
-# assert_env_unmodified {/OLDPWD=/d}
-#
-# @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; #"# (fix Vim syntax highlighting)
- # Escape newlines
- regsub -all {\n} [string trim $sed] "\r\n" sed
-
- # 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 ""
- }
-
- # Execute diff
-
- # NOTE: The dummy argument 'LAST-ARG' sets bash variable $_ (last argument) to
- # 'LAST-ARG' so that $_ doesn't mess up the diff (as it would if $_
- # was the (possibly multi-lined) sed script).
- set cmd "diff_env \"[gen_env_filename $file 1]\" \"[gen_env_filename $file 2]\" \"$sed\" LAST-ARG"
- send "$cmd\r"
- expect "LAST-ARG\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]]
- }
- send_user $diff;
- }
- }
-}
-
-
-# Check that no completion is attempted on a certain command.
-# Params:
-# @cmd The command to attempt to complete.
-# @test Optional parameter with test name.
-proc assert_no_complete {{cmd} {test ""}} {
- if {[string length $test] == 0} {
- set test "$cmd shouldn't complete"
- }
-
- send "$cmd\t"
- expect -ex "$cmd"
-
- # We can't anchor on $, simulate typing a magical string instead.
- set endguard "Magic End Guard"
- send "$endguard"
- expect {
- -re "^$endguard$" { pass "$test" }
- default { fail "$test" }
- timeout { fail "$test" }
- }
-}
-
-
-# Check that no output is generated on a certain command.
-# @param string $cmd The command to attempt to complete.
-# @param string $test Optional parameter with test name.
-# @param string $prompt (optional) Bash prompt. Default is "/@"
-proc assert_no_output {{cmd} {test ""} {prompt /@}} {
- if {[string length $test] == 0} {
- set test "$cmd shouldn't generate output"
- }
-
- send "$cmd\r"
- expect -ex "$cmd"
-
- expect {
- -re "^\r\n$prompt$" { pass "$test" }
- default { fail "$test" }
- timeout { fail "$test" }
- }
-}
-
-
-# Source/run file with additional tests if completion for the specified command
-# is installed in bash, and the command is available.
-# @param string $command Command to check completion availability for.
-# @param string $file (optional) File to source/run. Default is
-# "lib/completions/$cmd.exp".
-proc assert_source_completions {command {file ""}} {
- if {[assert_bash_type $command]
- && [assert_install_completion_for $command]} {
- if {[string length $file] == 0} {
- set file "$::srcdir/lib/completions/$command.exp"
- }
- source $file
- } else {
- untested $command
- }
-}
-
-
-# Sort list.
-# `exec sort' is used instead of `lsort' to achieve exactly the
-# same sort order as in bash.
-# @param list $items
-# @return list Sort list
-proc bash_sort {items} {
- return [split [exec sort << [join $items "\n"]] "\n"]
-}
-
-
-# Get 'known' hostnames. Looks also in ssh's 'known_hosts' files.
-# @param string cword (optional) Word, hosts should start with.
-# @return list Hostnames
-# @see get_hosts()
-proc get_known_hosts {{cword ''}} {
- assert_bash_exec "_known_hosts_real '$cword'; echo_array COMPREPLY" \
- {} /@ result
- return $result
-}
-
-
-# Get hostnames
-# @param list $args Options:
-# -unsorted Do not sort unique. Default is sort unique.
-# @return list Hostnames
-# @see get_known_hosts()
-proc get_hosts {{args {}}} {
- array set arg [::cmdline::getoptions args {
- {unsorted "do not sort unique"}
- }]
- set sort "| sort -u"
- if {$arg(unsorted)} {set sort ""}
- set hosts [exec bash -c "compgen -A hostname $sort"]
- # NOTE: Circumventing var `avahi_hosts' and appending directly to `hosts'
- # causes an empty element to be inserted in `hosts'.
- # -- FVu, Fri Jul 17 23:11:46 CEST 2009
- set avahi_hosts [get_hosts_avahi]
- if {[llength $avahi_hosts] > 0} {
- lappend hosts $avahi_hosts
- }
- return $hosts
-}
-
-
-# Get hostnames according to avahi
-# @return list Hostnames
-proc get_hosts_avahi {} {
- # Retrieving hosts is successful?
- if { [catch {exec bash -c {
- type avahi-browse >&/dev/null \
- && avahi-browse -cpr _workstation._tcp 2>/dev/null | command grep ^= | cut -d\; -f7 | sort -u
- }} hosts] } {
- # No, retrieving hosts yields error;
- # Reset hosts
- set hosts {}
- }
- return $hosts
-}
-
-
-# Initialize tcl globals with bash variables
-proc init_tcl_bash_globals {} {
- global BASH_VERSINFO BASH_VERSION COMP_WORDBREAKS LC_CTYPE
- assert_bash_exec {printf "%s" "$COMP_WORDBREAKS"} {} /@ COMP_WORDBREAKS
- assert_bash_exec {printf "%s " "${BASH_VERSINFO[@]}"} "" /@ BASH_VERSINFO
- set BASH_VERSINFO [eval list $BASH_VERSINFO]
- assert_bash_exec {printf "%s" "$BASH_VERSION"} "" /@ BASH_VERSION
- assert_bash_exec {printf "%s" "$TESTDIR"} "" /@ TESTDIR
- assert_bash_exec {eval $(locale); printf "%s" "$LC_CTYPE"} "" /@ LC_CTYPE
-}
-
-
-# Try installing completion for the specified command.
-# @param string $command Command to install completion for.
-# @return boolean True (1) if completion is installed, False (0) if not.
-proc assert_install_completion_for {command} {
- set test "$command should have completion installed in bash"
- set cmd "__load_completion $command ; complete -p $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 }
- }
- expect "/@"
- return $result
-}
-
-
-# Detect if test suite is running under Cygwin/Windows
-proc is_cygwin {} {
- expr {[string first [string tolower [exec uname -s]] cygwin] >= 0}
-}
-
-
-# Expect items, a limited number (20) at a time.
-# Break items into chunks because `expect' seems to have a limited buffer size
-# @param list $items Expected list items
-# @param list $args Options:
-# -bash-sort Compare list bash-sorted. Default is
-# unsorted
-# -prompt PROMPT Bash prompt. Default is `/@'
-# -chunk-size CHUNK-SIZE Compare list CHUNK-SIZE items at
-# a time. Default is 20.
-# -end-newline Expect newline after last item.
-# Default is not.
-# -end-prompt Expect prompt after last item.
-# Default is not.
-# -end-space Expect single space after last item.
-# Default is not. Valid only if
-# `end-newline' not set.
-# @result boolean True if successful, False if not
-proc match_items {items {args {}}} {
- array set arg [::cmdline::getoptions args {
- {bash-sort "compare list sorted"}
- {prompt.arg "/@" "bash prompt"}
- {chunk-size.arg 20 "compare N list items at a time"}
- {end-newline "expect newline after last item"}
- {end-prompt "expect prompt after last item"}
- {end-space "expect space ater last item"}
- }]
- set prompt $arg(prompt)
- set size $arg(chunk-size)
- if {$arg(bash-sort)} {set items [bash_sort $items]}
- set result false
- for {set i 0} {$i < [llength $items]} {set i [expr {$i + $size}]} {
- # For chunks > 1, allow leading whitespace
- if {$i > $size} { set expected "\\s*" } else { set expected "" }
- for {set j 0} {$j < $size && $i + $j < [llength $items]} {incr j} {
- set item "[lindex $items [expr {$i + $j}]]"
- _escape_regexp_chars item
- append expected $item
- if {[llength $items] > 1} {append expected {\s+}}
- }
- if {[llength $items] == 1} {
- if {$arg(end-prompt)} {set end $prompt} {set end ""}
- # Both trailing space and newline are specified?
- if {$arg(end-newline) && $arg(end-space)} {
- # Indicate both trailing space or newline are ok
- set expected2 "|^$expected $end$"; # Include space
- append expected "\r\n$end"; # Include newline
- } else {
- if {$arg(end-newline)} {append expected "\r\n$end"}
- if {$arg(end-space)} {append expected " $end"}
- set expected2 ""
- }
- expect {
- -re "^$expected$$expected2" { set result true }
- -re "^$prompt$" {set result false; break }
- default { set result false; break }
- timeout { set result false; break }
- }
- } else {
- set end ""
- if {$arg(end-prompt) && $i + $j == [llength $items]} {
- set end "$prompt"
- _escape_regexp_chars end
- # \$ matches real end of expect_out buffer
- set end "$end\$"
- }
- expect {
- -re "^$expected$end" { set result true }
- default { set result false; break }
- timeout { set result false; break }
- }
- }
- }
- return $result
-}
-
-
-# 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]]
- }
- }
- return "\$TESTDIR/tmp/$file.env$seq~"
-}
-
-
-# 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 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 -o posix ; set); declare -F; shopt -p; set -o; } > \"$file\""
-}
-
-
-# Source bash_completion package
-proc source_bash_completion {} {
- assert_bash_exec {source $(cd "$SRCDIR/.."; pwd)/bash_completion}
-}
-
-
-# Split line into words, disregarding backslash escapes (e.g. \b (backspace),
-# \g (bell)), but taking backslashed spaces into account.
-# Aimed for simulating bash word splitting.
-# Example usage:
-#
-# % set a {f cd\ \be}
-# % split_words $a
-# f {cd\ \be}
-#
-# @param string Line to split
-# @return list Words
-proc split_words_bash {line} {
- set words {}
- set glue false
- foreach part [split $line] {
- set glue_next false
- # Does `part' end with a backslash (\)?
- if {[string last "\\" $part] == [string length $part] - [string length "\\"]} {
- # Remove end backslash
- set part [string range $part 0 [expr [string length $part] - [string length "\\"] - 1]]
- # Indicate glue on next run
- set glue_next true
- }
- # Must `part' be appended to latest word (= glue)?
- if {[llength $words] > 0 && [string is true $glue]} {
- # Yes, join `part' to latest word;
- set zz [lindex $words [expr [llength $words] - 1]]
- # Separate glue with backslash-space (\ );
- lset words [expr [llength $words] - 1] "$zz\\ $part"
- } else {
- # No, don't append word to latest word;
- # Append `part' as separate word
- lappend words $part
- }
- set glue $glue_next
- }
- return $words
-}
-
-
-# Given a list of items this proc finds a (part, full) pair so that when
-# completing from $part $full will be the only option.
-#
-# Arguments:
-# list The list of full completions.
-# partName Output parameter for the partial string.
-# fullName Output parameter for the full string, member of item.
-#
-# Results:
-# 1, or 0 if no suitable result was found.
-proc find_unique_completion_pair {{list} {partName} {fullName}} {
- upvar $partName part
- upvar $fullName full
- set bestscore 0
- # Uniquify the list, that's what completion does too.
- set list [lsort -unique $list]
- set n [llength $list]
- for {set i 0} {$i < $n} {incr i} {
- set cur [lindex $list $i]
- set curlen [string length $cur]
-
- set prev [lindex $list [expr {$i - 1}]]
- set next [lindex $list [expr {$i + 1}]]
- set diffprev [expr {$prev == ""}]
- set diffnext [expr {$next == ""}]
-
- # Analyse each item of the list and look for the minimum length of the
- # partial prefix which is distinct from both $next and $prev. The list
- # is sorted so the prefix will be unique in the entire list.
- #
- # In the worst case we analyse every character in the list 3 times.
- # That's actually very fast, sorting could take more.
- for {set j 0} {$j < $curlen} {incr j} {
- set curchar [string index $cur $j]
- if {!$diffprev && [string index $prev $j] != $curchar} {
- set diffprev 1
- }
- if {!$diffnext && [string index $next $j] != $curchar} {
- set diffnext 1
- }
- if {$diffnext && $diffprev} {
- break
- }
- }
-
- # At the end of the loop $j is the index of last character of
- # the unique partial prefix. The length is one plus that.
- set parlen [expr {$j + 1}]
- if {$parlen >= $curlen} {
- continue
- }
-
- # Try to find the most "readable pair"; look for a long pair where
- # $part is about half of $full.
- if {$parlen < $curlen / 2} {
- set parlen [expr {$curlen / 2}]
- }
- set score [expr {$curlen - $parlen}]
- if {$score > $bestscore} {
- set bestscore $score
- set part [string range $cur 0 [expr {$parlen - 1}]]
- set full $cur
- }
- }
- return [expr {$bestscore != 0}]
-}
-
-
-# Start bash running as test environment.
-proc start_bash {} {
- global TESTDIR TOOL_EXECUTABLE spawn_id env srcdirabs
- set TESTDIR [pwd]
- set srcdirabs [file normalize $::srcdir]; # Absolute srcdir
- # If `--tool_exec' option not specified, use "bash"
- if {! [info exists TOOL_EXECUTABLE]} {set TOOL_EXECUTABLE bash}
- set env(SRCDIR) $::srcdir
- set env(SRCDIRABS) $::srcdirabs
-
- # PS1, INPUTRC, TERM and stty columns must be initialized
- # *before* starting bash to take proper effect.
-
- # Set fixed prompt `/@'
- set env(PS1) "/@"
- # Configure readline
- set env(INPUTRC) "$::srcdir/config/inputrc"
- # Avoid escape junk at beginning of line from readline,
- # see e.g. http://bugs.gentoo.org/246091
- set env(TERM) "dumb"
- # Ensure enough columns so expect doesn't have to care about line breaks
- set stty_init "columns 150"
-
- exp_spawn $TOOL_EXECUTABLE --norc
- assert_bash_exec {} "$TOOL_EXECUTABLE --norc"
- assert_bash_exec "source $::srcdir/config/bashrc"
-}
-
-
-# Redirect xtrace output to a file.
-#
-# 'set -x' can be very useful for debugging but by default it writes to
-# stderr.
-#
-# This function uses file descriptor 6. This will break if any completion
-# tries to use the same descriptor.
-proc init_bash_xtrace {{fname xtrace.log}} {
- verbose "Enabling bash xtrace output to '$fname'"
- assert_bash_exec "exec 6>'$fname'"
- assert_bash_exec "BASH_XTRACEFD=6"
- assert_bash_exec "set -o xtrace"
-}
-
-
-# Setup test environment
-#
-# Common initialization for unit and completion tests.
-proc start_interactive_test {} {
- start_bash
- source_bash_completion
- init_tcl_bash_globals
-
- global OPT_BASH_XTRACE
- if {[info exists OPT_BASH_XTRACE]} {
- init_bash_xtrace
- }
- global OPT_BUFFER_SIZE
- if {![info exists OPT_BUFFER_SIZE]} {
- set OPT_BUFFER_SIZE 20000
- }
- verbose "Changing default expect match buffer size to $OPT_BUFFER_SIZE"
- match_max $OPT_BUFFER_SIZE
- global OPT_TIMEOUT
- if {[info exists OPT_TIMEOUT]} {
- global timeout
- verbose "Changing default expect timeout from $timeout to $OPT_TIMEOUT"
- set timeout $OPT_TIMEOUT
- }
-}
-
-
-# Interrupt completion and sync with prompt.
-# Send signals QUIT & INT.
-# @param string $prompt (optional) Bash prompt. Default is "/@"
-proc sync_after_int {{prompt /@}} {
- set test "Sync after INT"
- sleep .1
- send \031\003; # QUIT/INT
- # Wait to allow bash to become ready
- # See also: http://lists.alioth.debian.org/pipermail/bash-completion-devel/
- # 2010-February/002566.html
- sleep .1
- # NOTE: Regexp `.*' causes `expect' to discard previous unknown output.
- # This is necessary if a completion doesn't match expectations.
- # For instance with `filetype_xspec' completion (e.g. `kdvi') if
- # one expects `.txt' as a completion (wrong, because it isn't
- # there), the unmatched completions need to be cleaned up.
- expect -re ".*$prompt$"
-}
-
-
-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
-}
-
-
-# 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]]/
-}
diff --git a/test/lib/library.sh b/test/lib/library.sh
deleted file mode 100644
index ed5a85d4..00000000
--- a/test/lib/library.sh
+++ /dev/null
@@ -1,38 +0,0 @@
-# Bash library for bash-completion DejaGnu testsuite
-
-
-# @param $1 Char to add to $COMP_WORDBREAKS
-add_comp_wordbreak_char() {
- [[ "${COMP_WORDBREAKS//[^$1]}" ]] || COMP_WORDBREAKS+=$1
-} # add_comp_wordbreak_char()
-
-
-# Diff environment files to detect if environment is unmodified
-# @param $1 File 1
-# @param $2 File 2
-# @param $3 Additional sed script
-diff_env() {
- diff "$1" "$2" | sed -e "
-# Remove diff line indicators
- /^[0-9,]\{1,\}[acd]/d
-# Remove diff block separators
- /---/d
-# Remove underscore variable
- /[<>] _=/d
-# Remove PPID bash variable
- /[<>] PPID=/d
-# Remove BASH_REMATCH bash variable
- /[<>] BASH_REMATCH=/d
-# Remove functions starting with underscore
- /[<>] declare -f _/d
- $3"
-} # diff_env()
-
-
-# Output array elements, sorted and separated by newline
-# Unset variable after outputting.
-# @param $1 Name of array variable to process
-echo_array() {
- local name=$1[@]
- printf "%s\n" "${!name}" | sort
-} # echo_array()
diff --git a/test/lib/unit.exp b/test/lib/unit.exp
deleted file mode 100644
index e113e1b5..00000000
--- a/test/lib/unit.exp
+++ /dev/null
@@ -1,25 +0,0 @@
-source $::srcdir/lib/library.exp
-
-
-proc unit_exit {} {
- # Exit bash
- send "\rexit\r"
-}
-
-
-proc unit_init {test_file_name} {
- # Call unit_start() only once
- if {! [info exists ::BASH_VERSINFO]} {
- unit_start
- }
-}
-
-
-proc unit_start {} {
- start_interactive_test
-}
-
-
-proc unit_version {} {
- puts "$::TESTDIR, bash-$::BASH_VERSION"
-}
diff --git a/test/requirements-dev.txt b/test/requirements-dev.txt
new file mode 100644
index 00000000..f34f10fb
--- /dev/null
+++ b/test/requirements-dev.txt
@@ -0,0 +1,4 @@
+# Python >= 3.6.1 required here
+-r requirements.txt
+black==19.10b0
+pre-commit>=2.4.0
diff --git a/test/requirements.txt b/test/requirements.txt
index 70d77d02..df56f4e0 100644
--- a/test/requirements.txt
+++ b/test/requirements.txt
@@ -1,4 +1,4 @@
-black>=19.10b0;python_version>"3.6"
+# Python >= 3.4 required here
pexpect>=4
pytest>=3.6
pytest-xdist
diff --git a/test/run b/test/run
deleted file mode 100755
index 6180bbbf..00000000
--- a/test/run
+++ /dev/null
@@ -1,67 +0,0 @@
-#!/bin/bash
-
-
-# Print some helpful messages.
-usage() {
- echo "Run bash-completion tests"
- echo
- echo "The 'tool' is determined automatically from filenames."
- echo "Unrecognized options are passed through to dejagnu by default."
- echo
- echo "Interesting options:"
- echo " --tool_exec= Test against a different bash executable."
- echo " --buffer-size Change expect match buffer size from our default of 20000 bytes."
- echo " --debug Create a dbg.log in the test directory with detailed expect match information."
- echo " --timeout Change expect timeout from the default of 10 seconds."
- echo " --debug-xtrace Create an xtrace.log in the test directory with set -x output."
- echo
- echo "Example run: ./run unit/_get_cword.exp unit/compgen.exp"
-}
-
-
-# Try to set the tool variable; or fail if trying to set different values.
-set_tool() {
- if [[ $tool ]]; then
- if [[ $tool != $1 ]]; then
- echo "Tool spec mismatch ('$tool' and '$1'). See --usage."
- exit 1
- fi
- else
- tool=$1
- fi
-}
-
-
-cd "$(dirname "${BASH_SOURCE[0]}")"
-
-
-# Loop over the arguments.
-args=()
-while [[ $# > 0 ]]; do
- case "$1" in
- --help|--usage) usage; exit 1;;
- --buffer-size) shift; buffer_size=$1;;
- --buffer-size=*) buffer_size=${1/--buffer-size=};;
- --debug-xtrace) args+=(OPT_BASH_XTRACE=1);;
- --timeout) shift; timeout=$1;;
- --timeout=*) timeout=${1/--timeout=};;
- --tool=*) set_tool "${1#/--tool=}";;
- --tool) shift; set_tool "$1";;
- completion/*.exp|*/completion/*.exp|unit/*.exp|*/unit/*.exp)
- arg=${1%/*}
- set_tool "${arg##*/}"
- args+=("${1##*/}")
- ;;
- *) args+=("$1")
- esac
- shift
-done
-
-[[ -n $buffer_size ]] && args+=("OPT_BUFFER_SIZE=$buffer_size")
-[[ -n $timeout ]] && args+=("OPT_TIMEOUT=$timeout")
-[[ -z $tool ]] && { echo "Must specify tool somehow"; exit 1; }
-
-runtest --outdir log --tool $tool "${args[@]}"
-rc=$?
-[[ $rc -ne 0 && -n "$CI" ]] && cat log/$tool.log
-exit $rc
diff --git a/test/run-shellcheck b/test/run-shellcheck
deleted file mode 100755
index cae7b809..00000000
--- a/test/run-shellcheck
+++ /dev/null
@@ -1,4 +0,0 @@
-#!/bin/sh -eu
-cd "$(dirname $0)/.."
-exec docker run --network none -tv "$PWD:/mnt:ro" \
- koalaman/shellcheck -S error "$@"
diff --git a/test/runCompletion b/test/runCompletion
deleted file mode 100755
index 38a82622..00000000
--- a/test/runCompletion
+++ /dev/null
@@ -1,8 +0,0 @@
-#!/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.
-exec "${bashcomp_bash:-$BASH}" \
- "$(dirname "${BASH_SOURCE[0]}")/run" --tool completion $*
diff --git a/test/runInstall b/test/runInstall
deleted file mode 100755
index 87aea589..00000000
--- a/test/runInstall
+++ /dev/null
@@ -1,7 +0,0 @@
-#!/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.
-exec runtest --outdir log --tool install $*
diff --git a/test/runLint b/test/runLint
index a84c46d8..95c3887e 100755
--- a/test/runLint
+++ b/test/runLint
@@ -1,10 +1,10 @@
-#!/bin/bash
+#!/bin/bash -u
gitgrep()
{
- local out=$(git grep -I -P -n "$1" | \
- grep -E '^(bash_completion|completions/|test/)' | \
- grep -Fv 'test/runLint')
+ local out=$(git grep -I -P -n "$1" |
+ grep -E '^(bash_completion|completions/|test/)' |
+ grep -Ev "^test/runLint\>${filter_out:+|$filter_out}")
if [ -n "$out" ]; then
printf '***** %s\n' "$2"
printf '%s\n\n' "$out"
@@ -12,9 +12,10 @@ gitgrep()
}
unset CDPATH
-cd $(dirname "$0") ; cd ..
+cd $(dirname "$0")/..
cmdstart='(^|[[:space:]]|\()'
+filter_out=
gitgrep $cmdstart"awk\b.*-F([[:space:]]|[[:space:]]*[\"'][^\"']{2,})" \
'awk with -F char or -F ERE, use -Fchar instead (Solaris)'
@@ -45,3 +46,6 @@ gitgrep '(?<!command)'$cmdstart'(grep|ls|sed)(\s|$)' \
'invoke grep, ls, and sed through "command", e.g. "command grep"'
gitgrep '<<<' 'herestrings use temp files, use some other way'
+
+filter_out='^(test/|bash_completion\.sh)' gitgrep ' \[ ' \
+ 'use [[ ]] instead of [ ]'
diff --git a/test/runUnit b/test/runUnit
deleted file mode 100755
index 5df06227..00000000
--- a/test/runUnit
+++ /dev/null
@@ -1,8 +0,0 @@
-#!/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.
-exec "${bashcomp_bash:-$BASH}" \
- "$(dirname "${BASH_SOURCE[0]}")/run" --tool unit $*
diff --git a/test/setup.cfg b/test/setup.cfg
index ef9c755e..6abd7d3a 100644
--- a/test/setup.cfg
+++ b/test/setup.cfg
@@ -7,3 +7,12 @@ markers =
[mypy]
python_version = 3.4
ignore_missing_imports = true
+
+[isort]
+known_first_party = conftest
+known_third_party = pexpect,pytest
+profile = black
+line_length = 79
+
+[flake8]
+extend-ignore = D202,E203,E501
diff --git a/test/t/Makefile.am b/test/t/Makefile.am
index 0ce46b12..801841fb 100644
--- a/test/t/Makefile.am
+++ b/test/t/Makefile.am
@@ -45,6 +45,7 @@ EXTRA_DIST = \
test_bind.py \
test_bison.py \
test_bk.py \
+ test_bmake.py \
test_brctl.py \
test_btdownloadcurses_py.py \
test_btdownloadgui_py.py \
@@ -132,6 +133,7 @@ EXTRA_DIST = \
test_dot.py \
test_dpkg.py \
test_dpkg_deb.py \
+ test_dpkg_query.py \
test_dpkg_reconfigure.py \
test_dpkg_source.py \
test_dropdb.py \
@@ -249,6 +251,7 @@ EXTRA_DIST = \
test_invoke_rc_d.py \
test_ionice.py \
test_ip.py \
+ test_ipcalc.py \
test_iperf.py \
test_ipmitool.py \
test_ipsec.py \
@@ -456,6 +459,7 @@ EXTRA_DIST = \
test_povray.py \
test_pr.py \
test_prelink.py \
+ test_printenv.py \
test_protoc.py \
test_psql.py \
test_ptx.py \
@@ -523,9 +527,11 @@ EXTRA_DIST = \
test_sbcl.py \
test_sbcl_mt.py \
test_sbopkg.py \
+ test_scp.py \
test_screen.py \
test_scrub.py \
test_sdptool.py \
+ test_secret_tool.py \
test_sed.py \
test_seq.py \
test_service.py \
@@ -589,11 +595,13 @@ EXTRA_DIST = \
test_time.py \
test_timeout.py \
test_tipc.py \
+ test_totem.py \
test_touch.py \
test_tox.py \
test_tr.py \
test_tracepath.py \
test_tshark.py \
+ test_tsig_keygen.py \
test_tune2fs.py \
test_udevadm.py \
test_ulimit.py \
@@ -657,6 +665,7 @@ EXTRA_DIST = \
test_xdg_settings.py \
test_xfreerdp.py \
test_xgamma.py \
+ test_xhost.py \
test_xm.py \
test_xmllint.py \
test_xmlwf.py \
diff --git a/test/t/conftest.py b/test/t/conftest.py
index 20942e87..5c1603d5 100644
--- a/test/t/conftest.py
+++ b/test/t/conftest.py
@@ -3,18 +3,18 @@ import os
import re
import shlex
import subprocess
-from typing import Iterable, List, Optional, Tuple, Union
+import time
+from typing import Callable, Iterable, Iterator, List, Optional, Tuple
import pexpect
import pytest
-
PS1 = "/@"
MAGIC_MARK = "__MaGiC-maRKz!__"
def find_unique_completion_pair(
- items: Iterable[str]
+ items: Iterable[str],
) -> Optional[Tuple[str, str]]:
result = None
bestscore = 0
@@ -56,10 +56,22 @@ def find_unique_completion_pair(
@pytest.fixture(scope="class")
-def part_full_user(bash: pexpect.spawn) -> Optional[Tuple[str, str]]:
- res = (
- assert_bash_exec(bash, "compgen -u", want_output=True).strip().split()
- )
+def output_sort_uniq(bash: pexpect.spawn) -> Callable[[str], List[str]]:
+ def _output_sort_uniq(command: str) -> List[str]:
+ return sorted(
+ set( # weed out possible duplicates
+ assert_bash_exec(bash, command, want_output=True).split()
+ )
+ )
+
+ return _output_sort_uniq
+
+
+@pytest.fixture(scope="class")
+def part_full_user(
+ bash: pexpect.spawn, output_sort_uniq: Callable[[str], List[str]]
+) -> Optional[Tuple[str, str]]:
+ res = output_sort_uniq("compgen -u")
pair = find_unique_completion_pair(res)
if not pair:
pytest.skip("No suitable test user found")
@@ -67,10 +79,10 @@ def part_full_user(bash: pexpect.spawn) -> Optional[Tuple[str, str]]:
@pytest.fixture(scope="class")
-def part_full_group(bash: pexpect.spawn) -> Optional[Tuple[str, str]]:
- res = (
- assert_bash_exec(bash, "compgen -g", want_output=True).strip().split()
- )
+def part_full_group(
+ bash: pexpect.spawn, output_sort_uniq: Callable[[str], List[str]]
+) -> Optional[Tuple[str, str]]:
+ res = output_sort_uniq("compgen -g")
pair = find_unique_completion_pair(res)
if not pair:
pytest.skip("No suitable test user found")
@@ -78,6 +90,82 @@ def part_full_group(bash: pexpect.spawn) -> Optional[Tuple[str, str]]:
@pytest.fixture(scope="class")
+def hosts(bash: pexpect.spawn) -> List[str]:
+ output = assert_bash_exec(bash, "compgen -A hostname", want_output=True)
+ return sorted(set(output.split() + _avahi_hosts(bash)))
+
+
+@pytest.fixture(scope="class")
+def avahi_hosts(bash: pexpect.spawn) -> List[str]:
+ return _avahi_hosts(bash)
+
+
+def _avahi_hosts(bash: pexpect.spawn) -> List[str]:
+ output = assert_bash_exec(
+ bash,
+ "! type avahi-browse &>/dev/null || "
+ "avahi-browse -cpr _workstation._tcp 2>/dev/null "
+ "| command grep ^= | cut -d';' -f7",
+ want_output=None,
+ )
+ return sorted(set(output.split()))
+
+
+@pytest.fixture(scope="class")
+def known_hosts(bash: pexpect.spawn) -> List[str]:
+ output = assert_bash_exec(
+ bash,
+ '_known_hosts_real ""; '
+ r'printf "%s\n" "${COMPREPLY[@]}"; unset COMPREPLY',
+ want_output=True,
+ )
+ return sorted(set(output.split()))
+
+
+@pytest.fixture(scope="class")
+def user_home(bash: pexpect.spawn) -> Tuple[str, str]:
+ user = assert_bash_exec(
+ bash, 'id -un 2>/dev/null || echo "$USER"', want_output=True
+ ).strip()
+ home = assert_bash_exec(bash, 'echo "$HOME"', want_output=True).strip()
+ return (user, home)
+
+
+def partialize(
+ bash: pexpect.spawn, items: Iterable[str]
+) -> Tuple[str, List[str]]:
+ """
+ Get list of items starting with the first char of first of items.
+
+ Disregard items starting with a COMP_WORDBREAKS character
+ (e.g. a colon ~ IPv6 address), they are special cases requiring
+ special tests.
+ """
+ first_char = None
+ comp_wordbreaks = assert_bash_exec(
+ bash,
+ 'printf "%s" "$COMP_WORDBREAKS"',
+ want_output=True,
+ want_newline=False,
+ )
+ partial_items = []
+ for item in sorted(items):
+ if first_char is None:
+ if item[0] not in comp_wordbreaks:
+ first_char = item[0]
+ partial_items.append(item)
+ elif item.startswith(first_char):
+ partial_items.append(item)
+ else:
+ break
+ if first_char is None:
+ pytest.skip("Could not generate partial items list from %s" % items)
+ # superfluous/dead code to assist mypy; pytest.skip always raises
+ assert first_char is not None
+ return first_char, partial_items
+
+
+@pytest.fixture(scope="class")
def bash(request) -> pexpect.spawn:
logfile = None
@@ -135,7 +223,7 @@ def bash(request) -> pexpect.spawn:
skipif = marker.kwargs.get("skipif")
if skipif:
try:
- assert_bash_exec(bash, skipif)
+ assert_bash_exec(bash, skipif, want_output=None)
except AssertionError:
pass
else:
@@ -144,7 +232,7 @@ def bash(request) -> pexpect.spawn:
xfail = marker.kwargs.get("xfail")
if xfail:
try:
- assert_bash_exec(bash, xfail)
+ assert_bash_exec(bash, xfail, want_output=None)
except AssertionError:
pass
else:
@@ -182,7 +270,7 @@ def bash(request) -> pexpect.spawn:
logfile.close()
-def is_testable(bash: pexpect.spawn, cmd: str) -> bool:
+def is_testable(bash: pexpect.spawn, cmd: Optional[str]) -> bool:
if not cmd:
pytest.fail("Could not resolve name of command to test")
return False
@@ -214,8 +302,14 @@ def load_completion_for(bash: pexpect.spawn, cmd: str) -> bool:
def assert_bash_exec(
- bash: pexpect.spawn, cmd: str, want_output: bool = False, want_newline=True
+ bash: pexpect.spawn,
+ cmd: str,
+ want_output: Optional[bool] = False,
+ want_newline=True,
) -> str:
+ """
+ :param want_output: if None, don't care if got output or not
+ """
# Send command
bash.sendline(cmd)
@@ -243,16 +337,17 @@ def assert_bash_exec(
status,
output,
)
- if output:
- assert want_output, (
- 'Unexpected output from "%s": exit status=%s, output="%s"'
- % (cmd, status, output)
- )
- else:
- assert not want_output, (
- 'Expected output from "%s": exit status=%s, output="%s"'
- % (cmd, status, output)
- )
+ if want_output is not None:
+ if output:
+ assert want_output, (
+ 'Unexpected output from "%s": exit status=%s, output="%s"'
+ % (cmd, status, output)
+ )
+ else:
+ assert not want_output, (
+ 'Expected output from "%s": exit status=%s, output="%s"'
+ % (cmd, status, output)
+ )
return output
@@ -293,76 +388,52 @@ def diff_env(before: List[str], after: List[str], ignore: str):
assert not diff, "Environment should not be modified"
-class CompletionResult:
+class CompletionResult(Iterable[str]):
"""
Class to hold completion results.
"""
- def __init__(self, output: str, items: Optional[Iterable[str]] = None):
+ def __init__(self, output: Optional[str] = None):
"""
- When items are specified, they are used as the base for comparisons
- provided by this class. When not, regular expressions are used instead.
- This is because it is not always possible to unambiguously split a
- completion output string into individual items, for example when the
- items contain whitespace.
-
:param output: All completion output as-is.
- :param items: Completions as individual items. Should be specified
- only in cases where the completions are robustly known to be
- exactly the specified ones.
"""
- self.output = output
- self._items = None if items is None else sorted(items)
+ self.output = output or ""
def endswith(self, suffix: str) -> bool:
return self.output.endswith(suffix)
- def __eq__(self, expected: Union[str, Iterable[str]]) -> bool:
+ def startswith(self, prefix: str) -> bool:
+ return self.output.startswith(prefix)
+
+ def _items(self) -> List[str]:
+ return [x.strip() for x in self.output.strip().splitlines()]
+
+ def __eq__(self, expected: object) -> bool:
"""
Returns True if completion contains expected items, and no others.
Defining __eq__ this way is quite ugly, but facilitates concise
testing code.
"""
- expiter = [expected] if isinstance(expected, str) else expected
- if self._items is not None:
- return self._items == expiter
- return bool(
- re.match(
- r"^\s*" + r"\s+".join(re.escape(x) for x in expiter) + r"\s*$",
- self.output,
- )
- )
+ if isinstance(expected, str):
+ expiter = [expected] # type: Iterable
+ elif not isinstance(expected, Iterable):
+ return False
+ else:
+ expiter = expected
+ return self._items() == expiter
def __contains__(self, item: str) -> bool:
- if self._items is not None:
- return item in self._items
- return bool(
- re.search(r"(^|\s)%s(\s|$)" % re.escape(item), self.output)
- )
+ return item in self._items()
- def __iter__(self) -> Iterable[str]:
- """
- Note that iteration over items may not be accurate when items were not
- specified to the constructor, if individual items in the output contain
- whitespace. In those cases, it errs on the side of possibly returning
- more items than there actually are, and intends to never return fewer.
- """
- return iter(
- self._items
- if self._items is not None
- else re.split(r" {2,}|\r\n", self.output.strip())
- )
+ def __iter__(self) -> Iterator[str]:
+ return iter(self._items())
def __len__(self) -> int:
- """
- Uses __iter__, see caveat in it. While possibly inaccurate, this is
- good enough for truthiness checks.
- """
- return len(list(iter(self)))
+ return len(self._items())
def __repr__(self) -> str:
- return "<CompletionResult %s>" % list(self)
+ return "<CompletionResult %s>" % self._items()
def assert_complete(
@@ -371,7 +442,7 @@ def assert_complete(
skipif = kwargs.get("skipif")
if skipif:
try:
- assert_bash_exec(bash, skipif)
+ assert_bash_exec(bash, skipif, want_output=None)
except AssertionError:
pass
else:
@@ -379,7 +450,7 @@ def assert_complete(
xfail = kwargs.get("xfail")
if xfail:
try:
- assert_bash_exec(bash, xfail)
+ assert_bash_exec(bash, xfail, want_output=None)
except AssertionError:
pass
else:
@@ -393,57 +464,63 @@ def assert_complete(
# Back up environment and apply new one
assert_bash_exec(
bash,
- " ".join('%s%s="$%s"' % (env_prefix, k, k) for k in env.keys()),
+ " ".join('%s%s="${%s-}"' % (env_prefix, k, k) for k in env.keys()),
)
assert_bash_exec(
bash,
"export %s" % " ".join("%s=%s" % (k, v) for k, v in env.items()),
)
- bash.send(cmd + "\t")
- bash.expect_exact(cmd)
- bash.send(MAGIC_MARK)
- got = bash.expect(
- [
- # 0: multiple lines, result in .before
- r"\r\n" + re.escape(PS1 + cmd) + ".*" + MAGIC_MARK,
- # 1: no completion
- r"^" + MAGIC_MARK,
- # 2: on same line, result in .match
- r"^([^\r]+)%s$" % MAGIC_MARK,
- pexpect.EOF,
- pexpect.TIMEOUT,
- ]
- )
- if got == 0:
- output = bash.before
- if output.endswith(MAGIC_MARK):
- output = bash.before[: -len(MAGIC_MARK)]
- result = CompletionResult(output)
- elif got == 2:
- output = bash.match.group(1)
- result = CompletionResult(output, [shlex.split(cmd + output)[-1]])
- else:
- # TODO: warn about EOF/TIMEOUT?
- result = CompletionResult("", [])
- bash.sendintr()
- bash.expect_exact(PS1)
- if env:
- # Restore environment, and clean up backup
- # TODO: Test with declare -p if a var was set, backup only if yes, and
- # similarly restore only backed up vars. Should remove some need
- # for ignore_env.
- assert_bash_exec(
- bash,
- "export %s"
- % " ".join('%s="$%s%s"' % (k, env_prefix, k) for k in env.keys()),
- )
- assert_bash_exec(
- bash,
- "unset -v %s"
- % " ".join("%s%s" % (env_prefix, k) for k in env.keys()),
+ try:
+ bash.send(cmd + "\t")
+ # Sleep a bit if requested, to avoid `.*` matching too early
+ time.sleep(kwargs.get("sleep_after_tab", 0))
+ bash.expect_exact(cmd)
+ bash.send(MAGIC_MARK)
+ got = bash.expect(
+ [
+ # 0: multiple lines, result in .before
+ r"\r\n" + re.escape(PS1 + cmd) + ".*" + re.escape(MAGIC_MARK),
+ # 1: no completion
+ r"^" + re.escape(MAGIC_MARK),
+ # 2: on same line, result in .match
+ r"^([^\r]+)%s$" % re.escape(MAGIC_MARK),
+ pexpect.EOF,
+ pexpect.TIMEOUT,
+ ]
)
- if cwd:
- assert_bash_exec(bash, "cd - >/dev/null")
+ if got == 0:
+ output = bash.before
+ if output.endswith(MAGIC_MARK):
+ output = bash.before[: -len(MAGIC_MARK)]
+ result = CompletionResult(output)
+ elif got == 2:
+ output = bash.match.group(1)
+ result = CompletionResult(output)
+ else:
+ # TODO: warn about EOF/TIMEOUT?
+ result = CompletionResult()
+ finally:
+ bash.sendintr()
+ bash.expect_exact(PS1)
+ if env:
+ # Restore environment, and clean up backup
+ # TODO: Test with declare -p if a var was set, backup only if yes, and
+ # similarly restore only backed up vars. Should remove some need
+ # for ignore_env.
+ assert_bash_exec(
+ bash,
+ "export %s"
+ % " ".join(
+ '%s="$%s%s"' % (k, env_prefix, k) for k in env.keys()
+ ),
+ )
+ assert_bash_exec(
+ bash,
+ "unset -v %s"
+ % " ".join("%s%s" % (env_prefix, k) for k in env.keys()),
+ )
+ if cwd:
+ assert_bash_exec(bash, "cd - >/dev/null")
return result
@@ -451,7 +528,7 @@ def assert_complete(
def completion(request, bash: pexpect.spawn) -> CompletionResult:
marker = request.node.get_closest_marker("complete")
if not marker:
- return CompletionResult("", [])
+ return CompletionResult()
for pre_cmd in marker.kwargs.get("pre_cmds", []):
assert_bash_exec(bash, pre_cmd)
cmd = getattr(request.cls, "cmd", None)
@@ -467,9 +544,61 @@ def completion(request, bash: pexpect.spawn) -> CompletionResult:
) % ((cmd,) * 2)
if marker.kwargs.get("require_cmd") and not is_bash_type(bash, cmd):
pytest.skip("Command not found")
+
+ if "trail" in marker.kwargs:
+ return assert_complete_at_point(
+ bash, cmd=marker.args[0], trail=marker.kwargs["trail"]
+ )
+
return assert_complete(bash, marker.args[0], **marker.kwargs)
+def assert_complete_at_point(
+ bash: pexpect.spawn, cmd: str, trail: str
+) -> CompletionResult:
+ # TODO: merge to assert_complete
+ fullcmd = "%s%s%s" % (
+ cmd,
+ trail,
+ "\002" * len(trail),
+ ) # \002 = ^B = cursor left
+ bash.send(fullcmd + "\t")
+ bash.send(MAGIC_MARK)
+ bash.expect_exact(fullcmd.replace("\002", "\b"))
+
+ got = bash.expect_exact(
+ [
+ # 0: multiple lines, result in .before
+ PS1 + fullcmd.replace("\002", "\b"),
+ # 1: no completion
+ MAGIC_MARK,
+ pexpect.EOF,
+ pexpect.TIMEOUT,
+ ]
+ )
+ if got == 0:
+ output = bash.before
+ result = CompletionResult(output)
+
+ # At this point, something weird happens. For most test setups, as
+ # expected (pun intended!), MAGIC_MARK follows as is. But for some
+ # others (e.g. CentOS 6, Ubuntu 14 test containers), we get MAGIC_MARK
+ # one character a time, followed each time by trail and the corresponding
+ # number of \b's. Don't know why, but accept it until/if someone finds out.
+ # Or just be fine with it indefinitely, the visible and practical end
+ # result on a terminal is the same anyway.
+ repeat = "(%s%s)?" % (re.escape(trail), "\b" * len(trail))
+ fullexpected = "".join(
+ "%s%s" % (re.escape(x), repeat) for x in MAGIC_MARK
+ )
+ bash.expect(fullexpected)
+ else:
+ # TODO: warn about EOF/TIMEOUT?
+ result = CompletionResult()
+
+ return result
+
+
def in_container() -> bool:
try:
container = subprocess.check_output(
diff --git a/test/t/test_2to3.py b/test/t/test_2to3.py
index 030fb261..4bce44e6 100644
--- a/test/t/test_2to3.py
+++ b/test/t/test_2to3.py
@@ -6,6 +6,6 @@ class Test2to3:
def test_1(self, completion):
assert completion
- @pytest.mark.complete("2to3 -", require_cmd=True)
+ @pytest.mark.complete("2to3 -", require_cmd=True, require_longopt=True)
def test_2(self, completion):
assert completion
diff --git a/test/t/test_7z.py b/test/t/test_7z.py
index c6e73890..d4308d95 100644
--- a/test/t/test_7z.py
+++ b/test/t/test_7z.py
@@ -8,12 +8,11 @@ class Test7z:
@pytest.mark.complete("7z a ar -tzi")
def test_2(self, completion):
- assert completion == "-tzip"
+ assert completion == "p"
- @pytest.mark.xfail # TODO: whitespace split issue
@pytest.mark.complete(r"7z x -wa\ ", cwd="_filedir")
def test_3(self, completion):
- assert completion == r"-wa\ b/"
+ assert completion == "b/"
assert not completion.endswith(" ")
@pytest.mark.complete("7z x ", cwd="7z")
diff --git a/test/t/test_alias.py b/test/t/test_alias.py
index da9ecc33..cc592a8c 100644
--- a/test/t/test_alias.py
+++ b/test/t/test_alias.py
@@ -15,3 +15,7 @@ class TestAlias:
def test_2(self, completion):
assert completion == "foo='bar'"
assert not completion.endswith(" ")
+
+ @pytest.mark.complete("alias ", trail="foo")
+ def test_alias_at_point(self, completion):
+ assert completion == "bar foo".split()
diff --git a/test/t/test_ant.py b/test/t/test_ant.py
index b14beb94..94acea11 100644
--- a/test/t/test_ant.py
+++ b/test/t/test_ant.py
@@ -1,5 +1,7 @@
import pytest
+from conftest import assert_bash_exec
+
@pytest.mark.bashcomp(ignore_env=r"^\+ANT_ARGS=")
class TestAnt:
@@ -18,8 +20,15 @@ class TestAnt:
@pytest.mark.complete(
"ant ", cwd="ant", env=dict(ANT_ARGS="'-f named-build.xml'")
)
- def test_4(self, completion):
- assert completion == "named-build"
+ def test_4(self, bash, completion):
+ output = assert_bash_exec(bash, "complete -p ant", want_output=True)
+ if "complete-ant-cmd.pl" in output:
+ # Some versions of complete-ant-cmd.pl don't treat ANT_ARGS right;
+ # in those cases we get the correct completion produced by _ant
+ # plus whatever complete-ant-cmd.pl was able to get from build.xml
+ assert "named-build" in completion
+ else:
+ assert completion == "named-build"
@pytest.mark.complete("ant -l ")
def test_5(self, completion):
diff --git a/test/t/test_apt_cache.py b/test/t/test_apt_cache.py
index a1c29cda..f9329f22 100644
--- a/test/t/test_apt_cache.py
+++ b/test/t/test_apt_cache.py
@@ -5,9 +5,13 @@ import pytest
class TestAptCache:
@pytest.mark.complete("apt-cache ")
def test_1(self, completion):
- assert completion
+ assert "search" in completion
@pytest.mark.complete("apt-cache showsrc [", require_cmd=True)
def test_2(self, completion):
# Doesn't actually fail on grep errors, but takes a long time.
assert not completion
+
+ @pytest.mark.complete("apt-cache ", trail=" add foo")
+ def test_special_at_point(self, completion):
+ assert not completion
diff --git a/test/t/test_apt_get.py b/test/t/test_apt_get.py
index ccdff6cd..dc8299a9 100644
--- a/test/t/test_apt_get.py
+++ b/test/t/test_apt_get.py
@@ -9,4 +9,8 @@ class TestAptGet:
@pytest.mark.complete("apt-get install ./", cwd="dpkg")
def test_2(self, completion):
- assert completion == "./bash-completion-test-subject.deb"
+ assert completion == "bash-completion-test-subject.deb"
+
+ @pytest.mark.complete("apt-get build-dep ")
+ def test_build_dep_dirs(self, completion):
+ assert "dpkg/" in completion
diff --git a/test/t/test_aptitude.py b/test/t/test_aptitude.py
index c59c3580..29569f15 100644
--- a/test/t/test_aptitude.py
+++ b/test/t/test_aptitude.py
@@ -5,3 +5,19 @@ class TestAptitude:
@pytest.mark.complete("aptitude ")
def test_1(self, completion):
assert completion
+
+ @pytest.mark.complete("aptitude -", require_cmd=True)
+ def test_options(self, completion):
+ assert completion
+
+ @pytest.mark.complete("aptitude --", require_cmd=True)
+ def test_long_options(self, completion):
+ assert completion
+
+ @pytest.mark.complete("aptitude -u -")
+ def test_no_i_with_u(self, completion):
+ assert "-i" not in completion
+
+ @pytest.mark.complete("aptitude -i -")
+ def test_no_u_with_i(self, completion):
+ assert "-u" not in completion
diff --git a/test/t/test_arpspoof.py b/test/t/test_arpspoof.py
index c8955f8d..74c09a43 100644
--- a/test/t/test_arpspoof.py
+++ b/test/t/test_arpspoof.py
@@ -2,6 +2,11 @@ import pytest
class TestArpspoof:
- @pytest.mark.complete("arpspoof -", require_cmd=True)
+ @pytest.mark.complete(
+ "arpspoof -",
+ require_cmd=True,
+ # May require privileges even for outputting the usage message
+ skipif="arpspoof 2>&1 | command grep -qF libnet_open_link",
+ )
def test_1(self, completion):
assert completion
diff --git a/test/t/test_bmake.py b/test/t/test_bmake.py
new file mode 100644
index 00000000..bc885d31
--- /dev/null
+++ b/test/t/test_bmake.py
@@ -0,0 +1,7 @@
+import pytest
+
+
+class TestBmake:
+ @pytest.mark.complete("bmake -", require_cmd=True)
+ def test_options(self, completion):
+ assert completion
diff --git a/test/t/test_ccache.py b/test/t/test_ccache.py
index 64620ef4..ef55d0d8 100644
--- a/test/t/test_ccache.py
+++ b/test/t/test_ccache.py
@@ -12,15 +12,15 @@ class TestCcache:
@pytest.mark.complete("ccache stt")
def test_3(self, completion):
- assert "stty" in completion
+ assert completion == "y" or "stty" in completion
@pytest.mark.complete("ccache --zero-stats stt")
def test_4(self, completion):
- assert "stty" in completion
+ assert completion == "y" or "stty" in completion
@pytest.mark.complete("ccache --hel", require_cmd=True)
def test_5(self, completion):
- assert "--help" in completion
+ assert completion == "p" or "--help" in completion
@pytest.mark.complete("ccache --zero-stats sh +")
def test_6(self, completion):
diff --git a/test/t/test_cd.py b/test/t/test_cd.py
index fd532312..5b7789ae 100644
--- a/test/t/test_cd.py
+++ b/test/t/test_cd.py
@@ -9,7 +9,7 @@ class TestCd:
@pytest.mark.complete("cd fo", env=dict(CDPATH="shared/default"))
def test_2(self, completion):
- assert completion == "foo.d/"
+ assert completion == "o.d/"
@pytest.mark.complete("cd fo")
def test_3(self, completion):
@@ -20,3 +20,7 @@ class TestCd:
)
def test_4(self, completion):
assert not completion # No subdirs nor CDPATH
+
+ @pytest.mark.complete("cd shared/default/", trail="foo")
+ def test_dir_at_point(self, completion):
+ assert completion == ["bar bar.d/", "foo.d/"]
diff --git a/test/t/test_chown.py b/test/t/test_chown.py
index 37221cfa..9643f3eb 100644
--- a/test/t/test_chown.py
+++ b/test/t/test_chown.py
@@ -2,7 +2,7 @@ import getpass
import pytest
-from conftest import assert_bash_exec, assert_complete
+from conftest import assert_complete
@pytest.mark.bashcomp(
@@ -16,10 +16,8 @@ class TestChown:
getpass.getuser() != "root", reason="Only root can chown to all users"
)
@pytest.mark.complete("chown ")
- def test_1(self, bash, completion):
- users = sorted(
- assert_bash_exec(bash, "compgen -A user", want_output=True).split()
- )
+ def test_1(self, bash, completion, output_sort_uniq):
+ users = output_sort_uniq("compgen -u")
assert completion == users
@pytest.mark.complete("chown foo: shared/default/")
@@ -33,37 +31,39 @@ class TestChown:
def test_4(self, bash, part_full_user):
part, full = part_full_user
completion = assert_complete(bash, "chown %s" % part)
- assert completion == full
+ assert completion == full[len(part) :]
assert completion.endswith(" ")
def test_5(self, bash, part_full_user, part_full_group):
_, user = part_full_user
partgroup, fullgroup = part_full_group
completion = assert_complete(bash, "chown %s:%s" % (user, partgroup))
- assert completion == "%s:%s" % (user, fullgroup)
+ assert completion == fullgroup[len(partgroup) :]
assert completion.output.endswith(" ")
def test_6(self, bash, part_full_group):
part, full = part_full_group
completion = assert_complete(bash, "chown dot.user:%s" % part)
- assert completion == "dot.user:%s" % full
+ assert completion == full[len(part) :]
assert completion.output.endswith(" ")
- @pytest.mark.xfail # TODO check escaping, whitespace
- def test_7(self, bash, part_full_group):
- """Test preserving special chars in $prefix$partgroup<TAB>."""
- part, full = part_full_group
- for prefix in (
+ @pytest.mark.parametrize(
+ "prefix",
+ [
r"funky\ user:",
"funky.user:",
r"funky\.user:",
r"fu\ nky.user:",
r"f\ o\ o\.\bar:",
r"foo\_b\ a\.r\ :",
- ):
- completion = assert_complete(bash, "chown %s%s" % (prefix, part))
- assert completion == "%s%s" % (prefix, full)
- assert completion.output.endswith(" ")
+ ],
+ )
+ def test_7(self, bash, part_full_group, prefix):
+ """Test preserving special chars in $prefix$partgroup<TAB>."""
+ part, full = part_full_group
+ completion = assert_complete(bash, "chown %s%s" % (prefix, part))
+ assert completion == full[len(part) :]
+ assert completion.output.endswith(" ")
def test_8(self, bash, part_full_user, part_full_group):
"""Test giving up on degenerate cases instead of spewing junk."""
diff --git a/test/t/test_complete.py b/test/t/test_complete.py
index 036f954e..7ff56b41 100644
--- a/test/t/test_complete.py
+++ b/test/t/test_complete.py
@@ -5,3 +5,7 @@ class TestComplete:
@pytest.mark.complete("complete -")
def test_1(self, completion):
assert completion
+
+ @pytest.mark.complete(r"\complete -")
+ def test_2(self, completion):
+ assert completion
diff --git a/test/t/test_cpan2dist.py b/test/t/test_cpan2dist.py
index f456c0ce..1ab5de13 100644
--- a/test/t/test_cpan2dist.py
+++ b/test/t/test_cpan2dist.py
@@ -2,6 +2,8 @@ import pytest
class TestCpan2dist:
- @pytest.mark.complete("cpan2dist -", require_cmd=True)
+ @pytest.mark.complete(
+ "cpan2dist -", require_cmd=True, require_longopt=True
+ )
def test_1(self, completion):
assert completion
diff --git a/test/t/test_cpio.py b/test/t/test_cpio.py
index 1b9e37df..0b739663 100644
--- a/test/t/test_cpio.py
+++ b/test/t/test_cpio.py
@@ -1,7 +1,5 @@
import pytest
-from conftest import assert_bash_exec
-
class TestCpio:
@pytest.mark.complete("cpio --")
@@ -9,10 +7,6 @@ class TestCpio:
assert completion
@pytest.mark.complete("cpio -R ")
- def test_2(self, bash, completion):
- users = sorted(
- assert_bash_exec(bash, "compgen -A user", want_output=True)
- .strip()
- .splitlines()
- )
- assert list(completion) == users
+ def test_2(self, bash, completion, output_sort_uniq):
+ users = output_sort_uniq("compgen -u")
+ assert completion == users
diff --git a/test/t/test_cppcheck.py b/test/t/test_cppcheck.py
index da770786..73e64f5e 100644
--- a/test/t/test_cppcheck.py
+++ b/test/t/test_cppcheck.py
@@ -20,12 +20,12 @@ class TestCppcheck:
@pytest.mark.complete("cppcheck --enable=al")
def test_5(self, completion):
- assert completion == "--enable=all"
+ assert completion == "l"
@pytest.mark.complete("cppcheck --enable=xx,styl")
def test_6(self, completion):
- assert completion == "--enable=xx,style"
+ assert completion == "e"
@pytest.mark.complete("cppcheck --enable=xx,yy,styl")
def test_7(self, completion):
- assert completion == "--enable=xx,yy,style"
+ assert completion == "e"
diff --git a/test/t/test_crontab.py b/test/t/test_crontab.py
index 098fd9e0..a476694c 100644
--- a/test/t/test_crontab.py
+++ b/test/t/test_crontab.py
@@ -5,3 +5,12 @@ class TestCrontab:
@pytest.mark.complete("crontab ")
def test_1(self, completion):
assert completion
+
+ @pytest.mark.complete("crontab -l -")
+ def test_only_u_with_l(self, completion):
+ assert completion == "u"
+
+ @pytest.mark.complete("crontab -r -")
+ def test_no_l_with_r(self, completion):
+ assert completion
+ assert "-l" not in completion
diff --git a/test/t/test_curl.py b/test/t/test_curl.py
index ebccca95..63e969f9 100644
--- a/test/t/test_curl.py
+++ b/test/t/test_curl.py
@@ -8,11 +8,11 @@ class TestCurl:
@pytest.mark.complete("curl -o f", cwd="shared/default/foo.d")
def test_2(self, completion):
- assert completion == "foo"
+ assert completion == "oo"
@pytest.mark.complete("curl -LRo f", cwd="shared/default/foo.d")
def test_3(self, completion):
- assert completion == "foo"
+ assert completion == "oo"
@pytest.mark.complete("curl --o f")
def test_4(self, completion):
@@ -20,9 +20,9 @@ class TestCurl:
@pytest.mark.complete("curl --data @", cwd="shared/default/foo.d")
def test_data_atfile(self, completion):
- assert completion == "@foo"
+ assert completion == "foo"
@pytest.mark.complete("curl --data @foo.", cwd="shared/default")
def test_data_atfile_dir(self, completion):
- assert completion == "@foo.d/"
+ assert completion == "d/"
assert not completion.endswith(" ")
diff --git a/test/t/test_cvs.py b/test/t/test_cvs.py
index ab7fead8..97361e9e 100644
--- a/test/t/test_cvs.py
+++ b/test/t/test_cvs.py
@@ -13,7 +13,7 @@ class TestCvs:
@pytest.mark.complete("cvs diff foo/", cwd="cvs")
def test_3(self, completion):
- assert completion == "foo/bar"
+ assert completion == "bar"
@pytest.mark.complete("cvs -", require_cmd=True)
def test_4(self, completion):
diff --git a/test/t/test_dd.py b/test/t/test_dd.py
index be1829d3..e082faa9 100644
--- a/test/t/test_dd.py
+++ b/test/t/test_dd.py
@@ -14,4 +14,4 @@ class TestDd:
@pytest.mark.complete("dd bs")
def test_2(self, completion):
- assert completion == "bs="
+ assert completion == "="
diff --git a/test/t/test_dmypy.py b/test/t/test_dmypy.py
index efaef7ca..4c031ddd 100644
--- a/test/t/test_dmypy.py
+++ b/test/t/test_dmypy.py
@@ -2,11 +2,13 @@ import pytest
class TestDmypy:
- @pytest.mark.complete("dmypy ", require_cmd=True)
+ @pytest.mark.complete(
+ "dmypy ", require_cmd=True, xfail="! dmypy --help &>/dev/null"
+ )
def test_commands(self, completion):
assert "help" in completion
assert not any("," in x for x in completion)
- @pytest.mark.complete("dmypy -", require_cmd=True)
+ @pytest.mark.complete("dmypy -", require_cmd=True, require_longopt=True)
def test_options(self, completion):
assert "--help" in completion
diff --git a/test/t/test_dnssec_keygen.py b/test/t/test_dnssec_keygen.py
index d52e3af0..f8bd6fb1 100644
--- a/test/t/test_dnssec_keygen.py
+++ b/test/t/test_dnssec_keygen.py
@@ -13,7 +13,7 @@ class TestDnssecKeygen:
@pytest.mark.complete("dnssec-keygen -a ")
def test_2(self, completion):
assert completion
- assert "HMAC-MD5" in completion
+ assert any(x in completion for x in ("HMAC-MD5", "RSASHA1", "ED25519"))
assert "|" not in completion
assert not any(x.startswith("-") for x in completion)
diff --git a/test/t/test_dpkg_deb.py b/test/t/test_dpkg_deb.py
index c1ad8191..9be85eb6 100644
--- a/test/t/test_dpkg_deb.py
+++ b/test/t/test_dpkg_deb.py
@@ -6,3 +6,7 @@ class TestDpkgDeb:
@pytest.mark.complete("dpkg-deb --c", require_cmd=True)
def test_1(self, completion):
assert completion
+
+ @pytest.mark.complete("dpkg-deb --show b", cwd="dpkg")
+ def test_show(self, completion):
+ assert completion == "ash-completion-test-subject.deb"
diff --git a/test/t/test_dpkg_query.py b/test/t/test_dpkg_query.py
new file mode 100644
index 00000000..37c56211
--- /dev/null
+++ b/test/t/test_dpkg_query.py
@@ -0,0 +1,18 @@
+import os.path
+
+import pytest
+
+
+@pytest.mark.bashcomp(cmd="dpkg-query",)
+class TestDpkgQuery:
+ @pytest.mark.complete("dpkg-query --", require_cmd=True)
+ def test_options(self, completion):
+ assert completion
+
+ @pytest.mark.xfail(
+ not os.path.exists("/etc/debian_version"),
+ reason="Likely fails on systems not based on Debian",
+ )
+ @pytest.mark.complete("dpkg-query -W dpk", require_cmd=True)
+ def test_show(self, completion):
+ assert "dpkg" in completion
diff --git a/test/t/test_feh.py b/test/t/test_feh.py
index 51bd77b6..f2d5317b 100644
--- a/test/t/test_feh.py
+++ b/test/t/test_feh.py
@@ -16,11 +16,11 @@ class TestFeh:
@pytest.mark.complete("feh -S pix")
def test_3(self, completion):
- assert completion == "pixels"
+ assert completion == "els"
@pytest.mark.complete("feh --zoom ma")
def test_4(self, completion):
- assert completion == "max"
+ assert completion == "x"
@pytest.mark.complete("feh -g 640")
def test_5(self, completion):
diff --git a/test/t/test_find.py b/test/t/test_find.py
index a94e0e0d..9968ade7 100644
--- a/test/t/test_find.py
+++ b/test/t/test_find.py
@@ -14,10 +14,9 @@ class TestFind:
def test_3(self, completion):
assert completion
- @pytest.mark.xfail # TODO: whitespace split issue
@pytest.mark.complete("find -wholename ", cwd="shared/default")
def test_4(self, completion):
- assert completion == ["bar", "bar bar.d/", "foo", "foo foo.d/"]
+ assert completion == ["bar", "bar bar.d/", "foo", "foo.d/"]
@pytest.mark.complete("find -uid ")
def test_5(self, completion):
@@ -26,3 +25,13 @@ class TestFind:
@pytest.mark.complete("find -gid ")
def test_6(self, completion):
assert not [x for x in completion if not x.isdigit()]
+
+ @pytest.mark.complete("find -exec shared/bin/ar")
+ def test_exec(self, completion):
+ assert completion == "p"
+
+ # sh +: something that produces completions also when command is not
+ # available, and the chosen completion is not one of find's
+ @pytest.mark.complete("find /some/where -exec sh +")
+ def test_exec_args(self, completion):
+ assert "+o" in completion
diff --git a/test/t/test_finger.py b/test/t/test_finger.py
index 92c983fa..d765fdd7 100644
--- a/test/t/test_finger.py
+++ b/test/t/test_finger.py
@@ -1,16 +1,12 @@
import pytest
-from conftest import assert_bash_exec
+from conftest import assert_complete, partialize
class TestFinger:
@pytest.fixture(scope="class")
- def users_at(self, bash):
- return sorted(
- assert_bash_exec(
- bash, "compgen -A user -S @", want_output=True
- ).split()
- )
+ def users_at(self, bash, output_sort_uniq):
+ return output_sort_uniq("compgen -u -S @")
@pytest.mark.complete("finger ")
def test_1(self, bash, completion, users_at):
@@ -21,5 +17,17 @@ class TestFinger:
if not any(x.startswith("r") for x in users_at):
pytest.skip("No users starting with r")
assert completion
- assert all(x.startswith("r") for x in completion)
+ idx = 1 if len(completion) == 1 else 0
+ assert completion == sorted(
+ x[idx:] for x in users_at if x.startswith("r")
+ )
assert not completion.endswith(" ")
+
+ def test_partial_hostname(self, bash, known_hosts):
+ first_char, partial_hosts = partialize(bash, known_hosts)
+ user = "test"
+ completion = assert_complete(bash, "finger %s@%s" % (user, first_char))
+ if len(completion) == 1:
+ assert completion == partial_hosts[0][1:]
+ else:
+ assert completion == ["%s@%s" % (user, x) for x in partial_hosts]
diff --git a/test/t/test_gcc.py b/test/t/test_gcc.py
index 87f25797..50906db5 100644
--- a/test/t/test_gcc.py
+++ b/test/t/test_gcc.py
@@ -24,7 +24,7 @@ class TestGcc:
@pytest.mark.complete("gcc -fsanitize=add")
def test_enum_value(self, completion, gcc_with_completion):
- assert completion == "-fsanitize=address"
+ assert completion == "ress"
@pytest.mark.complete("gcc -fsanitize=")
def test_enum_value_with_eq(self, completion, gcc_with_completion):
@@ -48,15 +48,12 @@ class TestGcc:
@pytest.mark.complete("gcc --param=lto-max-p")
def test_param_with_eq(self, completion, gcc_with_completion):
- # starting with GCC 10.1 param end with =
- assert (
- completion == "--param=lto-max-partition"
- or completion == "--param=lto-max-partition="
- )
+ # starting with GCC 10.1 param ends with =
+ assert completion in ("artition", "artition=")
@pytest.mark.complete("gcc -march=amd")
def test_march(self, completion, gcc_with_completion, gcc_x86):
- assert completion == "-march=amdfam10"
+ assert completion == "fam10"
@pytest.mark.complete("gcc -march=")
def test_march_native(self, completion, gcc_with_completion):
diff --git a/test/t/test_ip.py b/test/t/test_ip.py
index 20752505..320647f4 100644
--- a/test/t/test_ip.py
+++ b/test/t/test_ip.py
@@ -9,3 +9,7 @@ class TestIp:
@pytest.mark.complete("ip a ")
def test_2(self, completion):
assert completion
+
+ @pytest.mark.complete("ip route replace ")
+ def test_r_r(self, completion):
+ assert completion
diff --git a/test/t/test_ipcalc.py b/test/t/test_ipcalc.py
new file mode 100644
index 00000000..5611674c
--- /dev/null
+++ b/test/t/test_ipcalc.py
@@ -0,0 +1,23 @@
+import pytest
+
+
+class TestIpcalc:
+ @pytest.mark.complete("ipcalc -", require_cmd=True)
+ def test_options(self, completion):
+ assert any(x in completion for x in "--help -h".split())
+
+ @pytest.mark.complete("ipcalc --split -")
+ def test_split_3args_1(self, completion):
+ assert not completion
+
+ @pytest.mark.complete("ipcalc --split 1 -")
+ def test_split_3args_2(self, completion):
+ assert not completion
+
+ @pytest.mark.complete("ipcalc --split 1 2 -")
+ def test_split_3args_3(self, completion):
+ assert not completion
+
+ @pytest.mark.complete("ipcalc --split 1 2 3 -", require_cmd=True)
+ def test_split_3args_4(self, completion):
+ assert any(x in completion for x in "--help -h".split())
diff --git a/test/t/test_irb.py b/test/t/test_irb.py
index 03a83c66..801d3739 100644
--- a/test/t/test_irb.py
+++ b/test/t/test_irb.py
@@ -6,6 +6,6 @@ class TestIrb:
def test_1(self, completion):
assert completion
- @pytest.mark.complete("irb -", require_cmd=True)
+ @pytest.mark.complete("irb -", require_longopt=True)
def test_options(self, completion):
assert completion
diff --git a/test/t/test_iscsiadm.py b/test/t/test_iscsiadm.py
index 932ffeb5..885ca0ab 100644
--- a/test/t/test_iscsiadm.py
+++ b/test/t/test_iscsiadm.py
@@ -2,6 +2,6 @@ import pytest
class TestIscsiadm:
- @pytest.mark.complete("iscsiadm --mode")
+ @pytest.mark.complete("iscsiadm --mod")
def test_1(self, completion):
- assert completion
+ assert completion == "e" or "--mode" in completion
diff --git a/test/t/test_isort.py b/test/t/test_isort.py
index 9f7a6524..b142d1c4 100644
--- a/test/t/test_isort.py
+++ b/test/t/test_isort.py
@@ -6,6 +6,6 @@ class TestIsort:
def test_1(self, completion):
assert completion
- @pytest.mark.complete("isort -", require_cmd=True)
+ @pytest.mark.complete("isort -", require_cmd=True, require_longopt=True)
def test_2(self, completion):
assert completion
diff --git a/test/t/test_jsonschema.py b/test/t/test_jsonschema.py
index 9e3929e6..6027f5d6 100644
--- a/test/t/test_jsonschema.py
+++ b/test/t/test_jsonschema.py
@@ -6,6 +6,8 @@ class TestJsonschema:
def test_1(self, completion):
assert completion
- @pytest.mark.complete("jsonschema -", require_cmd=True)
+ @pytest.mark.complete(
+ "jsonschema -", require_cmd=True, require_longopt=True
+ )
def test_2(self, completion):
assert completion
diff --git a/test/t/test_kcov.py b/test/t/test_kcov.py
index 3c7d3dfa..3e377ebe 100644
--- a/test/t/test_kcov.py
+++ b/test/t/test_kcov.py
@@ -8,7 +8,7 @@ class TestKcov:
@pytest.mark.complete("kcov --exclude-patter", require_cmd=True)
def test_2(self, completion):
- assert completion == "--exclude-pattern="
+ assert completion == "n="
assert completion.endswith("=")
@pytest.mark.complete("kcov -l 42,")
diff --git a/test/t/test_ldd.py b/test/t/test_ldd.py
index 70e295a5..7f7201bd 100644
--- a/test/t/test_ldd.py
+++ b/test/t/test_ldd.py
@@ -6,6 +6,8 @@ class TestLdd:
def test_1(self, completion):
assert completion
- @pytest.mark.complete("ldd -", require_cmd=True)
+ @pytest.mark.complete(
+ "ldd -", require_cmd=True, xfail="! ldd --help &>/dev/null"
+ )
def test_options(self, completion):
assert completion
diff --git a/test/t/test_less.py b/test/t/test_less.py
index 0b14e21e..70833c34 100644
--- a/test/t/test_less.py
+++ b/test/t/test_less.py
@@ -5,3 +5,7 @@ class TestLess:
@pytest.mark.complete("less --", require_longopt=True)
def test_1(self, completion):
assert completion
+
+ @pytest.mark.complete("less --", require_longopt=True)
+ def test_no_dashdashdash(self, completion):
+ assert all(not x.startswith("---") for x in completion)
diff --git a/test/t/test_lftp.py b/test/t/test_lftp.py
index 765e51e1..f775a4c6 100644
--- a/test/t/test_lftp.py
+++ b/test/t/test_lftp.py
@@ -1,17 +1,15 @@
import pytest
-from conftest import assert_bash_exec
-
@pytest.mark.bashcomp(pre_cmds=("HOME=$PWD/lftp",))
class TestLftp:
- @pytest.mark.complete("lftp ")
- def test_1(self, bash, completion):
- hosts = assert_bash_exec(
- bash, "compgen -A hostname", want_output=True
- ).split()
+ @pytest.mark.complete("lftp ", require_cmd=True)
+ def test_1(self, bash, completion, output_sort_uniq):
+ hosts = output_sort_uniq("compgen -A hostname")
assert all(x in completion for x in hosts)
- assert "lftptest" in completion # defined in lftp/.lftp/bookmarks
+ # defined in lftp/.lftp/bookmarks
+ assert all(x in completion for x in "lftptest spacetest".split())
+ assert "badbookmark" not in completion
@pytest.mark.complete("lftp -", require_cmd=True)
def test_2(self, completion):
diff --git a/test/t/test_lilo.py b/test/t/test_lilo.py
index 9783f506..2c698212 100644
--- a/test/t/test_lilo.py
+++ b/test/t/test_lilo.py
@@ -5,3 +5,12 @@ class TestLilo:
@pytest.mark.complete("lilo -")
def test_1(self, completion):
assert completion
+
+ @pytest.mark.complete("lilo -C lilo/lilo.conf -D ")
+ def test_labels(self, completion):
+ # Note that 2.4.33 should not be here, it's commented out
+ assert completion == sorted("try tamu PCDOS WinXP oldDOS".split())
+
+ @pytest.mark.complete("lilo -C -D ")
+ def test_labels_incorrect_command(self, completion):
+ assert not completion
diff --git a/test/t/test_ls.py b/test/t/test_ls.py
index 7e2d1f35..8abcb59d 100644
--- a/test/t/test_ls.py
+++ b/test/t/test_ls.py
@@ -36,5 +36,5 @@ class TestLs:
return
part, full = part_full
completion = assert_complete(bash, "ls ~%s" % part)
- assert completion == "~%s" % full
+ assert completion == full[len(part) :]
assert completion.endswith(" ")
diff --git a/test/t/test_lspci.py b/test/t/test_lspci.py
index ac18da3f..aba7b5a4 100644
--- a/test/t/test_lspci.py
+++ b/test/t/test_lspci.py
@@ -6,6 +6,8 @@ class TestLspci:
def test_1(self, completion):
assert completion
- @pytest.mark.complete("lspci -A ", require_cmd=True)
+ @pytest.mark.complete(
+ "lspci -A ", require_cmd=True, skipif="! lspci -A help &>/dev/null"
+ )
def test_2(self, completion):
assert completion
diff --git a/test/t/test_make.py b/test/t/test_make.py
index e6e043cd..19861b00 100644
--- a/test/t/test_make.py
+++ b/test/t/test_make.py
@@ -2,21 +2,19 @@ import os
import pytest
-from conftest import in_container
-
class TestMake:
@pytest.mark.complete("make -f Ma", cwd="make")
def test_1(self, completion):
- assert completion == "Makefile"
+ assert completion == "kefile"
- @pytest.mark.complete("make .", cwd="make")
+ @pytest.mark.complete("make .", cwd="make", require_cmd=True)
def test_2(self, bash, completion):
"""Hidden targets."""
assert completion == ".cache/ .test_passes".split()
os.remove("%s/make/%s" % (bash.cwd, "extra_makefile"))
- @pytest.mark.complete("make .cache/", cwd="make")
+ @pytest.mark.complete("make .cache/", cwd="make", require_cmd=True)
def test_3(self, bash, completion):
assert completion == "1 2".split()
os.remove("%s/make/%s" % (bash.cwd, "extra_makefile"))
@@ -29,22 +27,17 @@ class TestMake:
def test_5(self, completion):
assert completion
- @pytest.mark.complete("make ", cwd="make")
+ @pytest.mark.complete("make ", cwd="make", require_cmd=True)
def test_6(self, bash, completion):
assert completion == "all clean extra_makefile install sample".split()
os.remove("%s/make/%s" % (bash.cwd, "extra_makefile"))
- @pytest.mark.xfail(
- in_container() and os.environ.get("DIST") == "centos6",
- reason="Fails for some unknown reason on CentOS 6, "
- "even though the behavior appears to be correct",
- )
- @pytest.mark.complete("make .cache/.", cwd="make")
+ @pytest.mark.complete("make .cache/.", cwd="make", require_cmd=True)
def test_7(self, bash, completion):
assert completion == ".1 .2".split()
os.remove("%s/make/%s" % (bash.cwd, "extra_makefile"))
- @pytest.mark.complete("make -C make ")
+ @pytest.mark.complete("make -C make ", require_cmd=True)
def test_8(self, bash, completion):
assert completion == "all clean extra_makefile install sample".split()
os.remove("%s/make/%s" % (bash.cwd, "extra_makefile"))
diff --git a/test/t/test_man.py b/test/t/test_man.py
index ad36d96e..1ff9f84b 100644
--- a/test/t/test_man.py
+++ b/test/t/test_man.py
@@ -1,8 +1,6 @@
-import os
-
import pytest
-from conftest import assert_bash_exec, in_container
+from conftest import assert_bash_exec
@pytest.mark.bashcomp(
@@ -36,24 +34,16 @@ class TestMan:
require_cmd=True,
)
def test_1(self, completion):
- assert completion == "bash-completion-testcase"
+ assert completion == "e"
@pytest.mark.complete("man man1/f", cwd="man", env=dict(MANPATH=manpath))
def test_2(self, completion):
- assert completion == "man1/foo.1"
+ assert completion == "oo.1"
@pytest.mark.complete("man man/", cwd="man", env=dict(MANPATH=manpath))
def test_3(self, completion):
- assert completion == "man/quux.8"
-
- @pytest.mark.xfail(
- in_container() and os.environ.get("DIST") == "centos6",
- reason="TODO: Fails in CentOS for some reason, unknown "
- "how to trigger same behavior as tests show (is "
- "different and correct when tried manually, but here "
- "at least in CI completes things it should not with "
- "this MANPATH setting)",
- )
+ assert completion == "quux.8"
+
@pytest.mark.complete(
"man %s" % assumed_present,
cwd="shared/empty_dir",
@@ -82,7 +72,7 @@ class TestMan:
env=dict(MANPATH="%s:" % manpath),
)
def test_6(self, completion):
- assert completion == "bash-completion-testcase"
+ assert completion == "e"
@pytest.mark.complete(
"man %s" % assumed_present,
@@ -100,7 +90,7 @@ class TestMan:
env=dict(MANPATH=":%s" % manpath),
)
def test_8(self, completion):
- assert completion == "bash-completion-testcase"
+ assert completion == "e"
@pytest.mark.complete(
"man %s" % assumed_present,
@@ -118,7 +108,7 @@ class TestMan:
env=dict(MANPATH="%s:../tmp/man" % manpath),
)
def test_10(self, bash, colonpath, completion):
- assert completion == "Bash::Completion"
+ assert completion == "ompletion"
@pytest.mark.complete("man -", require_cmd=True)
def test_11(self, completion):
diff --git a/test/t/test_mkdir.py b/test/t/test_mkdir.py
index 1b9cb9dc..afc3fd04 100644
--- a/test/t/test_mkdir.py
+++ b/test/t/test_mkdir.py
@@ -6,10 +6,9 @@ class TestMkdir:
def test_1(self, completion):
assert completion
- @pytest.mark.xfail # TODO: whitespace split issue
@pytest.mark.complete("mkdir ", cwd="shared/default")
def test_2(self, completion):
- assert completion == ["bar bar.d/", "foo", "foo.d/"]
+ assert completion == ["bar", "bar bar.d/", "foo", "foo.d/"]
@pytest.mark.xfail # TODO: why path in completion, basename in .output?
@pytest.mark.complete("mkdir shared/default/foo.d/")
diff --git a/test/t/test_modprobe.py b/test/t/test_modprobe.py
index 38d290ae..9201119d 100644
--- a/test/t/test_modprobe.py
+++ b/test/t/test_modprobe.py
@@ -6,7 +6,7 @@ import pytest
class TestModprobe:
@pytest.mark.complete("modprobe --al")
def test_1(self, completion):
- assert completion == "--all"
+ assert completion == "l"
# "in": intel*, ...
@pytest.mark.complete(
diff --git a/test/t/test_mount.py b/test/t/test_mount.py
index fbd6dcae..8254fd40 100644
--- a/test/t/test_mount.py
+++ b/test/t/test_mount.py
@@ -12,7 +12,7 @@ class TestMount:
@pytest.mark.complete("mount /dev/sda1 def", cwd="shared")
def test_3(self, completion):
- assert completion == "default/"
+ assert completion == "ault/"
assert not completion.endswith(" ")
@pytest.mark.complete(
diff --git a/test/t/test_mr.py b/test/t/test_mr.py
index 768e1b35..bfad643f 100644
--- a/test/t/test_mr.py
+++ b/test/t/test_mr.py
@@ -19,7 +19,7 @@ class TestMr:
"mr -c shared/default/foo.d/", xfail="! man -h &>/dev/null"
)
def test_3(self, completion):
- assert completion == "shared/default/foo.d/foo"
+ assert completion == "foo"
@pytest.mark.complete(
"mr bootstrap shared/default/",
@@ -29,18 +29,21 @@ class TestMr:
def test_4(self, completion):
assert completion == ["bar", "bar bar.d/", "foo", "foo.d/"]
- @pytest.mark.xfail # "clean" doesn't exist before mr 1.20141023
@pytest.mark.complete(
- "mr clean -", require_cmd=True, xfail="! man -h &>/dev/null"
+ "mr clean -",
+ require_cmd=True,
+ xfail="! man -h &>/dev/null",
+ # "clean" does not exist before mr 1.20141023
+ skipif="! mr help 2>&1 | command grep -qwF clean",
)
def test_5(self, completion):
- assert completion == "-f"
+ assert completion == "f"
@pytest.mark.complete(
"mr commit -", require_cmd=True, xfail="! man -h &>/dev/null"
)
def test_6(self, completion):
- assert completion == "-m"
+ assert completion == "m"
@pytest.mark.complete(
"mr status ", require_cmd=True, xfail="! man -h &>/dev/null"
diff --git a/test/t/test_mypy.py b/test/t/test_mypy.py
index 63fc916c..11628c1d 100644
--- a/test/t/test_mypy.py
+++ b/test/t/test_mypy.py
@@ -6,7 +6,7 @@ class TestMypy:
def test_1(self, completion):
assert completion
- @pytest.mark.complete("mypy --", require_cmd=True)
+ @pytest.mark.complete("mypy --", require_cmd=True, require_longopt=True)
def test_2(self, completion):
assert completion
diff --git a/test/t/test_nmap.py b/test/t/test_nmap.py
index a4d8a899..9aff8b29 100644
--- a/test/t/test_nmap.py
+++ b/test/t/test_nmap.py
@@ -1,7 +1,47 @@
import pytest
+from conftest import assert_bash_exec
+
class TestNmap:
- @pytest.mark.complete("nmap --v")
- def test_1(self, completion):
+ @pytest.fixture(scope="class")
+ def functions(self, request, bash):
+ assert_bash_exec(bash, "_mock_nmap() { cat nmap/nmap-h.txt; }")
+ assert_bash_exec(bash, "complete -F _nmap _mock_nmap")
+
+ @pytest.mark.complete("nmap --v", require_cmd=True)
+ def test_live_options(self, completion):
+ assert completion
+
+ @pytest.mark.complete("nmap ")
+ def test_hosts(self, completion):
assert completion
+
+ @pytest.mark.complete("_mock_nmap -")
+ def test_mock_options(self, completion, functions):
+ assert completion == sorted(
+ "-iL -iR --exclude --excludefile -sL -sn -Pn -PS -PA -PU -PY -PE "
+ "-PP -PM -PO -n -R --dns-servers --system-dns --traceroute -sS "
+ "-sT -sA -sW -sM -sU -sN -sF -sX --scanflags -sI -sY -sZ -sO -b "
+ "-p --exclude-ports -F -r --top-ports --port-ratio -sV "
+ "--version-intensity --version-light --version-all "
+ "--version-trace -sC --script= --script-args= --script-args-file= "
+ "--script-trace --script-updatedb --script-help= -O "
+ "--osscan-limit --osscan-guess "
+ # TODO: -T known mishandled; should expand -T<0-5> to -T0 ... -T5
+ "-T --min-hostgroup --max-hostgroup --min-parallelism "
+ "--max-parallelism --min-rtt-timeout --max-rtt-timeout "
+ "--initial-rtt-timeout --max-retries --host-timeout --scan-delay "
+ "--max-scan-delay --min-rate --max-rate -f --mtu -D -S -e -g "
+ "--source-port --proxies --data --data-string --data-length "
+ "--ip-options --ttl --spoof-mac --badsum -oN -oX -oS -oG -oA -v "
+ "-d --reason --open --packet-trace --iflist --append-output "
+ "--resume --stylesheet --webxml --no-stylesheet -6 -A --datadir "
+ "--send-eth --send-ip --privileged --unprivileged -V -h"
+ "".strip().split()
+ )
+
+ @pytest.mark.complete("_mock_nmap --script-args-f")
+ def test_mock_nospace(self, completion, functions):
+ assert completion == "ile="
+ assert completion.endswith("=") # no space appended
diff --git a/test/t/test_openssl.py b/test/t/test_openssl.py
index e3af3530..3eaf6d47 100644
--- a/test/t/test_openssl.py
+++ b/test/t/test_openssl.py
@@ -6,10 +6,11 @@ class TestOpenssl:
def test_1(self, completion):
assert completion
- @pytest.mark.complete("openssl pkey -cipher ")
+ @pytest.mark.complete("openssl pkey -cipher ", require_cmd=True)
def test_2(self, completion):
assert completion
- @pytest.mark.complete("openssl dgst -s")
+ @pytest.mark.complete("openssl dgst -s", require_cmd=True)
def test_3(self, completion):
assert completion
+ assert any(x.startswith("-sha") for x in completion)
diff --git a/test/t/test_perl.py b/test/t/test_perl.py
index c8baa2f3..049c91ea 100644
--- a/test/t/test_perl.py
+++ b/test/t/test_perl.py
@@ -63,7 +63,7 @@ class TestPerl:
@pytest.mark.complete("perl -xshared/default/b")
def test_14(self, completion):
"""-x without space should complete dirs."""
- assert completion == ["-xshared/default/bar bar.d/"]
+ assert completion == r"ar\ bar.d/"
@pytest.mark.complete("perl -x shared/default/b")
def test_15(self, completion):
diff --git a/test/t/test_pgrep.py b/test/t/test_pgrep.py
index 9c233311..9a998edb 100644
--- a/test/t/test_pgrep.py
+++ b/test/t/test_pgrep.py
@@ -11,3 +11,25 @@ class TestPgrep:
@pytest.mark.complete("pgrep -", require_cmd=True)
def test_2(self, completion):
assert completion
+
+ @pytest.mark.complete(
+ "pgrep --nslist ",
+ require_cmd=True,
+ skipif=(
+ "! pgrep --help 2>&1 | command grep -qF 'Available namespaces'"
+ ),
+ )
+ def test_nslist(self, completion):
+ assert completion
+ assert not any("," in x for x in completion)
+
+ @pytest.mark.complete(
+ "pgrep --nslist foo,",
+ require_cmd=True,
+ skipif=(
+ "! pgrep --help 2>&1 | command grep -qF 'Available namespaces'"
+ ),
+ )
+ def test_nslist_after_comma(self, completion):
+ assert completion
+ assert not any("," in x for x in completion)
diff --git a/test/t/test_postfix.py b/test/t/test_postfix.py
index 67a898d1..10020b0b 100644
--- a/test/t/test_postfix.py
+++ b/test/t/test_postfix.py
@@ -1,3 +1,5 @@
+import getpass
+
import pytest
@@ -6,7 +8,15 @@ class TestPostfix:
def test_1(self, completion):
assert completion
- @pytest.mark.xfail # see TODO in completion
- @pytest.mark.complete("postfix -", require_cmd=True)
- def test_2(self, completion):
+ @pytest.mark.xfail(
+ getpass.getuser() != "root",
+ reason="Likely outputs usage only for root",
+ )
+ @pytest.mark.complete(
+ "postfix -",
+ require_cmd=True,
+ xfail="! type unbuffer &>/dev/null",
+ sleep_after_tab=2, # postfix is slow to output usage
+ )
+ def test_options(self, completion):
assert completion
diff --git a/test/t/test_printenv.py b/test/t/test_printenv.py
new file mode 100644
index 00000000..540c4f64
--- /dev/null
+++ b/test/t/test_printenv.py
@@ -0,0 +1,19 @@
+import pytest
+
+
+class TestPrintenv:
+ @pytest.mark.complete("printenv ")
+ def test_empty(self, completion):
+ assert completion
+
+ @pytest.mark.complete("printenv PAT")
+ def test_path(self, completion):
+ assert completion == "H" or "PATH" in completion
+
+ @pytest.mark.complete(
+ "printenv -",
+ require_cmd=True,
+ xfail="! printenv --help 2>&1 | command grep -qF -- ' -'",
+ )
+ def test_options(self, completion):
+ assert completion
diff --git a/test/t/test_protoc.py b/test/t/test_protoc.py
index e890c56a..744b99f4 100644
--- a/test/t/test_protoc.py
+++ b/test/t/test_protoc.py
@@ -9,3 +9,12 @@ class TestProtoc:
@pytest.mark.complete("protoc -", require_cmd=True)
def test_2(self, completion):
assert completion
+ assert any(
+ x.endswith("_out") or x.endswith("_out=") for x in completion
+ )
+
+ @pytest.mark.complete(
+ "protoc --non_existent_plugin_out ", cwd="shared/default"
+ )
+ def test_all_out(self, completion):
+ assert completion == ["bar bar.d/", "foo.d/"]
diff --git a/test/t/test_pydocstyle.py b/test/t/test_pydocstyle.py
index caa87902..1f443208 100644
--- a/test/t/test_pydocstyle.py
+++ b/test/t/test_pydocstyle.py
@@ -6,6 +6,8 @@ class TestPydocstyle:
def test_1(self, completion):
assert completion
- @pytest.mark.complete("pydocstyle -", require_cmd=True)
+ @pytest.mark.complete(
+ "pydocstyle -", require_cmd=True, require_longopt=True
+ )
def test_2(self, completion):
assert completion
diff --git a/test/t/test_pylint.py b/test/t/test_pylint.py
index 4b799532..43a4c43f 100644
--- a/test/t/test_pylint.py
+++ b/test/t/test_pylint.py
@@ -2,7 +2,7 @@ import pytest
class TestPylint:
- @pytest.mark.complete("pylint --v", require_cmd=True)
+ @pytest.mark.complete("pylint --v", require_cmd=True, require_longopt=True)
def test_1(self, completion):
assert completion
diff --git a/test/t/test_pytest.py b/test/t/test_pytest.py
index 69d01820..e70c7a5d 100644
--- a/test/t/test_pytest.py
+++ b/test/t/test_pytest.py
@@ -1,3 +1,5 @@
+import inspect
+
import pytest
@@ -9,3 +11,40 @@ class TestPytest:
@pytest.mark.complete("pytest -")
def test_2(self, completion):
assert completion
+
+ @pytest.mark.complete("pytest ../t/test_pytest.py:")
+ def test_classes_and_functions(self, completion):
+ assert completion == ":TestPytest :test_function_canary".split()
+
+ @pytest.mark.complete("pytest ../t/test_pytest.py::TestPytest::")
+ def test_class_methods(self, completion):
+ methods = [
+ x[0]
+ for x in inspect.getmembers(self, predicate=inspect.ismethod)
+ if x[0].startswith("test_")
+ ]
+ assert completion == methods
+
+ @pytest.mark.complete("pytest pytest/test_async.py:")
+ def test_classes_and_async_functions(self, completion):
+ assert completion == ":Testing :test_positive".split()
+
+ @pytest.mark.complete("pytest pytest/test_async.py::Testing::")
+ def test_async_class_methods(self, completion):
+ assert completion == "test_positive"
+
+ def non_test_cananary_method(self):
+ pass
+
+
+def test_function_canary():
+ pass
+
+
+def non_test_canary():
+ pass
+
+
+class NonTestCanaryClass:
+ def test_is_this_function_not(self):
+ pass
diff --git a/test/t/test_python.py b/test/t/test_python.py
index 57802721..5308dcb1 100644
--- a/test/t/test_python.py
+++ b/test/t/test_python.py
@@ -33,3 +33,7 @@ class TestPython:
@pytest.mark.complete("python -m sy", require_cmd=True)
def test_8(self, completion):
assert completion
+
+ @pytest.mark.complete("python -m json.", require_cmd=True)
+ def test_9(self, completion):
+ assert "json.tool" in completion
diff --git a/test/t/test_python3.py b/test/t/test_python3.py
index b968a34e..a4f6d966 100644
--- a/test/t/test_python3.py
+++ b/test/t/test_python3.py
@@ -33,3 +33,7 @@ class TestPython3:
@pytest.mark.complete("python3 -m sy", require_cmd=True)
def test_8(self, completion):
assert completion
+
+ @pytest.mark.complete("python3 -m json.", require_cmd=True)
+ def test_9(self, completion):
+ assert "json.tool" in completion
diff --git a/test/t/test_ri.py b/test/t/test_ri.py
index 9430b667..420b6cbb 100644
--- a/test/t/test_ri.py
+++ b/test/t/test_ri.py
@@ -13,4 +13,4 @@ class TestRi:
@pytest.mark.complete("ri BashCompletio", require_cmd=True)
def test_3(self, completion):
- assert completion == "BashCompletion"
+ assert completion == "n"
diff --git a/test/t/test_sbcl.py b/test/t/test_sbcl.py
index cce4cba3..f05741a7 100644
--- a/test/t/test_sbcl.py
+++ b/test/t/test_sbcl.py
@@ -2,7 +2,6 @@ import pytest
class TestSbcl:
- @pytest.mark.xfail # TODO: whitespace split issue
@pytest.mark.complete("sbcl shared/default/")
def test_1(self, completion):
- assert completion == ["bar", "bar bar.d/", "foo", "foo foo.d/"]
+ assert completion == ["bar", "bar bar.d/", "foo", "foo.d/"]
diff --git a/test/t/test_sbcl_mt.py b/test/t/test_sbcl_mt.py
index d8049f3f..c3965393 100644
--- a/test/t/test_sbcl_mt.py
+++ b/test/t/test_sbcl_mt.py
@@ -3,7 +3,6 @@ import pytest
@pytest.mark.bashcomp(cmd="sbcl-mt")
class TestSbclMt:
- @pytest.mark.xfail # TODO: whitespace split issue
@pytest.mark.complete("sbcl-mt shared/default/")
def test_1(self, completion):
- assert completion == ["bar", "bar bar.d/", "foo", "foo foo.d/"]
+ assert completion == ["bar", "bar bar.d/", "foo", "foo.d/"]
diff --git a/test/t/test_scp.py b/test/t/test_scp.py
new file mode 100644
index 00000000..66b8da22
--- /dev/null
+++ b/test/t/test_scp.py
@@ -0,0 +1,79 @@
+from itertools import chain
+
+import pytest
+
+from conftest import assert_bash_exec
+
+LIVE_HOST = "bash_completion"
+
+
+class TestScp:
+ @pytest.mark.complete("scp -F config ", cwd="scp")
+ def test_basic(self, hosts, completion):
+ expected = sorted(
+ chain(
+ (
+ "%s:" % x
+ for x in chain(
+ hosts,
+ # From fixtures/scp/config
+ "gee hut".split(),
+ # From fixtures/scp/known_hosts
+ "blah doo ike".split(),
+ )
+ ),
+ # Local filenames
+ ["config", "known_hosts", r"spaced\ \ conf"],
+ )
+ )
+ assert completion == expected
+
+ @pytest.mark.complete("scp -F 'spaced conf' ", cwd="scp")
+ def test_basic_spaced_conf(self, hosts, completion):
+ expected = sorted(
+ chain(
+ (
+ "%s:" % x
+ for x in chain(
+ hosts,
+ # From "fixtures/scp/spaced conf"
+ "gee jar".split(),
+ # From fixtures/scp/known_hosts
+ "blah doo ike".split(),
+ )
+ ),
+ # Local filenames
+ ["config", "known_hosts", r"spaced\ \ conf"],
+ )
+ )
+ assert completion == expected
+
+ @pytest.mark.complete("scp -F")
+ def test_capital_f_without_space(self, completion):
+ assert completion
+ assert not any(
+ "option requires an argument -- F" in x for x in completion
+ )
+
+ @pytest.fixture(scope="class")
+ def live_pwd(self, bash):
+ try:
+ return assert_bash_exec(
+ bash,
+ "ssh -o 'Batchmode yes' -o 'ConnectTimeout 1' "
+ "%s pwd 2>/dev/null" % LIVE_HOST,
+ want_output=True,
+ ).strip()
+ except AssertionError:
+ pytest.skip("Live host %s not available" % LIVE_HOST)
+
+ @pytest.mark.complete("scp %s:" % LIVE_HOST, sleep_after_tab=2)
+ def test_live(self, live_pwd, completion):
+ """
+ To support this test, configure a HostName entry for LIVE_HOST
+ in ssh's configs, e.g. ~/.ssh/config or /etc/ssh/ssh_config.
+
+ Connection to it must open sufficiently quickly for the
+ ConnectTimeout and sleep_after_tab settings.
+ """
+ assert completion == "%s:%s/" % (LIVE_HOST, live_pwd)
diff --git a/test/t/test_screen.py b/test/t/test_screen.py
index d9254bda..3e98837f 100644
--- a/test/t/test_screen.py
+++ b/test/t/test_screen.py
@@ -19,17 +19,17 @@ class TestScreen:
def test_4(self, completion):
assert completion
- @pytest.mark.complete("screen -T foo cat")
+ @pytest.mark.complete("screen -T foo ca")
def test_5(self, completion):
- assert completion
+ assert completion == "t" or "cat" in completion
@pytest.mark.complete("screen //")
def test_telnet(self, completion):
- assert completion == "//telnet"
+ assert completion == "telnet"
@pytest.mark.complete("screen cat //")
def test_not_telnet(self, completion):
- assert completion != "//telnet"
+ assert completion != "telnet"
@pytest.mark.complete("screen //telnet ", env=dict(HOME="$PWD/shared"))
def test_telnet_first_arg(self, completion):
diff --git a/test/t/test_secret_tool.py b/test/t/test_secret_tool.py
new file mode 100644
index 00000000..cbfc0cbc
--- /dev/null
+++ b/test/t/test_secret_tool.py
@@ -0,0 +1,12 @@
+import pytest
+
+
+@pytest.mark.bashcomp(cmd="secret-tool",)
+class TestSecretTool:
+ @pytest.mark.complete("secret-tool ", require_cmd=True)
+ def test_modes(self, completion):
+ assert "store" in completion
+
+ @pytest.mark.complete("secret-tool search ")
+ def test_no_complete(self, completion):
+ assert not completion
diff --git a/test/t/test_sftp.py b/test/t/test_sftp.py
index 0c039399..a421a449 100644
--- a/test/t/test_sftp.py
+++ b/test/t/test_sftp.py
@@ -1,11 +1,46 @@
+from itertools import chain
+
import pytest
class TestSftp:
@pytest.mark.complete("sftp -Fsp", cwd="sftp")
def test_1(self, completion):
- assert completion == "-Fspaced conf"
+ assert completion == r"aced\ \ conf"
@pytest.mark.complete("sftp -", require_cmd=True)
def test_2(self, completion):
assert completion
+
+ @pytest.mark.complete("sftp -F config ", cwd="sftp")
+ def test_hosts(self, hosts, completion):
+ expected = sorted(
+ chain(
+ hosts,
+ # From fixtures/sftp/config
+ "gee hut".split(),
+ # From fixtures/sftp/known_hosts
+ "10.10.10.10 doo ike".split(),
+ )
+ )
+ assert completion == expected
+
+ @pytest.mark.complete(r"sftp -F spaced\ \ conf ", cwd="sftp")
+ def test_hosts_spaced_conf(self, hosts, completion):
+ expected = sorted(
+ chain(
+ hosts,
+ # From "fixtures/sftp/spaced conf"
+ "gee jar".split(),
+ # From fixtures/sftp/known_hosts
+ "10.10.10.10 doo ike".split(),
+ )
+ )
+ assert completion == expected
+
+ @pytest.mark.complete("sftp -F")
+ def test_capital_f_without_space(self, completion):
+ assert completion
+ assert not any(
+ "option requires an argument -- F" in x for x in completion
+ )
diff --git a/test/t/test_slapt_get.py b/test/t/test_slapt_get.py
index 626dde9e..92449711 100644
--- a/test/t/test_slapt_get.py
+++ b/test/t/test_slapt_get.py
@@ -1,8 +1,26 @@
+import os.path
+from tempfile import mkstemp
+
import pytest
+from conftest import assert_complete, is_bash_type
+
@pytest.mark.bashcomp(cmd="slapt-get")
class TestSlaptGet:
+ @pytest.fixture(scope="class")
+ def slapt_getrc(self, request, bash):
+ fd, fname = mkstemp(prefix="slapt-getrc.", text=True)
+ request.addfinalizer(lambda: os.remove(fname))
+ with os.fdopen(fd, "w") as f:
+ print(
+ "WORKINGDIR=%s/"
+ % os.path.join(bash.cwd, *"slackware var slapt-get".split()),
+ file=f,
+ )
+ print("SOURCE=file:///home/", file=f)
+ return fname
+
@pytest.mark.complete("slapt-get -", require_cmd=True)
def test_1(self, completion):
assert completion
@@ -14,3 +32,13 @@ class TestSlaptGet:
@pytest.mark.complete("slapt-get -c non-existent-file --install ")
def test_3(self, completion):
assert not completion
+
+ def test_install(self, bash, slapt_getrc):
+ if not is_bash_type(bash, "slapt-get"):
+ pytest.skip("slapt-get not found")
+ completion = assert_complete(
+ bash, "slapt-get -c %s --install " % slapt_getrc
+ )
+ assert completion == sorted(
+ "abc-4-i686-1 ran-1.2-noarch-1 qwe-2.1-i486-1".split()
+ )
diff --git a/test/t/test_slapt_src.py b/test/t/test_slapt_src.py
index dd443b04..b55b722d 100644
--- a/test/t/test_slapt_src.py
+++ b/test/t/test_slapt_src.py
@@ -1,16 +1,43 @@
+import os
+from tempfile import mkstemp
+
import pytest
+from conftest import assert_complete, is_bash_type
+
@pytest.mark.bashcomp(cmd="slapt-src")
class TestSlaptSrc:
+ @pytest.fixture(scope="class")
+ def slapt_srcrc(self, request, bash):
+ fd, fname = mkstemp(prefix="slapt-srcrc.", text=True)
+ request.addfinalizer(lambda: os.remove(fname))
+ with os.fdopen(fd, "w") as f:
+ print(
+ "BUILDDIR=%s/"
+ % os.path.join(
+ bash.cwd, *"slackware usr src slapt-src".split()
+ ),
+ file=f,
+ )
+ return fname
+
@pytest.mark.complete("slapt-src -", require_cmd=True)
def test_1(self, completion):
assert completion
@pytest.mark.complete("slapt-src --bu", require_cmd=True)
def test_2(self, completion):
- assert completion == "--build"
+ assert completion == "ild" or "--build" in completion
@pytest.mark.complete("slapt-src --ins", require_cmd=True)
def test_3(self, completion):
- assert completion == "--install"
+ assert completion == "tall" or "--install" in completion
+
+ def test_install(self, bash, slapt_srcrc):
+ if not is_bash_type(bash, "slapt-src"):
+ pytest.skip("slapt-src not found")
+ completion = assert_complete(
+ bash, "slapt-src --config %s --install " % slapt_srcrc
+ )
+ assert completion == "abc:4 qwe:2.1".split()
diff --git a/test/t/test_ssh.py b/test/t/test_ssh.py
index 204b7c7c..8e958195 100644
--- a/test/t/test_ssh.py
+++ b/test/t/test_ssh.py
@@ -1,10 +1,12 @@
import pytest
+from conftest import assert_complete, partialize
+
class TestSsh:
@pytest.mark.complete("ssh -Fsp", cwd="ssh")
def test_1(self, completion):
- assert completion == "-Fspaced conf"
+ assert completion == r"aced\ \ conf"
@pytest.mark.complete("ssh -F config ls", cwd="ssh")
def test_2(self, completion):
@@ -32,3 +34,27 @@ class TestSsh:
@pytest.mark.complete("ssh -", require_cmd=True)
def test_6(self, completion):
assert completion
+
+ @pytest.mark.complete("ssh -F")
+ def test_capital_f_without_space(self, completion):
+ assert completion
+ assert not any(
+ "option requires an argument -- F" in x for x in completion
+ )
+
+ @pytest.mark.complete("ssh -F nonexistent ")
+ def test_capital_f_nonexistent(self, completion):
+ assert completion
+
+ def test_partial_hostname(self, bash, known_hosts):
+ first_char, partial_hosts = partialize(bash, known_hosts)
+ completion = assert_complete(bash, "ssh %s" % first_char)
+ if len(completion) == 1:
+ assert completion == partial_hosts[0][1:]
+ else:
+ assert completion == sorted(x for x in partial_hosts)
+
+ @pytest.mark.parametrize("protocol", "4 6 9".split())
+ def test_protocol_option_bundling(self, bash, protocol):
+ completion = assert_complete(bash, "ssh -%sF ssh/" % protocol)
+ assert "config" in completion
diff --git a/test/t/test_ssh_keygen.py b/test/t/test_ssh_keygen.py
index 2d53f5f8..b773ab4f 100644
--- a/test/t/test_ssh_keygen.py
+++ b/test/t/test_ssh_keygen.py
@@ -6,3 +6,54 @@ class TestSshKeygen:
@pytest.mark.complete("ssh-keygen -", require_cmd=True)
def test_1(self, completion):
assert completion
+
+ @pytest.mark.complete("ssh-keygen -s foo_key ssh-copy-id/.ssh/")
+ def test_filedir_pub_at_end_of_s(self, completion):
+ assert completion
+ assert all(x.endswith(".pub") for x in completion)
+
+ @pytest.mark.complete("ssh-keygen -s foo_key -n foo,")
+ def test_usernames_for_n(self, completion):
+ assert completion
+ assert not any("," in x for x in completion)
+ # TODO check that these are usernames
+
+ @pytest.mark.complete("ssh-keygen -s foo_key -h -n foo,")
+ def test_host_for_h_n(self, completion):
+ assert completion
+ assert not any("," in x for x in completion)
+ # TODO check that these are hostnames
+
+ @pytest.mark.complete("ssh-keygen -Y foo -n ")
+ def test_n_with_Y(self, completion):
+ assert not completion
+
+ @pytest.mark.complete("ssh-keygen -r ")
+ def test_r_without_Y(self, completion):
+ assert not completion
+
+ @pytest.mark.complete("ssh-keygen -Y foo -r ")
+ def test_r_with_Y(self, completion):
+ assert "ssh/" in completion
+
+ @pytest.mark.complete("ssh-keygen -t ecdsa -b ")
+ def test_ecdsa_b(self, completion):
+ assert completion
+
+ @pytest.mark.complete("ssh-keygen -t ecdsa-sk -b ")
+ def test_ecdsa_sk_b(self, completion):
+ assert not completion
+
+ @pytest.mark.complete("ssh-keygen -O ")
+ def test_O(self, completion):
+ assert completion
+ assert any(x.endswith("=") for x in completion)
+
+ @pytest.mark.complete("ssh-keygen -O force-command=bas")
+ def test_O_force_command(self, completion):
+ assert completion
+ assert not completion.startswith("force-command=")
+
+ @pytest.mark.complete("ssh-keygen -O unknown=")
+ def test_O_unknown(self, completion):
+ assert not completion
diff --git a/test/t/test_sudo.py b/test/t/test_sudo.py
index ced6662e..a3494664 100644
--- a/test/t/test_sudo.py
+++ b/test/t/test_sudo.py
@@ -10,27 +10,27 @@ class TestSudo:
@pytest.mark.complete("sudo cd fo", cwd="shared/default")
def test_2(self, completion):
- assert completion == "foo.d/"
+ assert completion == "o.d/"
assert not completion.endswith(" ")
@pytest.mark.complete("sudo sh share")
def test_3(self, completion):
- assert completion == "shared/"
+ assert completion == "d/"
assert not completion.endswith(" ")
@pytest.mark.complete("sudo mount /dev/sda1 def", cwd="shared")
def test_4(self, completion):
- assert completion == "default/"
+ assert completion == "ault/"
assert not completion.endswith(" ")
@pytest.mark.complete("sudo -e -u root bar foo", cwd="shared/default")
def test_5(self, completion):
- assert completion == ["foo", "foo.d/"]
+ assert completion == "foo foo.d/".split()
def test_6(self, bash, part_full_user):
part, full = part_full_user
completion = assert_complete(bash, "sudo chown %s" % part)
- assert completion == full
+ assert completion == full[len(part) :]
assert completion.endswith(" ")
def test_7(self, bash, part_full_user, part_full_group):
@@ -39,32 +39,32 @@ class TestSudo:
completion = assert_complete(
bash, "sudo chown %s:%s" % (user, partgroup)
)
- assert completion == "%s:%s" % (user, fullgroup)
+ assert completion == fullgroup[len(partgroup) :]
assert completion.endswith(" ")
def test_8(self, bash, part_full_group):
part, full = part_full_group
completion = assert_complete(bash, "sudo chown dot.user:%s" % part)
- assert completion == "dot.user:%s" % full
+ assert completion == full[len(part) :]
assert completion.endswith(" ")
- @pytest.mark.xfail # TODO check escaping, whitespace
- def test_9(self, bash, part_full_group):
- """Test preserving special chars in $prefix$partgroup<TAB>."""
- part, full = part_full_group
- for prefix in (
+ @pytest.mark.parametrize(
+ "prefix",
+ [
r"funky\ user:",
"funky.user:",
r"funky\.user:",
r"fu\ nky.user:",
r"f\ o\ o\.\bar:",
r"foo\_b\ a\.r\ :",
- ):
- completion = assert_complete(
- bash, "sudo chown %s%s" % (prefix, part)
- )
- assert completion == "%s%s" % (prefix, full)
- assert completion.endswith(" ")
+ ],
+ )
+ def test_9(self, bash, part_full_group, prefix):
+ """Test preserving special chars in $prefix$partgroup<TAB>."""
+ part, full = part_full_group
+ completion = assert_complete(bash, "sudo chown %s%s" % (prefix, part))
+ assert completion == full[len(part) :]
+ assert completion.endswith(" ")
def test_10(self, bash, part_full_user, part_full_group):
"""Test giving up on degenerate cases instead of spewing junk."""
diff --git a/test/t/test_tar.py b/test/t/test_tar.py
index 309bcc76..4518d0bd 100644
--- a/test/t/test_tar.py
+++ b/test/t/test_tar.py
@@ -77,28 +77,22 @@ class TestTar:
@pytest.mark.complete("tar --add-fil")
def test_15(self, completion, gnu_tar):
- assert completion == "--add-file="
+ assert completion == "e="
assert not completion.endswith(" ")
@pytest.mark.complete("tar -cf /dev/null --posi")
def test_16(self, completion, gnu_tar):
- assert completion == "--posix"
+ assert completion == "x"
assert completion.endswith(" ")
@pytest.mark.complete("tar --owner=")
- def test_17(self, bash, completion, gnu_tar):
- users = sorted(
- assert_bash_exec(bash, "compgen -A user", want_output=True).split()
- )
+ def test_17(self, bash, completion, gnu_tar, output_sort_uniq):
+ users = output_sort_uniq("compgen -u")
assert completion == users
@pytest.mark.complete("tar --group=")
- def test_18(self, bash, completion, gnu_tar):
- groups = sorted(
- assert_bash_exec(
- bash, "compgen -A group", want_output=True
- ).split()
- )
+ def test_18(self, bash, completion, gnu_tar, output_sort_uniq):
+ groups = output_sort_uniq("compgen -g")
assert completion == groups
# Use -b for this as -b is still not handled by tar's completion
@@ -121,6 +115,6 @@ class TestTar:
@pytest.mark.complete(r"tar tf escape.tar a/b\'", cwd="tar")
def test_22(self, bash, completion):
"""Test listing escaped chars in old option."""
- assert completion == "a/b'c/"
+ assert completion == "c/"
# TODO: "tar tf escape.tar a/b"
diff --git a/test/t/test_totem.py b/test/t/test_totem.py
new file mode 100644
index 00000000..f6fb26fe
--- /dev/null
+++ b/test/t/test_totem.py
@@ -0,0 +1,7 @@
+import pytest
+
+
+class TestTotem:
+ @pytest.mark.complete("totem ")
+ def test_basic(self, completion):
+ assert completion
diff --git a/test/t/test_tshark.py b/test/t/test_tshark.py
index 8ed881ee..f49533e0 100644
--- a/test/t/test_tshark.py
+++ b/test/t/test_tshark.py
@@ -13,9 +13,8 @@ class TestTshark:
@pytest.mark.complete("tshark -O foo,htt", require_cmd=True)
def test_3(self, completion):
- # When there's only one completion, it's be the one with "foo," prefix;
- # when multiple (e.g. http and http2), it's the completion alone.
- assert completion == "foo,http" or "http" in completion
+ # p: one completion only; http: e.g. http and http2
+ assert completion == "p" or "http" in completion
@pytest.mark.complete("tshark -o tcp", require_cmd=True)
def test_4(self, completion):
@@ -29,3 +28,7 @@ class TestTshark:
def test_6(self, completion):
"""Test there are no URLs in completions."""
assert not any("://" in x for x in completion)
+
+ @pytest.mark.complete("tshark -r ")
+ def test_input_files(self, completion):
+ assert completion
diff --git a/test/t/test_tsig_keygen.py b/test/t/test_tsig_keygen.py
new file mode 100644
index 00000000..8c8a64ac
--- /dev/null
+++ b/test/t/test_tsig_keygen.py
@@ -0,0 +1,12 @@
+import pytest
+
+
+@pytest.mark.bashcomp(cmd="tsig-keygen")
+class TestTsigKeygen:
+ @pytest.mark.complete("tsig-keygen ")
+ def test_basic(self, completion):
+ assert not completion
+
+ @pytest.mark.complete("tsig-keygen -", require_cmd=True)
+ def test_options(self, completion):
+ assert completion
diff --git a/test/t/test_umount.py b/test/t/test_umount.py
index dd4ae0b5..2baf0dac 100644
--- a/test/t/test_umount.py
+++ b/test/t/test_umount.py
@@ -1,7 +1,85 @@
import pytest
+from conftest import assert_bash_exec
+
class TestUmount:
+ @pytest.fixture(scope="class")
+ def dummy_mnt(self, request, bash):
+ """
+ umount completion from fstab can't be tested directly because it
+ (correctly) uses absolute paths. So we create a custom completion which
+ reads from a file in our text fixture instead.
+ """
+ assert_bash_exec(bash, "unset COMPREPLY cur; unset -f _mnt_completion")
+ assert_bash_exec(
+ bash,
+ "_mnt_completion() { "
+ "local cur=$(_get_cword); "
+ "_linux_fstab $(_get_pword) < mount/test-fstab; "
+ "} && complete -F _mnt_completion _mnt",
+ )
+ request.addfinalizer(
+ lambda: assert_bash_exec(
+ bash, "complete -r _mnt; unset -f _mnt_completion"
+ )
+ )
+
@pytest.mark.complete("umount ")
def test_1(self, completion):
assert completion
+
+ @pytest.mark.complete("_mnt /mnt/nice-test-p")
+ def test_mnt_basic(self, completion, dummy_mnt):
+ assert completion == "ath"
+
+ # Note in tests below that return only one result, that the result
+ # is shell unescaped due to how assert_complete handles the
+ # "one result on same line case".
+
+ @pytest.mark.complete(r"_mnt /mnt/nice\ test-p")
+ def test_mnt_space(self, completion, dummy_mnt):
+ assert completion == r"ath"
+
+ @pytest.mark.complete(r"_mnt /mnt/nice\$test-p")
+ def test_mnt_dollar(self, completion, dummy_mnt):
+ assert completion == "ath"
+
+ @pytest.mark.complete(r"_mnt /mnt/nice\ test\\p")
+ def test_mnt_backslash(self, completion, dummy_mnt):
+ assert completion == "ath"
+
+ @pytest.mark.complete(r"_mnt /mnt/nice\ ")
+ def test_mnt_after_space(self, completion, dummy_mnt):
+ assert completion == sorted(
+ (r"/mnt/nice\ test\\path", r"/mnt/nice\ test-path")
+ )
+
+ @pytest.mark.complete(r"_mnt /mnt/nice\$")
+ def test_mnt_at_dollar(self, completion, dummy_mnt):
+ assert completion == "test-path"
+
+ @pytest.mark.complete(r"_mnt /mnt/nice\'")
+ def test_mnt_at_quote(self, completion, dummy_mnt):
+ assert completion == "test-path"
+
+ @pytest.mark.complete("_mnt /mnt/other")
+ def test_mnt_other(self, completion, dummy_mnt):
+ assert completion == r"\'test\ path"
+
+ @pytest.mark.complete("_mnt -L Ubu")
+ def test_mnt_label_space(self, completion, dummy_mnt):
+ assert completion == r"ntu\ Karmic"
+
+ @pytest.mark.complete("_mnt -L Deb")
+ def test_mnt_label_quote(self, completion, dummy_mnt):
+ assert completion == r"ian-it\'s\ awesome"
+
+ def test_linux_fstab_unescape(self, bash):
+ assert_bash_exec(bash, r"var=one\'two\\040three\\")
+ assert_bash_exec(bash, "__linux_fstab_unescape var")
+ output = assert_bash_exec(
+ bash, r'printf "%s\n" "$var"', want_output=True
+ )
+ assert output.strip() == "one'two three\\"
+ assert_bash_exec(bash, "unset var")
diff --git a/test/t/test_upgradepkg.py b/test/t/test_upgradepkg.py
index 4c72a158..87fe8e4c 100644
--- a/test/t/test_upgradepkg.py
+++ b/test/t/test_upgradepkg.py
@@ -32,3 +32,20 @@ class TestUpgradepkg:
]
)
assert completion == expected
+
+ @pytest.mark.complete("upgradepkg foo%", cwd="slackware/home")
+ def test_after_percent(self, completion):
+ expected = sorted(
+ [
+ "%s/" % x
+ for x in os.listdir("slackware/home")
+ if os.path.isdir("./slackware/home/%s" % x)
+ ]
+ + [
+ x
+ for x in os.listdir("slackware/home")
+ if os.path.isfile("./slackware/home/%s" % x)
+ and fnmatch.fnmatch(x, "*.t[bglx]z")
+ ]
+ )
+ assert completion == ["foo%%%s" % x for x in expected]
diff --git a/test/t/test_userdel.py b/test/t/test_userdel.py
index 718c6629..3405e127 100644
--- a/test/t/test_userdel.py
+++ b/test/t/test_userdel.py
@@ -6,6 +6,6 @@ class TestUserdel:
def test_1(self, completion):
assert completion
- @pytest.mark.complete("userdel root")
+ @pytest.mark.complete("userdel roo")
def test_2(self, completion):
- assert "root" in completion
+ assert completion == "t" or "root" in completion
diff --git a/test/t/test_valgrind.py b/test/t/test_valgrind.py
index c7c979dd..0553b556 100644
--- a/test/t/test_valgrind.py
+++ b/test/t/test_valgrind.py
@@ -16,13 +16,13 @@ class TestValgrind:
@pytest.mark.complete("valgrind --tool=memche", require_cmd=True)
def test_3(self, completion):
- assert "--tool=memcheck" in completion
+ assert completion == "ck" or "--tool=memcheck" in completion
@pytest.mark.complete(
"valgrind --tool=helgrind --history-l", require_cmd=True
)
def test_4(self, completion):
- assert "--history-level=" in completion
+ assert completion == "evel=" or "--history-level=" in completion
assert not completion.endswith(" ")
@pytest.mark.complete(r"valgrind --log-file=v\ 0.log ./bin/", cwd="shared")
diff --git a/test/t/test_wol.py b/test/t/test_wol.py
index b7a622ee..bf04f76e 100644
--- a/test/t/test_wol.py
+++ b/test/t/test_wol.py
@@ -5,14 +5,15 @@ import pytest
class TestWol:
@pytest.mark.complete("wol ")
def test_1(self, completion):
- assert (
- completion == "00:00:00:00:00:00 11:11:11:11:11:11 "
+ assert all(
+ x in completion
+ for x in "00:00:00:00:00:00 11:11:11:11:11:11 "
"22:22:22:22:22:22 33:33:33:33:33:33".split()
)
@pytest.mark.complete("wol 00:")
def test_2(self, completion):
- assert completion == "00:00:00:00:00:00"
+ assert any(x.endswith("00:00:00:00:00") for x in completion)
@pytest.mark.complete("wol -", require_cmd=True)
def test_3(self, completion):
diff --git a/test/t/test_write.py b/test/t/test_write.py
index 8f0886e4..fc4bfa00 100644
--- a/test/t/test_write.py
+++ b/test/t/test_write.py
@@ -2,6 +2,6 @@ import pytest
class TestWrite:
- @pytest.mark.complete("write root")
+ @pytest.mark.complete("write roo")
def test_1(self, completion):
- assert "root" in completion
+ assert completion == "t" or "root" in completion
diff --git a/test/t/test_xfreerdp.py b/test/t/test_xfreerdp.py
index a8435d6c..56162714 100644
--- a/test/t/test_xfreerdp.py
+++ b/test/t/test_xfreerdp.py
@@ -5,10 +5,20 @@ from conftest import assert_bash_exec
class TestXfreerdp:
def _help(self, bash):
- return assert_bash_exec(bash, "xfreerdp --help || :", want_output=True)
+ return assert_bash_exec(
+ bash, "xfreerdp --help 2>&1 || :", want_output=True
+ )
@pytest.fixture(scope="class")
- def slash_syntax(self, bash):
+ def help_success(self, bash):
+ output = self._help(bash)
+ # Example from our CentOS 7 container
+ # [04:51:31:663] [238:238] [ERROR][com.freerdp.client.x11] - Failed to get pixmap info
+ if not output or "ERROR" in output.strip().splitlines()[0]:
+ pytest.skip("--help errored")
+
+ @pytest.fixture(scope="class")
+ def slash_syntax(self, bash, help_success):
if "/help" not in self._help(bash):
pytest.skip("Not slash syntax")
@@ -18,27 +28,31 @@ class TestXfreerdp:
pytest.skip("Not dash syntax")
@pytest.mark.complete("xfreerdp /", require_cmd=True)
- def test_1(self, bash, completion, slash_syntax):
+ def test_1(self, bash, completion, help_success, slash_syntax):
assert completion
@pytest.mark.complete("xfreerdp -", require_cmd=True)
- def test_2(self, completion):
+ def test_2(self, completion, help_success):
assert completion
@pytest.mark.complete("xfreerdp +", require_cmd=True)
- def test_3(self, bash, completion, slash_syntax):
+ def test_3(self, bash, completion, help_success, slash_syntax):
assert completion
- @pytest.mark.complete("xfreerdp /kbd:", require_cmd=True)
- def test_4(self, bash, completion, slash_syntax):
+ @pytest.mark.complete(
+ "xfreerdp /kbd:",
+ require_cmd=True,
+ skipif='test -z "$(xfreerdp /kbd-list 2>/dev/null)"',
+ )
+ def test_4(self, bash, completion, help_success, slash_syntax):
assert completion
@pytest.mark.complete("xfreerdp /help ", require_cmd=True)
- def test_5(self, completion):
+ def test_5(self, completion, help_success):
assert not completion
@pytest.mark.complete("xfreerdp -k ", require_cmd=True)
- def test_6(self, bash, completion, dash_syntax):
+ def test_6(self, bash, completion, help_success, dash_syntax):
assert completion
@pytest.mark.complete("xfreerdp --help ", require_cmd=True)
diff --git a/test/t/test_xgamma.py b/test/t/test_xgamma.py
index beb684f8..151e2d36 100644
--- a/test/t/test_xgamma.py
+++ b/test/t/test_xgamma.py
@@ -8,5 +8,5 @@ class TestXgamma:
@pytest.mark.complete("xgamma -gam", require_cmd=True)
def test_2(self, completion):
- assert completion == "-gamma"
+ assert completion == "ma"
assert completion.endswith(" ")
diff --git a/test/t/test_xhost.py b/test/t/test_xhost.py
new file mode 100644
index 00000000..bb2df82a
--- /dev/null
+++ b/test/t/test_xhost.py
@@ -0,0 +1,22 @@
+import pytest
+
+from conftest import assert_complete, partialize
+
+
+@pytest.mark.bashcomp(pre_cmds=("HOME=$PWD",))
+class TestXhost:
+ @pytest.mark.parametrize("prefix", ["+", "-", ""])
+ def test_hosts(self, bash, hosts, prefix):
+ completion = assert_complete(bash, "xhost %s" % prefix)
+ assert completion == ["%s%s" % (prefix, x) for x in hosts]
+
+ @pytest.mark.parametrize("prefix", ["+", "-", ""])
+ def test_partial_hosts(self, bash, hosts, prefix):
+ first_char, partial_hosts = partialize(bash, hosts)
+ completion = assert_complete(bash, "xhost %s%s" % (prefix, first_char))
+ if len(completion) == 1:
+ assert completion == partial_hosts[0][1:]
+ else:
+ assert completion == sorted(
+ "%s%s" % (prefix, x) for x in partial_hosts
+ )
diff --git a/test/t/unit/Makefile.am b/test/t/unit/Makefile.am
index b96b326c..3eb652af 100644
--- a/test/t/unit/Makefile.am
+++ b/test/t/unit/Makefile.am
@@ -8,12 +8,15 @@ EXTRA_DIST = \
test_unit_get_cword.py \
test_unit_init_completion.py \
test_unit_ip_addresses.py \
+ test_unit_known_hosts_real.py \
test_unit_longopt.py \
test_unit_parse_help.py \
test_unit_parse_usage.py \
test_unit_quote.py \
+ test_unit_quote_readline.py \
test_unit_tilde.py \
- test_unit_variables.py
+ test_unit_variables.py \
+ test_unit_xinetd_services.py
all:
diff --git a/test/t/unit/test_unit_count_args.py b/test/t/unit/test_unit_count_args.py
index c0afe736..56bce2cb 100644
--- a/test/t/unit/test_unit_count_args.py
+++ b/test/t/unit/test_unit_count_args.py
@@ -1,6 +1,6 @@
import pytest
-from conftest import assert_bash_exec, TestUnitBase
+from conftest import TestUnitBase, assert_bash_exec
@pytest.mark.bashcomp(
@@ -11,7 +11,7 @@ class TestUnitCountArgs(TestUnitBase):
return self._test_unit("_count_args %s; echo $args", *args, **kwargs)
def test_1(self, bash):
- assert_bash_exec(bash, "_count_args >/dev/null")
+ assert_bash_exec(bash, "COMP_CWORD= _count_args >/dev/null")
def test_2(self, bash):
"""a b| should set args to 1"""
diff --git a/test/t/unit/test_unit_expand.py b/test/t/unit/test_unit_expand.py
index 7c0a9836..d2a3ebc4 100644
--- a/test/t/unit/test_unit_expand.py
+++ b/test/t/unit/test_unit_expand.py
@@ -3,7 +3,7 @@ import pytest
from conftest import assert_bash_exec
-@pytest.mark.bashcomp(cmd=None)
+@pytest.mark.bashcomp(cmd=None, ignore_env=r"^[+-](cur|COMPREPLY)=")
class TestUnitExpand:
def test_1(self, bash):
assert_bash_exec(bash, "_expand >/dev/null")
@@ -11,3 +11,21 @@ class TestUnitExpand:
def test_2(self, bash):
"""Test environment non-pollution, detected at teardown."""
assert_bash_exec(bash, "foo() { _expand; }; foo; unset foo")
+
+ def test_user_home_compreply(self, bash, user_home):
+ user, home = user_home
+ output = assert_bash_exec(
+ bash,
+ r'cur="~%s"; _expand; printf "%%s\n" "$COMPREPLY"' % user,
+ want_output=True,
+ )
+ assert output.strip() == home
+
+ def test_user_home_cur(self, bash, user_home):
+ user, home = user_home
+ output = assert_bash_exec(
+ bash,
+ r'cur="~%s/a"; _expand; printf "%%s\n" "$cur"' % user,
+ want_output=True,
+ )
+ assert output.strip() == "%s/a" % home
diff --git a/test/t/unit/test_unit_expand_tilde_by_ref.py b/test/t/unit/test_unit_expand_tilde_by_ref.py
index fbc172df..17bdedfe 100644
--- a/test/t/unit/test_unit_expand_tilde_by_ref.py
+++ b/test/t/unit/test_unit_expand_tilde_by_ref.py
@@ -3,7 +3,7 @@ import pytest
from conftest import assert_bash_exec
-@pytest.mark.bashcomp(cmd=None)
+@pytest.mark.bashcomp(cmd=None, ignore_env=r"^[+-]var=")
class TestUnitExpandTildeByRef:
def test_1(self, bash):
assert_bash_exec(bash, "__expand_tilde_by_ref >/dev/null")
@@ -14,3 +14,33 @@ class TestUnitExpandTildeByRef:
bash,
'_x() { local aa="~"; __expand_tilde_by_ref aa; }; _x; unset _x',
)
+
+ @pytest.mark.parametrize("plain_tilde", (True, False))
+ @pytest.mark.parametrize(
+ "suffix_expanded",
+ (
+ ("", True),
+ ("/foo", True),
+ (r"/\$HOME", True),
+ ("/a b", True),
+ ("/*", True),
+ (";echo hello", False),
+ ("/a;echo hello", True),
+ ),
+ )
+ def test_expand(self, bash, user_home, plain_tilde, suffix_expanded):
+ user, home = user_home
+ suffix, expanded = suffix_expanded
+ if plain_tilde:
+ user = ""
+ if not suffix or not expanded:
+ home = "~"
+ elif not expanded:
+ home = "~%s" % user
+ output = assert_bash_exec(
+ bash,
+ r'var="~%s%s"; __expand_tilde_by_ref var; printf "%%s\n" "$var"'
+ % (user, suffix),
+ want_output=True,
+ )
+ assert output.strip() == "%s%s" % (home, suffix.replace(r"\$", "$"),)
diff --git a/test/t/unit/test_unit_filedir.py b/test/t/unit/test_unit_filedir.py
index 7f14f294..b847efc2 100644
--- a/test/t/unit/test_unit_filedir.py
+++ b/test/t/unit/test_unit_filedir.py
@@ -1,3 +1,9 @@
+import os
+import shutil
+import sys
+import tempfile
+from pathlib import Path
+
import pytest
from conftest import assert_bash_exec, assert_complete
@@ -24,102 +30,206 @@ class TestUnitFiledir:
"complete -F _fd fd",
)
+ @pytest.fixture(scope="class")
+ def non_windows_testdir(self, request, bash):
+ if sys.platform.startswith("win"):
+ pytest.skip("Filenames not allowed on Windows")
+ tempdir = Path(tempfile.mkdtemp(prefix="bash-completion_filedir"))
+ request.addfinalizer(lambda: shutil.rmtree(str(tempdir)))
+ subdir = tempdir / 'a"b'
+ subdir.mkdir()
+ (subdir / "d").touch()
+ subdir = tempdir / "a*b"
+ subdir.mkdir()
+ (subdir / "j").touch()
+ subdir = tempdir / r"a\b"
+ subdir.mkdir()
+ (subdir / "g").touch()
+ return tempdir
+
+ @pytest.fixture(scope="class")
+ def utf8_ctype(self, bash):
+ # TODO: this likely is not the right thing to do. Instead we should
+ # grab the setting from the running shell, possibly eval $(locale)
+ # in a subshell and grab LC_CTYPE from there. That doesn't seem to work
+ # either everywhere though.
+ lc_ctype = os.environ.get("LC_CTYPE", "")
+ if "UTF-8" not in lc_ctype:
+ pytest.skip("Applicable only in LC_CTYPE=UTF-8 setups")
+ return lc_ctype
+
def test_1(self, bash):
assert_bash_exec(bash, "_filedir >/dev/null")
@pytest.mark.parametrize("funcname", "f f2".split())
def test_2(self, bash, functions, funcname):
completion = assert_complete(bash, "%s ab/" % funcname, cwd="_filedir")
- assert completion == "ab/e"
+ assert completion == "e"
@pytest.mark.parametrize("funcname", "f f2".split())
def test_3(self, bash, functions, funcname):
completion = assert_complete(
bash, r"%s a\ b/" % funcname, cwd="_filedir"
)
- assert completion == "a b/i"
+ assert completion == "i"
@pytest.mark.parametrize("funcname", "f f2".split())
def test_4(self, bash, functions, funcname):
completion = assert_complete(
bash, r"%s a\'b/" % funcname, cwd="_filedir"
)
- assert completion == "a'b/c"
+ assert completion == "c"
@pytest.mark.parametrize("funcname", "f f2".split())
def test_5(self, bash, functions, funcname):
completion = assert_complete(
bash, r"%s a\&b/" % funcname, cwd="_filedir"
)
- assert completion == "a&b/f"
+ assert completion == "f"
@pytest.mark.parametrize("funcname", "f f2".split())
def test_6(self, bash, functions, funcname):
completion = assert_complete(
bash, r"%s a\$" % funcname, cwd="_filedir"
)
- assert completion == "a$b/"
+ assert completion == "b/"
@pytest.mark.parametrize("funcname", "f f2".split())
def test_7(self, bash, functions, funcname):
completion = assert_complete(
bash, r"%s 'ab/" % funcname, cwd="_filedir"
)
- assert completion == "ab/e"
+ assert completion == "e'"
@pytest.mark.parametrize("funcname", "f f2".split())
def test_8(self, bash, functions, funcname):
completion = assert_complete(
bash, r"%s 'a b/" % funcname, cwd="_filedir"
)
- assert completion == "a b/i"
+ assert completion == "i'"
@pytest.mark.parametrize("funcname", "f f2".split())
def test_9(self, bash, functions, funcname):
completion = assert_complete(
bash, r"%s 'a$b/" % funcname, cwd="_filedir"
)
- assert completion == "a$b/h"
+ assert completion == "h'"
@pytest.mark.parametrize("funcname", "f f2".split())
def test_10(self, bash, functions, funcname):
completion = assert_complete(
bash, r"%s 'a&b/" % funcname, cwd="_filedir"
)
- assert completion == "a&b/f"
+ assert completion == "f'"
@pytest.mark.parametrize("funcname", "f f2".split())
def test_11(self, bash, functions, funcname):
completion = assert_complete(
bash, r'%s "ab/' % funcname, cwd="_filedir"
)
- assert completion == "ab/e"
+ assert completion == 'e"'
@pytest.mark.parametrize("funcname", "f f2".split())
def test_12(self, bash, functions, funcname):
completion = assert_complete(
bash, r'%s "a b/' % funcname, cwd="_filedir"
)
- assert completion == "a b/i"
+ assert completion == 'i"'
@pytest.mark.parametrize("funcname", "f f2".split())
def test_13(self, bash, functions, funcname):
completion = assert_complete(
bash, "%s \"a'b/" % funcname, cwd="_filedir"
)
- assert completion == "a'b/c"
+ assert completion == 'c"'
@pytest.mark.parametrize("funcname", "f f2".split())
def test_14(self, bash, functions, funcname):
completion = assert_complete(
bash, '%s "a&b/' % funcname, cwd="_filedir"
)
- assert completion == "a&b/f"
+ assert completion == 'f"'
@pytest.mark.complete(r"fd a\ ", cwd="_filedir")
def test_15(self, functions, completion):
- assert completion == "a b/"
+ assert completion == "b/"
@pytest.mark.complete("g ", cwd="_filedir/ext")
def test_16(self, functions, completion):
assert completion == sorted("ee.e1 foo/ gg.e1 ii.E1".split())
+
+ @pytest.mark.parametrize("funcname", "f f2".split())
+ def test_17(self, bash, functions, funcname):
+ completion = assert_complete(
+ bash, r"%s a\$b/" % funcname, cwd="_filedir"
+ )
+ assert completion == "h"
+
+ @pytest.mark.parametrize("funcname", "f f2".split())
+ def test_18(self, bash, functions, funcname):
+ completion = assert_complete(
+ bash, r"%s \[x" % funcname, cwd="_filedir/brackets"
+ )
+ assert completion == r"\]"
+
+ @pytest.mark.parametrize("funcname", "f f2".split())
+ def test_19(self, bash, functions, funcname, non_windows_testdir):
+ completion = assert_complete(
+ bash, '%s a\\"b/' % funcname, cwd=non_windows_testdir
+ )
+ assert completion == "d"
+
+ @pytest.mark.parametrize("funcname", "f f2".split())
+ def test_20(self, bash, functions, funcname, non_windows_testdir):
+ completion = assert_complete(
+ bash, r"%s a\\b/" % funcname, cwd=non_windows_testdir
+ )
+ assert completion == "g"
+
+ @pytest.mark.parametrize("funcname", "f f2".split())
+ def test_21(self, bash, functions, funcname, non_windows_testdir):
+ completion = assert_complete(
+ bash, "%s 'a\"b/" % funcname, cwd=non_windows_testdir
+ )
+ assert completion == "d'"
+
+ @pytest.mark.parametrize("funcname", "f f2".split())
+ def test_22(self, bash, functions, funcname, non_windows_testdir):
+ completion = assert_complete(
+ bash, r"%s '%s/a\b/" % (funcname, non_windows_testdir)
+ )
+ assert completion == "g'"
+
+ @pytest.mark.parametrize("funcname", "f f2".split())
+ def test_23(self, bash, functions, funcname, non_windows_testdir):
+ completion = assert_complete(
+ bash, r'%s "a\"b/' % funcname, cwd=non_windows_testdir
+ )
+ assert completion == 'd"'
+
+ @pytest.mark.parametrize("funcname", "f f2".split())
+ def test_24(self, bash, functions, funcname, non_windows_testdir):
+ completion = assert_complete(
+ bash, r'%s "a\\b/' % funcname, cwd=non_windows_testdir
+ )
+ assert completion == 'g"'
+
+ @pytest.mark.parametrize("funcname", "f f2".split())
+ def test_25(self, bash, functions, funcname):
+ completion = assert_complete(
+ bash, r'%s "a\b/' % funcname, cwd="_filedir"
+ )
+ assert completion == '\b\b\bb/e"'
+
+ @pytest.mark.parametrize("funcname", "f f2".split())
+ def test_26(self, bash, functions, funcname):
+ completion = assert_complete(
+ bash, r'%s "a\$b/' % funcname, cwd="_filedir"
+ )
+ assert completion == 'h"'
+
+ @pytest.mark.xfail(reason="TODO: non-ASCII issues with test suite?")
+ @pytest.mark.parametrize("funcname", "f f2".split())
+ def test_27(self, bash, functions, funcname, utf8_ctype):
+ completion = assert_complete(bash, "%s aé/" % funcname, cwd="_filedir")
+ assert completion == "g"
diff --git a/test/t/unit/test_unit_get_comp_words_by_ref.py b/test/t/unit/test_unit_get_comp_words_by_ref.py
index 1603bad6..b6498fa7 100644
--- a/test/t/unit/test_unit_get_comp_words_by_ref.py
+++ b/test/t/unit/test_unit_get_comp_words_by_ref.py
@@ -1,16 +1,17 @@
import pytest
-from conftest import assert_bash_exec, TestUnitBase
+from conftest import TestUnitBase, assert_bash_exec
@pytest.mark.bashcomp(
- cmd=None, ignore_env=r"^(\+(cur|prev)|[+-]COMP_(WORDS|CWORD|LINE|POINT))="
+ cmd=None,
+ ignore_env=r"^(\+(words|cword|cur|prev)|[+-]COMP_(WORDS|CWORD|LINE|POINT))=",
)
class TestUnitGetCompWordsByRef(TestUnitBase):
def _test(self, bash, *args, **kwargs):
assert_bash_exec(bash, "unset cur prev")
output = self._test_unit(
- "_get_comp_words_by_ref %s cur prev; echo $cur,$prev",
+ "_get_comp_words_by_ref %s cur prev; echo $cur,${prev-}",
bash,
*args,
**kwargs
@@ -18,7 +19,11 @@ class TestUnitGetCompWordsByRef(TestUnitBase):
return output.strip()
def test_1(self, bash):
- assert_bash_exec(bash, "_get_comp_words_by_ref cur >/dev/null")
+ assert_bash_exec(
+ bash,
+ "COMP_WORDS=() COMP_CWORD= COMP_POINT= COMP_LINE= "
+ "_get_comp_words_by_ref cur >/dev/null",
+ )
def test_2(self, bash):
"""a b|"""
@@ -165,3 +170,91 @@ class TestUnitGetCompWordsByRef(TestUnitBase):
"""a 'b&c|"""
output = self._test(bash, '(a "\'b&c")', 1, "a 'b&c", 6)
assert output == "'b&c,a"
+
+ def test_30(self, bash):
+ """a b| to all vars"""
+ assert_bash_exec(bash, "unset words cword cur prev")
+ output = self._test_unit(
+ "_get_comp_words_by_ref words cword cur prev%s; "
+ 'echo "${words[@]}",$cword,$cur,$prev',
+ bash,
+ "(a b)",
+ 1,
+ "a b",
+ 3,
+ )
+ assert output == "a b,1,b,a"
+
+ def test_31(self, bash):
+ """a b| to alternate vars"""
+ assert_bash_exec(bash, "unset words2 cword2 cur2 prev2")
+ output = self._test_unit(
+ "_get_comp_words_by_ref -w words2 -i cword2 -c cur2 -p prev2%s; "
+ 'echo $cur2,$prev2,"${words2[@]}",$cword2',
+ bash,
+ "(a b)",
+ 1,
+ "a b",
+ 3,
+ )
+ assert output == "b,a,a b,1"
+ assert_bash_exec(bash, "unset words2 cword2 cur2 prev2")
+
+ def test_32(self, bash):
+ """a b : c| with wordbreaks -= :"""
+ assert_bash_exec(bash, "unset words")
+ output = self._test_unit(
+ '_get_comp_words_by_ref -n : words%s; echo "${words[@]}"',
+ bash,
+ "(a b : c)",
+ 3,
+ "a b : c",
+ 7,
+ )
+ assert output == "a b : c"
+
+ def test_33(self, bash):
+ """a b: c| with wordbreaks -= :"""
+ assert_bash_exec(bash, "unset words")
+ output = self._test_unit(
+ '_get_comp_words_by_ref -n : words%s; echo "${words[@]}"',
+ bash,
+ "(a b : c)",
+ 3,
+ "a b: c",
+ 6,
+ )
+ assert output == "a b: c"
+
+ def test_34(self, bash):
+ """a b :c| with wordbreaks -= :"""
+ assert_bash_exec(bash, "unset words")
+ output = self._test_unit(
+ '_get_comp_words_by_ref -n : words%s; echo "${words[@]}"',
+ bash,
+ "(a b : c)",
+ 3,
+ "a b :c",
+ 6,
+ )
+ assert output == "a b :c"
+
+ def test_35(self, bash):
+ r"""a b\ :c| with wordbreaks -= :"""
+ assert_bash_exec(bash, "unset words")
+ output = self._test_unit(
+ '_get_comp_words_by_ref -n : words%s; echo "${words[@]}"',
+ bash,
+ "(a 'b ' : c)",
+ 3,
+ r"a b\ :c",
+ 7,
+ )
+ assert output == "a b :c"
+
+ def test_unknown_arg_error(self, bash):
+ with pytest.raises(AssertionError) as ex:
+ _ = assert_bash_exec(
+ bash, "_get_comp_words_by_ref dummy", want_output=True
+ )
+ ex.match("dummy.* unknown argument")
diff --git a/test/t/unit/test_unit_get_cword.py b/test/t/unit/test_unit_get_cword.py
index 3042dd29..0b56d163 100644
--- a/test/t/unit/test_unit_get_cword.py
+++ b/test/t/unit/test_unit_get_cword.py
@@ -1,17 +1,22 @@
+import pexpect
import pytest
-from conftest import assert_bash_exec, TestUnitBase
+from conftest import PS1, TestUnitBase, assert_bash_exec
@pytest.mark.bashcomp(
- cmd=None, ignore_env=r"^[+-]COMP_(WORDS|CWORD|LINE|POINT)="
+ cmd=None, ignore_env=r"^[+-](COMP_(WORDS|CWORD|LINE|POINT)|_scp_path_esc)="
)
class TestUnitGetCword(TestUnitBase):
def _test(self, *args, **kwargs):
return self._test_unit("_get_cword %s; echo", *args, **kwargs)
def test_1(self, bash):
- assert_bash_exec(bash, "_get_cword >/dev/null")
+ assert_bash_exec(
+ bash,
+ "COMP_WORDS=() COMP_CWORD= COMP_LINE= COMP_POINT= "
+ "_get_cword >/dev/null",
+ )
def test_2(self, bash):
"""a b| should return b"""
@@ -133,3 +138,17 @@ class TestUnitGetCword(TestUnitBase):
"""a 'b&c| should return 'b&c"""
output = self._test(bash, '(a "\'b&c")', 1, "a 'b&c", 6)
assert output == "'b&c"
+
+ @pytest.mark.xfail(reason="TODO: non-ASCII issues with test suite?")
+ def test_24(self, bash):
+ """Index shouldn't drop below 0"""
+ bash.send("scp ääää§ se\t\r\n")
+ got = bash.expect_exact(
+ [
+ "index: substring expression < 0",
+ PS1,
+ pexpect.EOF,
+ pexpect.TIMEOUT,
+ ]
+ )
+ assert got == 1
diff --git a/test/t/unit/test_unit_init_completion.py b/test/t/unit/test_unit_init_completion.py
index 64f3b511..64a5a790 100644
--- a/test/t/unit/test_unit_init_completion.py
+++ b/test/t/unit/test_unit_init_completion.py
@@ -1,6 +1,6 @@
import pytest
-from conftest import assert_bash_exec, TestUnitBase
+from conftest import TestUnitBase, assert_bash_exec, assert_complete
@pytest.mark.bashcomp(
@@ -13,12 +13,22 @@ class TestUnitInitCompletion(TestUnitBase):
"""Test environment non-pollution, detected at teardown."""
assert_bash_exec(
bash,
- "foo() { local cur prev words cword; _init_completion; }; "
+ "foo() { "
+ "local cur prev words cword "
+ "COMP_WORDS=() COMP_CWORD=0 COMP_LINE= COMP_POINT=0; "
+ "_init_completion; }; "
"foo; unset foo",
)
def test_2(self, bash):
output = self._test_unit(
- "_init_completion %s; echo $cur,$prev", bash, "(a)", 0, "a", 0
+ "_init_completion %s; echo $cur,${prev-}", bash, "(a)", 0, "a", 0
)
assert output == ","
+
+ @pytest.mark.parametrize("redirect", "> >> 2> < &>".split())
+ def test_redirect(self, bash, redirect):
+ completion = assert_complete(
+ bash, "%s " % redirect, cwd="shared/default"
+ )
+ assert all(x in completion for x in "foo bar".split())
diff --git a/test/t/unit/test_unit_known_hosts_real.py b/test/t/unit/test_unit_known_hosts_real.py
new file mode 100644
index 00000000..ac5205e1
--- /dev/null
+++ b/test/t/unit/test_unit_known_hosts_real.py
@@ -0,0 +1,158 @@
+from itertools import chain
+
+import pytest
+
+from conftest import assert_bash_exec
+
+
+@pytest.mark.bashcomp(
+ cmd=None,
+ ignore_env="^[+-](COMP(REPLY|_KNOWN_HOSTS_WITH_HOSTFILE)|OLDHOME)=",
+)
+class TestUnitKnownHostsReal:
+ @pytest.mark.parametrize(
+ "prefix,colon_flag,hostfile",
+ [("", "", True), ("", "", False), ("user@", "c", True)],
+ )
+ def test_basic(
+ self, bash, hosts, avahi_hosts, prefix, colon_flag, hostfile
+ ):
+ expected = (
+ "%s%s%s" % (prefix, x, ":" if colon_flag else "")
+ for x in chain(
+ hosts if hostfile else avahi_hosts,
+ # fixtures/_known_hosts_real/config
+ "gee hus jar #not-a-comment".split(),
+ # fixtures/_known_hosts_real/known_hosts
+ (
+ "doo",
+ "ike",
+ "jub",
+ "10.0.0.1",
+ "kyl",
+ "100.0.0.2",
+ "10.10.0.3",
+ "blah",
+ "fd00:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:5555",
+ "fe80::123:0xff:dead:beef%eth0",
+ "1111:2222:3333:4444:5555:6666:xxxx:abab",
+ "11xx:2222:3333:4444:5555:6666:xxxx:abab",
+ "::42",
+ ),
+ )
+ )
+ assert_bash_exec(
+ bash,
+ "unset -v COMP_KNOWN_HOSTS_WITH_HOSTFILE"
+ if hostfile
+ else "COMP_KNOWN_HOSTS_WITH_HOSTFILE=",
+ )
+ output = assert_bash_exec(
+ bash,
+ "_known_hosts_real -a%sF _known_hosts_real/config '%s'; "
+ r'printf "%%s\n" "${COMPREPLY[@]}"; unset COMPREPLY'
+ % (colon_flag, prefix),
+ want_output=True,
+ )
+ assert sorted(set(output.split())) == sorted(expected)
+
+ @pytest.mark.parametrize(
+ "family,result",
+ (
+ ("4", "127.0.0.1 localhost"),
+ ("6", "::1 localhost"),
+ ("46", "localhost"),
+ ),
+ )
+ def test_ip_filtering(self, bash, family, result):
+ assert_bash_exec(
+ bash, "unset -v COMPREPLY COMP_KNOWN_HOSTS_WITH_HOSTFILE"
+ )
+ output = assert_bash_exec(
+ bash,
+ "COMP_KNOWN_HOSTS_WITH_HOSTFILE= "
+ "_known_hosts_real -%sF _known_hosts_real/localhost_config ''; "
+ r'printf "%%s\n" "${COMPREPLY[@]}"' % family,
+ want_output=True,
+ )
+ assert sorted(set(output.strip().split())) == sorted(result.split())
+
+ def test_consecutive_spaces(self, bash, hosts):
+ expected = hosts.copy()
+ # fixtures/_known_hosts_real/spaced conf
+ expected.extend("gee hus #not-a-comment".split())
+ # fixtures/_known_hosts_real/known_hosts2
+ expected.extend("two two2 two3 two4".split())
+ # fixtures/_known_hosts_/spaced known_hosts
+ expected.extend("doo ike".split())
+
+ output = assert_bash_exec(
+ bash,
+ "unset -v COMPREPLY COMP_KNOWN_HOSTS_WITH_HOSTFILE; "
+ "_known_hosts_real -aF '_known_hosts_real/spaced conf' ''; "
+ r'printf "%s\n" "${COMPREPLY[@]}"',
+ want_output=True,
+ )
+ assert sorted(set(output.strip().split())) == sorted(expected)
+
+ def test_files_starting_with_tilde(self, bash, hosts):
+ expected = hosts.copy()
+ # fixtures/_known_hosts_real/known_hosts2
+ expected.extend("two two2 two3 two4".split())
+ # fixtures/_known_hosts_real/known_hosts3
+ expected.append("three")
+ # fixtures/_known_hosts_real/known_hosts4
+ expected.append("four")
+
+ assert_bash_exec(bash, 'OLDHOME="$HOME"; HOME="%s"' % bash.cwd)
+ output = assert_bash_exec(
+ bash,
+ "unset -v COMPREPLY COMP_KNOWN_HOSTS_WITH_HOSTFILE; "
+ "_known_hosts_real -aF _known_hosts_real/config_tilde ''; "
+ r'printf "%s\n" "${COMPREPLY[@]}"',
+ want_output=True,
+ )
+ assert_bash_exec(bash, 'HOME="$OLDHOME"')
+ assert sorted(set(output.strip().split())) == sorted(expected)
+
+ def test_included_configs(self, bash, hosts):
+ expected = hosts.copy()
+ # fixtures/_known_hosts_real/config_include_recursion
+ expected.append("recursion")
+ # fixtures/_known_hosts_real/.ssh/config_relative_path
+ expected.append("relative_path")
+ # fixtures/_known_hosts_real/.ssh/config_asterisk_*
+ expected.extend("asterisk_1 asterisk_2".split())
+ # fixtures/_known_hosts_real/.ssh/config_question_mark
+ expected.append("question_mark")
+
+ assert_bash_exec(
+ bash, 'OLDHOME="$HOME"; HOME="%s/_known_hosts_real"' % bash.cwd
+ )
+ output = assert_bash_exec(
+ bash,
+ "unset -v COMPREPLY COMP_KNOWN_HOSTS_WITH_HOSTFILE; "
+ "_known_hosts_real -aF _known_hosts_real/config_include ''; "
+ r'printf "%s\n" "${COMPREPLY[@]}"',
+ want_output=True,
+ )
+ assert_bash_exec(bash, 'HOME="$OLDHOME"')
+ assert sorted(set(output.strip().split())) == sorted(expected)
+
+ def test_no_globbing(self, bash):
+ assert_bash_exec(
+ bash, 'OLDHOME="$HOME"; HOME="%s/_known_hosts_real"' % bash.cwd
+ )
+ output = assert_bash_exec(
+ bash,
+ "cd _known_hosts_real; "
+ "unset -v COMPREPLY COMP_KNOWN_HOSTS_WITH_HOSTFILE; "
+ "_known_hosts_real -aF config ''; "
+ r'printf "%s\n" "${COMPREPLY[@]}"; '
+ "cd - &>/dev/null",
+ want_output=True,
+ )
+ assert_bash_exec(bash, 'HOME="$OLDHOME"')
+ completion = sorted(set(output.strip().split()))
+ assert "gee" in completion
+ assert "gee-filename-canary" not in completion
diff --git a/test/t/unit/test_unit_longopt.py b/test/t/unit/test_unit_longopt.py
index ac0ac836..c5488e34 100644
--- a/test/t/unit/test_unit_longopt.py
+++ b/test/t/unit/test_unit_longopt.py
@@ -11,6 +11,8 @@ class TestUnitLongopt:
def functions(self, request, bash):
assert_bash_exec(bash, "_grephelp() { cat _longopt/grep--help.txt; }")
assert_bash_exec(bash, "complete -F _longopt _grephelp")
+ assert_bash_exec(bash, "_various() { cat _longopt/various.txt; }")
+ assert_bash_exec(bash, "complete -F _longopt _various")
@pytest.mark.complete("_grephelp --")
def test_1(self, functions, completion):
@@ -32,3 +34,19 @@ class TestUnitLongopt:
assert completion
assert any(x.endswith("=") for x in completion)
assert any(not x.endswith("=") for x in completion)
+
+ @pytest.mark.complete("_various --")
+ def test_no_dashdashdash(self, functions, completion):
+ assert all(not x.startswith("---") for x in completion)
+
+ @pytest.mark.complete("_various --")
+ def test_no_trailingdash(self, functions, completion):
+ assert all(not x.endswith("-") for x in completion)
+
+ @pytest.mark.complete("_various --")
+ def test_underscore(self, functions, completion):
+ assert "--foo_bar" in completion
+
+ @pytest.mark.complete("_various --")
+ def test_equals(self, functions, completion):
+ assert "--foo=" in completion
diff --git a/test/t/unit/test_unit_quote.py b/test/t/unit/test_unit_quote.py
index e9f81c2d..b280bd68 100644
--- a/test/t/unit/test_unit_quote.py
+++ b/test/t/unit/test_unit_quote.py
@@ -1,6 +1,6 @@
import pytest
-from conftest import assert_bash_exec, TestUnitBase
+from conftest import TestUnitBase, assert_bash_exec
@pytest.mark.bashcomp(cmd=None)
diff --git a/test/t/unit/test_unit_quote_readline.py b/test/t/unit/test_unit_quote_readline.py
new file mode 100644
index 00000000..e2b437e3
--- /dev/null
+++ b/test/t/unit/test_unit_quote_readline.py
@@ -0,0 +1,15 @@
+import pytest
+
+from conftest import assert_bash_exec
+
+
+@pytest.mark.bashcomp(cmd=None)
+class TestUnitQuoteReadline:
+ def test_exec(self, bash):
+ assert_bash_exec(bash, "quote_readline '' >/dev/null")
+
+ def test_env_non_pollution(self, bash):
+ """Test environment non-pollution, detected at teardown."""
+ assert_bash_exec(
+ bash, "foo() { quote_readline meh >/dev/null; }; foo; unset foo"
+ )
diff --git a/test/t/unit/test_unit_variables.py b/test/t/unit/test_unit_variables.py
index dd7a4219..d62bc4a4 100644
--- a/test/t/unit/test_unit_variables.py
+++ b/test/t/unit/test_unit_variables.py
@@ -18,11 +18,11 @@ class TestUnitVariables:
@pytest.mark.complete(": $___v")
def test_simple_variable_name(self, functions, completion):
- assert completion == "$___var".split()
+ assert completion == "ar"
@pytest.mark.complete(": ${assoc1[")
def test_single_array_index(self, functions, completion):
- assert completion == "${assoc1[idx]}".split()
+ assert completion == "idx]}"
@pytest.mark.complete(": ${assoc2[")
def test_multiple_array_indexes(self, functions, completion):
@@ -30,12 +30,12 @@ class TestUnitVariables:
@pytest.mark.complete(": ${assoc1[bogus]")
def test_closing_curly_after_square(self, functions, completion):
- assert completion == "${assoc1[bogus]}".split()
+ assert completion == "}"
@pytest.mark.complete(": ${assoc1[@")
def test_closing_brackets_after_at(self, functions, completion):
- assert completion == "${assoc1[@]}".split()
+ assert completion == "]}"
@pytest.mark.complete(": ${#___v")
def test_hash_prefix(self, functions, completion):
- assert completion == "${#___var}".split()
+ assert completion == "ar}"
diff --git a/test/t/unit/test_unit_xinetd_services.py b/test/t/unit/test_unit_xinetd_services.py
new file mode 100644
index 00000000..7a90cb7f
--- /dev/null
+++ b/test/t/unit/test_unit_xinetd_services.py
@@ -0,0 +1,22 @@
+import pytest
+
+from conftest import assert_bash_exec
+
+
+@pytest.mark.bashcomp(cmd=None, ignore_env=r"^\+COMPREPLY=")
+class TestUnitXinetdServices:
+ def test_direct(self, bash):
+ assert_bash_exec(bash, "_xinetd_services >/dev/null")
+
+ def test_env_non_pollution(self, bash):
+ """Test environment non-pollution, detected at teardown."""
+ assert_bash_exec(bash, "foo() { _xinetd_services; }; foo; unset foo")
+
+ def test_basic(self, bash):
+ output = assert_bash_exec(
+ bash,
+ "foo() { local BASHCOMP_XINETDDIR=$PWD/shared/bin;unset COMPREPLY; "
+ '_xinetd_services; printf "%s\\n" "${COMPREPLY[@]}"; }; foo; unset foo',
+ want_output=True,
+ )
+ assert sorted(output.split()) == ["arp", "ifconfig"]
diff --git a/test/test-cmd-list.txt b/test/test-cmd-list.txt
new file mode 100644
index 00000000..eb8398e0
--- /dev/null
+++ b/test/test-cmd-list.txt
@@ -0,0 +1,687 @@
+2to3
+7z
+a2ps
+a2x
+abook
+aclocal
+acpi
+acroread
+adb
+add_members
+alias
+alpine
+animate
+ant
+apache2ctl
+appdata-validate
+apt-build
+apt-cache
+apt-get
+aptitude
+arch
+arp
+arping
+arpspoof
+asciidoc
+aspell
+autoconf
+autoheader
+automake
+autoreconf
+autorpm
+autoscan
+autossh
+autoupdate
+avctrl
+awk
+badblocks
+base64
+bash
+bc
+/bin/chroot
+bind
+/bin/rmdir
+bison
+bk
+bmake
+brctl
+bsdtar
+btdownloadcurses.py
+btdownloadgui.py
+btdownloadheadless.py
+bts
+bzip2
+c++
+cal
+cancel
+cardctl
+carton
+cat
+cc
+ccache
+ccze
+cd
+cdrecord
+cfagent
+cfrun
+chage
+change_pw
+check_db
+check_perms
+checksec
+chfn
+chgrp
+chkconfig
+chmod
+chown
+chpasswd
+chromium-browser
+chronyc
+chroot
+chrpath
+chsh
+ci
+ciptool
+civclient
+civserver
+cksfv
+cleanarch
+clisp
+clone_member
+co
+colordiff
+compare
+compgen
+complete
+composite
+config_list
+configure
+conjure
+convert
+cowsay
+cp
+cpan2dist
+cpio
+cppcheck
+createdb
+createuser
+crontab
+cryptsetup
+csplit
+curl
+cut
+cvs
+cvsps
+date
+dcop
+dd
+declare
+deja-dup
+desktop-file-validate
+df
+dfutool
+dhclient
+dict
+diff
+dir
+display
+dmesg
+dmypy
+dnssec-keygen
+dnsspoof
+dot
+dpkg
+dpkg-deb
+dpkg-query
+dpkg-reconfigure
+dpkg-source
+dropdb
+dropuser
+dselect
+dsniff
+du
+dumpdb
+dumpe2fs
+e2freefrag
+e2label
+ebtables
+ecryptfs-migrate-home
+eject
+enscript
+env
+eog
+etherwake
+ether-wake
+evince
+expand
+explodepkg
+export
+faillog
+fbgs
+fbi
+feh
+file
+filefrag
+file-roller
+filesnarf
+find
+find_member
+finger
+fio
+firefox
+flake8
+fmt
+fold
+freebsd-update
+freeciv
+freeciv-server
+function
+fusermount
+g++
+g4
+g77
+gcc
+gcj
+gcl
+gdb
+genaliases
+gendiff
+genisoimage
+geoiplookup
+getconf
+getent
+gkrellm
+gm
+gmplayer
+gnatmake
+gnokii
+gnome-mplayer
+gnome-screenshot
+gpasswd
+gpc
+gperf
+gpg
+gpg2
+gpgv
+gphoto2
+gprof
+grep
+groupadd
+groupdel
+groupmems
+groupmod
+growisofs
+grpck
+grub
+gssdp-discover
+gzip
+hciattach
+hciconfig
+hcitool
+hddtemp
+head
+hexdump
+hid2hci
+host
+hostname
+hping2
+hping3
+htop
+htpasswd
+hunspell
+hwclock
+iconv
+id
+identify
+idn
+ifdown
+ifstat
+iftop
+ifup
+import
+influx
+info
+inject
+inotifywait
+inotifywatch
+insmod
+installpkg
+interdiff
+invoke-rc.d
+ionice
+ip
+ipcalc
+iperf
+iperf3
+ipmitool
+ipsec
+iptables
+ipv6calc
+irb
+iscsiadm
+isort
+isql
+iwconfig
+iwlist
+iwpriv
+iwspy
+jar
+jarsigner
+java
+javac
+javadoc
+javaws
+jpegoptim
+jps
+jq
+jshint
+jsonschema
+json_xs
+k3b
+kcov
+kdvi
+kill
+killall
+kldload
+kldunload
+koji
+kpdf
+kplayer
+ktutil
+l2ping
+larch
+lastlog
+ld
+ldapadd
+ldapcompare
+ldapdelete
+ldapmodrdn
+ldappasswd
+ldapsearch
+ldapvi
+ldapwhoami
+ldd
+less
+lftp
+lftpget
+lilo
+links
+lintian
+lintian-info
+lisp
+list_admins
+list_lists
+list_members
+list_owners
+ln
+locale-gen
+look
+lpq
+lpr
+lrzip
+ls
+lsof
+lspci
+lsscsi
+lsusb
+lua
+luac
+luseradd
+luserdel
+lusermod
+lvchange
+lvcreate
+lvdisplay
+lvextend
+lvm
+lvmdiskscan
+lvreduce
+lvremove
+lvrename
+lvresize
+lvs
+lvscan
+lz4
+lzip
+lzma
+lzop
+m4
+macof
+mailmanctl
+mailsnarf
+make
+makepkg
+man
+mc
+mcrypt
+md5sum
+mdadm
+mdecrypt
+mdtool
+medusa
+mencoder
+mii-diag
+mii-tool
+minicom
+mkdir
+mkfifo
+mkinitrd
+mkisofs
+mknod
+mktemp
+mmsitepass
+mock
+modinfo
+modprobe
+module
+mogrify
+monodevelop
+montage
+mount
+mplayer
+mr
+msgsnarf
+msynctool
+mtx
+munindoc
+munin-node-configure
+munin-run
+mussh
+mutt
+muttng
+mv
+mypy
+mysql
+mysqladmin
+nc
+ncftp
+nethogs
+netstat
+newgrp
+newlist
+newusers
+ngrep
+nl
+nm
+nmap
+nmcli
+nproc
+nslookup
+nsupdate
+ntpdate
+objcopy
+objdump
+od
+oggdec
+op
+openssl
+opera
+optipng
+p4
+pack200
+passwd
+paste
+patch
+pdftotext
+perl
+perlcritic
+perldoc
+perltidy
+pgrep
+phing
+pidof
+pine
+pinfo
+ping
+pkgadd
+pkg-config
+pkg_deinstall
+pkg_delete
+pkg-get
+pkg_info
+pkgrm
+pkgtool
+pkgutil
+pkill
+plague-client
+pm-hibernate
+pm-is-supported
+pm-powersave
+pngfix
+portinstall
+portsnap
+portupgrade
+postcat
+postconf
+postfix
+postmap
+postsuper
+povray
+pr
+prelink
+printenv
+protoc
+psql
+ptx
+puppet
+pushd
+pv
+pvchange
+pvcreate
+pvdisplay
+pvmove
+pvremove
+pvs
+pvscan
+pwck
+pwd
+pwdx
+pwgen
+pycodestyle
+pydoc
+pydocstyle
+pyflakes
+pylint
+pylint-3
+pytest
+python
+python3
+pyvenv
+qemu
+qrunner
+querybts
+quota
+quotacheck
+quotaon
+radvdump
+rcs
+rcsdiff
+rdesktop
+rdict
+readelf
+readonly
+remove_members
+removepkg
+renice
+repomanage
+reportbug
+reptyr
+resolvconf
+rfcomm
+rfkill
+ri
+rlog
+rm
+rmdir
+rmlist
+rmmod
+route
+rpcdebug
+rpm
+rpm2tgz
+rpmbuild
+rrdtool
+rsync
+rtcwake
+runuser
+sbcl
+sbcl-mt
+sbopkg
+scp
+screen
+scrub
+sdptool
+secret-tool
+sed
+seq
+service
+set
+setquota
+sftp
+sh
+sha1sum
+shar
+shellcheck
+sitecopy
+slackpkg
+slapt-get
+slapt-src
+smartctl
+smbcacls
+smbclient
+smbcquotas
+smbget
+smbpasswd
+smbtar
+smbtree
+snownews
+sort
+split
+spovray
+sqlite3
+ss
+ssh
+ssh-add
+ssh-copy-id
+sshfs
+ssh-keygen
+sshmitm
+sshow
+strace
+stream
+strings
+strip
+su
+sudo
+sum
+svcadm
+svk
+svn
+svnadmin
+svnlook
+synclient
+sync_members
+sysbench
+sysctl
+tac
+tail
+tar
+tcpdump
+tcpkill
+tcpnice
+tee
+texindex
+tightvncviewer
+time
+timeout
+tipc
+totem
+touch
+tox
+tr
+tracepath
+tshark
+tsig-keygen
+tune2fs
+udevadm
+ulimit
+umount
+unace
+uname
+unexpand
+uniq
+units
+unpack200
+unrar
+unset
+unshunt
+update-alternatives
+update-rc.d
+upgradepkg
+urlsnarf
+uscan
+useradd
+userdel
+usermod
+valgrind
+vdir
+vgcfgbackup
+vgcfgrestore
+vgchange
+vgck
+vgconvert
+vgcreate
+vgdisplay
+vgexport
+vgextend
+vgimport
+vgmerge
+vgmknodes
+vgreduce
+vgremove
+vgrename
+vgs
+vgscan
+vgsplit
+vi
+vipw
+vmstat
+vncviewer
+vpnc
+watch
+wc
+webmitm
+wget
+who
+wine
+withlist
+wodim
+wol
+write
+wsimport
+wtf
+wvdial
+xdg-mime
+xdg-settings
+xfreerdp
+xgamma
+xm
+xmllint
+xmlwf
+xmms
+xmodmap
+xpovray
+xrandr
+xrdb
+xsltproc
+xvfb-run
+xvnc4viewer
+xxd
+xz
+xzdec
+ypcat
+ypmatch
+yum
+yum-arch
+zopfli
+zopflipng
diff --git a/test/unit/__expand_tilde_by_ref.exp b/test/unit/__expand_tilde_by_ref.exp
deleted file mode 100644
index 5569fe37..00000000
--- a/test/unit/__expand_tilde_by_ref.exp
+++ /dev/null
@@ -1,65 +0,0 @@
-# @param string $out Reference to variable to hold value of bash environment
-# variable $HOME.
-proc setup {home user} {
- upvar $home _home
- upvar $user _user
- save_env
- assert_bash_exec {echo "$HOME"} {} /@ _home
- set _home [string trim $_home]
- assert_bash_exec {id -un 2>/dev/null || echo "$USER"} {} /@ _user
- set _user [string trim $_user]
-}
-
-
-proc teardown {} {
- assert_env_unmodified {
- /var=/d
- }
-}
-
-
-setup home user
-
-
-set test "~user should return $home"
-set cmd [format {var="~%s"; __expand_tilde_by_ref var; printf "%%s\n" "$var"} $user]
-assert_bash_list "$home" $cmd $test
-sync_after_int
-
-set test "~/foo should return $home/foo"
-set cmd {var='~/foo'; __expand_tilde_by_ref var; printf "%s\n" "$var"}
-assert_bash_list "$home/foo" $cmd $test
-sync_after_int
-
-set test "~user/bar should return $home/bar"
-set cmd [format {var="~%s/bar"; __expand_tilde_by_ref var; printf "%%s\n" "$var"} $user]
-assert_bash_list "$home/bar" $cmd $test
-sync_after_int
-
-set test "~user/\$HOME should return $home/\$HOME"
-set cmd [format {var="~%s/\$HOME"; __expand_tilde_by_ref var; printf "%%s\n" "$var"} $user]
-assert_bash_list "$home/\$HOME" $cmd $test
-sync_after_int
-
-set test "'~user/a b' should return '$home/a b'"
-set cmd [format {var="~%s/a b"; __expand_tilde_by_ref var; printf "%%s\n" "$var"} $user]
-assert_bash_list [list [format {%s/a b} $home]] $cmd $test
-sync_after_int
-
-set test "~user/* should return $home/*"
-set cmd [format {var="~%s/*"; __expand_tilde_by_ref var; printf "%%s\n" "$var"} $user]
-assert_bash_list "$home/\*" $cmd $test
-sync_after_int
-
-set test "'~user;echo hello' should return '~user;echo hello' (not expanded)"
-set cmd [format {var="~%s;echo hello"; __expand_tilde_by_ref var; printf "%%s\n" "$var"} $user]
-assert_bash_list [format "~%s;echo hello" $user] $cmd $test
-sync_after_int
-
-set test "'~user/a;echo hello' should return '$home/a;echo hello'"
-set cmd [format {var="~%s/a;echo hello"; __expand_tilde_by_ref var; printf "%%s\n" "$var"} $user]
-assert_bash_list "$home/a;echo hello" $cmd $test
-sync_after_int
-
-
-teardown
diff --git a/test/unit/_expand.exp b/test/unit/_expand.exp
deleted file mode 100644
index 59dbed58..00000000
--- a/test/unit/_expand.exp
+++ /dev/null
@@ -1,33 +0,0 @@
-proc setup {home user} {
- upvar $home _home
- upvar $user _user
- save_env
- assert_bash_exec {echo "$HOME"} {} /@ _home
- set _home [string trim $_home]
- assert_bash_exec {id -un 2>/dev/null || echo "$USER"} {} /@ _user
- set _user [string trim $_user]
-}
-
-proc teardown {} {
- assert_env_unmodified {
- /COMPREPLY=/d
- /cur=/d
- }
-}
-
-
-setup home user
-
-
-set test "~$user should set $home to COMPREPLY"
-set cmd [format {cur="~%s" ; _expand ; printf "%%s\n" "$COMPREPLY"} $user]
-assert_bash_list "$home" $cmd $test
-sync_after_int
-
-set test "~$user/a should set $home/a to cur"
-set cmd [format {cur="~%s/a" ; _expand ; printf "%%s\n" "$cur"} $user]
-assert_bash_list "$home/a" $cmd $test
-sync_after_int
-
-
-teardown
diff --git a/test/unit/_filedir.exp b/test/unit/_filedir.exp
deleted file mode 100644
index 1de49504..00000000
--- a/test/unit/_filedir.exp
+++ /dev/null
@@ -1,124 +0,0 @@
-proc setup {} {
- assert_bash_exec {unset COMPREPLY cur}
- assert_bash_exec {unset -f _f}
- save_env
- # Declare bash completion function `_f'
- assert_bash_exec { \
- _f() { local cur=$(_get_cword); unset COMPREPLY; _filedir; }; \
- complete -F _f f \
- }
- # Declare bash completion function `_f2' with `-o filenames' active.
- assert_bash_exec { \
- complete -F _f -o filenames f2 \
- }
- # Create directories `a"b', `a*b', and `a\b' only when not running on
- # Cygwin/Windows (`"', `*', or `\' aren't allowed in filenames there)
- if {! [is_cygwin]} {
- # Create directory `a"b'
- assert_bash_exec {(cd $TESTDIR/tmp && [ ! -d a\"b ] && mkdir a\"b && touch a\"b/d || true)}
- # Create directory `a*b'
- assert_bash_exec {(cd $TESTDIR/tmp && [ ! -d a\*b ] && mkdir a\*b && touch a\*b/j || true)}
- # Create directory `a\b'
- assert_bash_exec {(cd $TESTDIR/tmp && [ ! -d a\\b ] && mkdir a\\b && touch a\\b/g || true)}
- }
-}
-
-
-proc teardown {} {
- if {! [is_cygwin]} {
- assert_bash_exec {(cd $TESTDIR/tmp && rm -- a\"b/d && rmdir a\"b/ || true)}
- assert_bash_exec {(cd $TESTDIR/tmp && rm -- a\\b/g && rmdir a\\b/ || true)}
- assert_bash_exec {(cd $TESTDIR/tmp && rm -- a\*b/j && rmdir a\*b/ || true)}
- }
- assert_bash_exec {unset COMPREPLY cur}
- assert_bash_exec {unset -f _f}
- assert_bash_exec {complete -r f}
- assert_env_unmodified {
- /OLDPWD/d
- /OLD_CTYPE/d
- }
-}
-
-
-setup
-
-
-foreach name {f f2} {
-
- set test "completing $name a\\\$b/ should return h"
- if {[info exists ::env(CI)] && [info exists ::env(DIST)] && $::env(DIST) == "centos6"} {
- xfail $test
- } else {
- set cmd "$name a\\\$b/"
- assert_complete_dir h $cmd "$::srcdir/fixtures/_filedir" $test
- sync_after_int
- }
-
- if {! [is_cygwin]} { # Illegal characters in file/dir names
- set test "completing $name a\\\"b/ should return d"; #"
- set cmd "$name a\\\"b/"; #"
- assert_complete_dir d $cmd "$TESTDIR/tmp" $test
- sync_after_int
-
- set test "completing $name a\\\\b/ should return g"
- set cmd "$name a\\\\b/"
- assert_complete_dir g $cmd "$TESTDIR/tmp" $test
- sync_after_int
- }
-
- if {! [is_cygwin]} { # Illegal characters in file/dir names
- set cmd "$name 'a\"b/"; #"
- assert_complete_dir {d'} $cmd "$TESTDIR/tmp"
- sync_after_int
-
- set cmd "$name '$TESTDIR/tmp/a\\b/"
- assert_complete_dir {g'} $cmd "$TESTDIR/tmp"
- sync_after_int
- }
-
- if {! [is_cygwin]} { # Illegal characters in file/dir names
- set cmd "$name \"a\\\"b/"; #"
- assert_complete_dir {d"} $cmd "$TESTDIR/tmp"; #"
- sync_after_int
- }
-
- if {[info exists ::env(CI)] && [info exists ::env(DIST)] && $::env(DIST) == "centos6"} {
- xfail "$name \"a\\\$b/ should show completions"
- } else {
- set cmd "$name \"a\\\$b/"; #"
- assert_complete_dir {h"} $cmd "$::srcdir/fixtures/_filedir"; #"
- sync_after_int
- }
-
- set cmd "$name \"a\\b/"; #"
- assert_complete_dir "\b\b\bb/e\\\"" $cmd "$::srcdir/fixtures/_filedir"
- sync_after_int
-
- set cmd "$name \"a\\\\b/"; #"
- assert_complete_dir {g"} $cmd "$TESTDIR/tmp"; #"
- sync_after_int
-
- set cmd "$name \\\[x"
- assert_complete_dir {\[x\]} $cmd "$::srcdir/fixtures/_filedir/brackets"
- sync_after_int
-
-}; # foreach
-
-set test "completing f aé should return g"
-# Execute this test only with LC_CTYPE matching *UTF-8*
-# See also: http://www.mail-archive.com/bash-completion-devel\
-# @lists.alioth.debian.org/msg02265.html
-# Don't execute this test on expect-5.44 cause it will segfault
-# See also: Alioth #312792
-if {
- [string first "UTF-8" $::LC_CTYPE] != -1 &&
- [string first 5.44 [exp_version]] != 0
-} {
- assert_complete_dir g "f aé/" "$::srcdir/fixtures/_filedir"
-} else {
- unsupported "$test"
-}
-sync_after_int
-
-
-teardown
diff --git a/test/unit/_get_comp_words_by_ref.exp b/test/unit/_get_comp_words_by_ref.exp
deleted file mode 100644
index a0e1886b..00000000
--- a/test/unit/_get_comp_words_by_ref.exp
+++ /dev/null
@@ -1,91 +0,0 @@
-proc setup {} {
- assert_bash_exec {unset COMP_CWORD COMP_LINE COMP_POINT COMP_WORDS}
- save_env
-}
-
-
-proc teardown {} {
- assert_bash_exec { \
- unset COMP_CWORD COMP_LINE COMP_POINT COMP_WORDS cur prev words cword \
- cur2 prev2 words2 cword2 \
- }
- # Delete 'COMP_WORDBREAKS' occupying two lines
- assert_env_unmodified {
- /COMP_WORDBREAKS=/{N
- d
- }
- }
-}
-
-
-setup
-
-
-# See also ./lib/completions/alias.exp. Here `_get_cword' is actually tested
-# by moving the cursor left into the current word.
-
-set test {unknown argument should raise error}
-set cmd {_get_comp_words_by_ref dummy}
-assert_bash_list {"bash_completion: _get_comp_words_by_ref: `dummy': unknown argument"} $cmd $test
-sync_after_int
-
-set test "a b| to all vars"; # | = cursor position
-set cmd {COMP_WORDS=(a b); COMP_CWORD=1; COMP_LINE='a b'; COMP_POINT=3}
-assert_bash_exec $cmd
-set cmd { \
- _get_comp_words_by_ref words cword prev cur; echo "${words[@]} $cword $cur $prev" \
-}
-assert_bash_list {"a b 1 b a"} $cmd $test
-sync_after_int
-
-set test "a b| to alternate vars"; # | = cursor position
-set cmd {COMP_WORDS=(a b); COMP_CWORD=1; COMP_LINE='a b'; COMP_POINT=3;}
-assert_bash_exec $cmd
-set cmd {_get_comp_words_by_ref -c cur2 -p prev2 -w words2 -i cword2}
-assert_bash_exec $cmd
-set cmd {echo "$cur2 $prev2 ${words2[@]} $cword2"}
-assert_bash_list {"b a a b 1"} $cmd $test
-sync_after_int
-
-set test "a b| to alternate vars"; # | = cursor position
-set cmd {COMP_WORDS=(a b); COMP_CWORD=1; COMP_LINE='a b'; COMP_POINT=3;}
-assert_bash_exec $cmd
-set cmd {_get_comp_words_by_ref -c cur2 -p prev2 -w words2 -i cword2}
-assert_bash_exec $cmd
-set cmd {echo "$cur2 $prev2 ${words2[@]} $cword2"}
-assert_bash_list {"b a a b 1"} $cmd $test
-sync_after_int
-
-set test {a b : c| with WORDBREAKS -= :}; # | = cursor position
-set cmd {COMP_WORDS=(a b : c); COMP_CWORD=3; COMP_LINE='a b : c'; COMP_POINT=7}
-assert_bash_exec $cmd $test
-set cmd {_get_comp_words_by_ref -n : words; echo "${words[@]}"}
-assert_bash_list {"a b : c"} $cmd $test
-sync_after_int
-
-set test {a b: c| with WORDBREAKS -= :}; # | = cursor position
-set cmd {COMP_WORDS=(a b : c); COMP_CWORD=3}
-append cmd {; COMP_LINE='a b: c'; COMP_POINT=6}
-assert_bash_exec $cmd $test
-set cmd {_get_comp_words_by_ref -n : words; echo "${words[@]}"}
-assert_bash_list {"a b: c"} $cmd $test
-sync_after_int
-
-set test {a b :c| with WORDBREAKS -= :}; # | = cursor position
-set cmd {COMP_WORDS=(a b : c); COMP_CWORD=3}
-append cmd {; COMP_LINE='a b :c'; COMP_POINT=6}
-assert_bash_exec $cmd $test
-set cmd {_get_comp_words_by_ref -n : words; echo "${words[@]}"}
-assert_bash_list {"a b :c"} $cmd $test
-sync_after_int
-
-set test {a b\ :c| with WORDBREAKS -= :}; # | = cursor position
-set cmd {COMP_WORDS=(a "b\\ " : c); COMP_CWORD=3}
-append cmd {; COMP_LINE='a b\ :c'; COMP_POINT=7}
-assert_bash_exec $cmd $test
-set cmd {_get_comp_words_by_ref -n : words; echo "${words[@]}"}
-assert_bash_list {a "b\\ :c"} $cmd $test
-sync_after_int
-
-
-teardown
diff --git a/test/unit/_get_cword.exp b/test/unit/_get_cword.exp
deleted file mode 100644
index 91bcb44e..00000000
--- a/test/unit/_get_cword.exp
+++ /dev/null
@@ -1,37 +0,0 @@
-proc setup {} {
- assert_bash_exec {unset COMP_CWORD COMP_LINE COMP_POINT COMP_WORDS}
- save_env
-}
-
-
-proc teardown {} {
- assert_bash_exec {unset COMP_CWORD COMP_LINE COMP_POINT COMP_WORDS}
- # Delete 'COMP_WORDBREAKS' occupying two lines
- assert_env_unmodified {
- /COMP_WORDBREAKS=/{N
- d
- }
- /_scp_path_esc=/d
- }
-}
-
-
-setup
-
-
-# See also ./lib/completions/alias.exp. Here `_get_cword' is actually tested
-# by moving the cursor left into the current word.
-
-set test "index shouldn't drop below 0"
-set dir $::srcdir/fixtures/_get_cword
-set cmd "scp"
-send "$cmd ääää§ se\t\r\n"
-expect {
- -re "index: substring expression < 0" { fail "$test" }
- -re /@ { pass "$test" }
- default { unresolved "$test" }
-}
-sync_after_int
-
-
-teardown
diff --git a/test/unit/_known_hosts_real.exp b/test/unit/_known_hosts_real.exp
deleted file mode 100644
index 01b09b6b..00000000
--- a/test/unit/_known_hosts_real.exp
+++ /dev/null
@@ -1,171 +0,0 @@
-proc setup {} {
- # NOTE: Changing dir to $SRCDIR is necessary because file locations in the
- # ssh config files (e.g. UserKnownHostsFile) are relative to $SRCDIR.
- assert_bash_exec {cd $SRCDIR}
- save_env
-}
-
-
-proc teardown {} {
- assert_env_unmodified {
- /COMPREPLY=/d
- /OLDHOME=/d
- }
- assert_bash_exec {cd $TESTDIR}
-}
-
-
-setup
-
-
-set test "Hosts should be put in COMPREPLY"
-set hosts [get_hosts -unsorted]
-# Hosts `gee', `hus' and `jar' are defined in
-# ./fixtures/_known_hosts_real/config
-# doo, ike, jub, 10.0.0.1, kyl, 100.0.0.2, 10.10.0.3, blah, and bunch of IPv6
-# test cases in ./fixtures/_known_hosts_real/known_hosts
-lappend hosts blah doo gee hus ike jar jub kyl 10.0.0.1 100.0.0.2 10.10.0.3 fd00:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:5555 fe80::123:0xff:dead:beef%eth0 1111:2222:3333:4444:5555:6666:xxxx:abab 11xx:2222:3333:4444:5555:6666:xxxx:abab ::42
-set cmd {unset COMPREPLY; _known_hosts_real -aF fixtures/_known_hosts_real/config ''; echo_array COMPREPLY}
-assert_bash_list $hosts $cmd $test -sort
-sync_after_int
-
-set test "Hosts should have username prefix and colon suffix"
-set hosts [get_hosts -unsorted]
-# Hosts `gee', `hus' and `jar' are defined in
-# ./fixtures/_known_hosts_real/config
-# doo, ike, jub, 10.0.0.1, kyl, 100.0.0.2, 10.10.0.3, blah, and bunch of IPv6
-# test cases in ./fixtures/_known_hosts_real/known_hosts
-lappend hosts blah doo gee hus ike jar jub kyl 10.0.0.1 100.0.0.2 10.10.0.3 fd00:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:5555 fe80::123:0xff:dead:beef%eth0 1111:2222:3333:4444:5555:6666:xxxx:abab 11xx:2222:3333:4444:5555:6666:xxxx:abab ::42
-set hosts [lsort -ascii $hosts]
-set expected {}
-foreach host $hosts {
- lappend expected "user@$host:"
-}
-# Call _known_hosts
-set cmd {unset COMPREPLY; _known_hosts_real -acF fixtures/_known_hosts_real/config 'user@'; echo_array COMPREPLY}
-assert_bash_list $expected $cmd $test -sort
-sync_after_int
-
-set test "Files containing consecutive spaces should work"
-set hosts [get_hosts -unsorted]
-set hosts_orig $hosts
-# Hosts `gee' and `hus' are defined in
-#`./fixtures/_known_hosts_real/spaced conf'
-# Hosts `two*' are defined in ./fixtures/_known_hosts_real/known_hosts2
-lappend hosts gee hus two two2 two3 two4
-set hosts_config $hosts
-# Hosts `doo' and `ike' are defined in
-# `./fixtures/_known_hosts_/spaced known_hosts'
-lappend hosts doo ike
-set hosts [join [bash_sort $hosts ] "\\s+"]
-set hosts_orig [join [bash_sort $hosts_orig ] "\\s+"]
-set hosts_config [join [bash_sort $hosts_config] "\\s+"]
-# Call _known_hosts
-set cmd {unset COMPREPLY; _known_hosts_real -aF 'fixtures/_known_hosts_real/spaced conf' ''; echo_array COMPREPLY}
-send "$cmd\r"
-expect -ex "$cmd\r\n"
-expect {
- -re "^$hosts\r\n/@$" { pass "$test" }
- -re "^$hosts_orig\r\n/@$" { fail "$test (config file)" }
- -re "^$hosts_config\r\n/@$" { fail "$test (known hosts file)" }
- -re /@ { unresolved "$test at prompt" }
- default { unresolved "$test" }
-}
-sync_after_int
-
-set test "Files starting with tilde (~) should work"
-set hosts [get_hosts -unsorted]
-# Hosts `two*' are defined in ./fixtures/_known_hosts_real/known_hosts2
-# Host `three' is defined in ./fixtures/_known_hosts_real/known_hosts3
-# Host `four' is defined in ./fixtures/_known_hosts_real/known_hosts4
-lappend hosts two two2 two3 two4 three four
-set hosts [join [bash_sort $hosts] "\\s+"]
-# Setup environment
-set cmd {OLDHOME=$HOME; HOME=$SRCDIRABS}
-send "$cmd\r"
-expect -ex "$cmd\r\n/@"
-# Call _known_hosts
-set cmd {unset COMPREPLY; _known_hosts_real -aF fixtures/_known_hosts_real/config_tilde ''; echo_array COMPREPLY}
-send "$cmd\r"
-expect -ex "$cmd\r\n"
-expect {
- -re "^$hosts\r\n/@$" { pass "$test" }
- default { unresolved "$test" }
-}
-# Teardown environment
-set cmd {HOME=$OLDHOME}
-send "$cmd\r"
-expect -ex "$cmd\r\n/@"
-sync_after_int
-
-set test "Empty COMP_KNOWN_HOSTS_WITH_HOSTFILE should omit HOSTFILE"
-assert_bash_exec "COMP_KNOWN_HOSTS_WITH_HOSTFILE="
-set hosts [get_hosts_avahi]
-# Hosts `gee', `hus' and `jar' are defined in
-# ./fixtures/_known_hosts_real/config
-# doo, ike, jub, 10.0.0.1, kyl, 100.0.0.2, 10.10.0.3, blah, and bunch of IPv6
-# test cases in ./fixtures/_known_hosts_real/known_hosts
-lappend hosts blah doo gee hus ike jar jub kyl 10.0.0.1 100.0.0.2 10.10.0.3 fd00:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:5555 fe80::123:0xff:dead:beef%eth0 1111:2222:3333:4444:5555:6666:xxxx:abab 11xx:2222:3333:4444:5555:6666:xxxx:abab ::42
-# Call _known_hosts
-set cmd {unset COMPREPLY; _known_hosts_real -aF fixtures/_known_hosts_real/config ''; echo_array COMPREPLY}
-assert_bash_list $hosts $cmd $test -sort
-sync_after_int
-assert_bash_exec "unset -v COMP_KNOWN_HOSTS_WITH_HOSTFILE"
-sync_after_int
-
-set test "Included config files should work"
-set hosts [get_hosts -unsorted]
-# Host 'recursion' is defined in
-# ./fixtures/_known_hosts_real/config_include_recursion
-# Host 'relative_path' is defined in
-# ./fixtures/_known_hosts_real/.ssh/config_relative_path
-lappend hosts recursion relative_path
-set hosts [join [bash_sort $hosts] "\\s+"]
-# Setup environment
-# Redefined HOME to handle relative path inclusions on $HOME/.ssh
-set cmd {OLDHOME=$HOME; HOME="$SRCDIRABS/fixtures/_known_hosts_real"}
-send "$cmd\r"
-expect -ex "$cmd\r\n/@"
-# Call _known_hosts
-set cmd {unset COMPREPLY; _known_hosts_real -aF fixtures/_known_hosts_real/config_include ''; echo_array COMPREPLY}
-send "$cmd\r"
-expect -ex "$cmd\r\n"
-expect {
- -re "^$hosts\r\n/@$" { pass "$test" }
- default { unresolved "$test" }
-}
-# Teardown environment
-set cmd {HOME=$OLDHOME}
-send "$cmd\r"
-expect -ex "$cmd\r\n/@"
-sync_after_int
-
-set test "IPv6 filtering should work"
-set hosts "127.0.0.1 localhost"
-assert_bash_exec "COMP_KNOWN_HOSTS_WITH_HOSTFILE="
-set cmd {unset COMPREPLY; _known_hosts_real -4F fixtures/_known_hosts_real/localhost_config ''; echo_array COMPREPLY}
-assert_bash_list $hosts $cmd $test -sort
-sync_after_int
-assert_bash_exec "unset -v COMP_KNOWN_HOSTS_WITH_HOSTFILE"
-sync_after_int
-
-set test "IPv4 filtering should work"
-set hosts "::1 localhost"
-assert_bash_exec "COMP_KNOWN_HOSTS_WITH_HOSTFILE="
-set cmd {unset COMPREPLY; _known_hosts_real -6F fixtures/_known_hosts_real/localhost_config ''; echo_array COMPREPLY}
-assert_bash_list $hosts $cmd $test -sort
-sync_after_int
-assert_bash_exec "unset -v COMP_KNOWN_HOSTS_WITH_HOSTFILE"
-sync_after_int
-
-set test "IPv4+IPv6 filtering should work"
-set hosts "localhost"
-assert_bash_exec "COMP_KNOWN_HOSTS_WITH_HOSTFILE="
-set cmd {unset COMPREPLY; _known_hosts_real -46F fixtures/_known_hosts_real/localhost_config ''; echo_array COMPREPLY}
-assert_bash_list $hosts $cmd $test -sort
-sync_after_int
-assert_bash_exec "unset -v COMP_KNOWN_HOSTS_WITH_HOSTFILE"
-sync_after_int
-
-
-teardown
diff --git a/test/update-test-cmd-list b/test/update-test-cmd-list
new file mode 100755
index 00000000..115ae165
--- /dev/null
+++ b/test/update-test-cmd-list
@@ -0,0 +1,13 @@
+#!/bin/bash -eu
+
+mydir=$(
+ cd "$(dirname "$0")"
+ pwd
+)
+
+cat "$mydir"/t/test_*.py |
+ tr -d '\n' |
+ grep -Eo '@pytest.mark.complete(\([^)]*\))' |
+ sed -ne 's/^[^"]*"\\\?\([^_][^[:space:]"]*\)[[:space:]"].*/\1/p' |
+ sort -u \
+ >"$mydir"/test-cmd-list.txt