diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-15 16:24:27 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-15 16:24:27 +0000 |
commit | 6c18848a903eb3ee06dccd915859ce64195c257c (patch) | |
tree | ea0fe36eb5e6f40e0a1f765d44c4b0c0b2bfb089 /test/t | |
parent | Initial commit. (diff) | |
download | bash-completion-6c18848a903eb3ee06dccd915859ce64195c257c.tar.xz bash-completion-6c18848a903eb3ee06dccd915859ce64195c257c.zip |
Adding upstream version 1:2.11.upstream/1%2.11
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to '')
707 files changed, 12397 insertions, 0 deletions
diff --git a/test/t/Makefile.am b/test/t/Makefile.am new file mode 100644 index 0000000..801841f --- /dev/null +++ b/test/t/Makefile.am @@ -0,0 +1,698 @@ +SUBDIRS = unit + +EXTRA_DIST = \ + conftest.py \ + test_2to3.py \ + test_7z.py \ + test_a2ps.py \ + test_a2x.py \ + test_abook.py \ + test_aclocal.py \ + test_acpi.py \ + test_acroread.py \ + test_adb.py \ + test_add_members.py \ + test_alias.py \ + test_alpine.py \ + test_animate.py \ + test_ant.py \ + test_apache2ctl.py \ + test_appdata_validate.py \ + test_apt_build.py \ + test_apt_cache.py \ + test_apt_get.py \ + test_aptitude.py \ + test_arch.py \ + test_arp.py \ + test_arping.py \ + test_arpspoof.py \ + test_asciidoc.py \ + test_aspell.py \ + test_autoconf.py \ + test_autoheader.py \ + test_automake.py \ + test_autoreconf.py \ + test_autorpm.py \ + test_autoscan.py \ + test_autossh.py \ + test_autoupdate.py \ + test_avctrl.py \ + test_awk.py \ + test_badblocks.py \ + test_base64.py \ + test_bash.py \ + test_bc.py \ + test_bind.py \ + test_bison.py \ + test_bk.py \ + test_bmake.py \ + test_brctl.py \ + test_btdownloadcurses_py.py \ + test_btdownloadgui_py.py \ + test_btdownloadheadless_py.py \ + test_bts.py \ + test_bzip2.py \ + test_cal.py \ + test_cancel.py \ + test_cardctl.py \ + test_carton.py \ + test_cat.py \ + test_cc.py \ + test_ccache.py \ + test_ccze.py \ + test_cd.py \ + test_cdrecord.py \ + test_cfagent.py \ + test_cfrun.py \ + test_chage.py \ + test_change_pw.py \ + test_check_db.py \ + test_check_perms.py \ + test_checksec.py \ + test_chfn.py \ + test_chgrp.py \ + test_chkconfig.py \ + test_chmod.py \ + test_chown.py \ + test_chpasswd.py \ + test_chromium_browser.py \ + test_chronyc.py \ + test_chroot.py \ + test_chrpath.py \ + test_chsh.py \ + test_ci.py \ + test_ciptool.py \ + test_civclient.py \ + test_civserver.py \ + test_cksfv.py \ + test_cleanarch.py \ + test_clisp.py \ + test_clone_member.py \ + test_co.py \ + test_colordiff.py \ + test_compare.py \ + test_compgen.py \ + test_complete.py \ + test_composite.py \ + test_config_list.py \ + test_configure.py \ + test_conjure.py \ + test_convert.py \ + test_cowsay.py \ + test_cp.py \ + test_cpan2dist.py \ + test_cpio.py \ + test_cplusplus.py \ + test_cppcheck.py \ + test_createdb.py \ + test_createuser.py \ + test_crontab.py \ + test_cryptsetup.py \ + test_csplit.py \ + test_curl.py \ + test_cut.py \ + test_cvs.py \ + test_cvsps.py \ + test_date.py \ + test_dcop.py \ + test_dd.py \ + test_declare.py \ + test_deja_dup.py \ + test_desktop_file_validate.py \ + test_df.py \ + test_dfutool.py \ + test_dhclient.py \ + test_dict.py \ + test_diff.py \ + test_dir.py \ + test_display.py \ + test_dmesg.py \ + test_dmypy.py \ + test_dnssec_keygen.py \ + test_dnsspoof.py \ + 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 \ + test_dropuser.py \ + test_dselect.py \ + test_dsniff.py \ + test_du.py \ + test_dumpdb.py \ + test_dumpe2fs.py \ + test_e2freefrag.py \ + test_e2label.py \ + test_ebtables.py \ + test_ecryptfs_migrate_home.py \ + test_eject.py \ + test_enscript.py \ + test_env.py \ + test_eog.py \ + test_ether_wake.py \ + test_etherwake.py \ + test_evince.py \ + test_expand.py \ + test_explodepkg.py \ + test_export.py \ + test_faillog.py \ + test_fbgs.py \ + test_fbi.py \ + test_feh.py \ + test_file.py \ + test_file_roller.py \ + test_filefrag.py \ + test_filesnarf.py \ + test_find.py \ + test_find_member.py \ + test_finger.py \ + test_fio.py \ + test_firefox.py \ + test_flake8.py \ + test_fmt.py \ + test_fold.py \ + test_freebsd_update.py \ + test_freeciv.py \ + test_freeciv_server.py \ + test_function.py \ + test_fusermount.py \ + test_g4.py \ + test_g77.py \ + test_gcc.py \ + test_gcj.py \ + test_gcl.py \ + test_gdb.py \ + test_genaliases.py \ + test_gendiff.py \ + test_genisoimage.py \ + test_geoiplookup.py \ + test_getconf.py \ + test_getent.py \ + test_gkrellm.py \ + test_gm.py \ + test_gmplayer.py \ + test_gnatmake.py \ + test_gnokii.py \ + test_gnome_mplayer.py \ + test_gnome_screenshot.py \ + test_gpasswd.py \ + test_gpc.py \ + test_gperf.py \ + test_gpg.py \ + test_gpg2.py \ + test_gpgv.py \ + test_gphoto2.py \ + test_gplusplus.py \ + test_gprof.py \ + test_grep.py \ + test_groupadd.py \ + test_groupdel.py \ + test_groupmems.py \ + test_groupmod.py \ + test_growisofs.py \ + test_grpck.py \ + test_grub.py \ + test_gssdp_discover.py \ + test_gzip.py \ + test_hciattach.py \ + test_hciconfig.py \ + test_hcitool.py \ + test_hddtemp.py \ + test_head.py \ + test_hexdump.py \ + test_hid2hci.py \ + test_host.py \ + test_hostname.py \ + test_hping2.py \ + test_hping3.py \ + test_htop.py \ + test_htpasswd.py \ + test_hunspell.py \ + test_hwclock.py \ + test_iconv.py \ + test_id.py \ + test_identify.py \ + test_idn.py \ + test_ifdown.py \ + test_ifstat.py \ + test_iftop.py \ + test_ifup.py \ + test_import.py \ + test_influx.py \ + test_info.py \ + test_inject.py \ + test_inotifywait.py \ + test_inotifywatch.py \ + test_insmod.py \ + test_installpkg.py \ + test_interdiff.py \ + test_invoke_rc_d.py \ + test_ionice.py \ + test_ip.py \ + test_ipcalc.py \ + test_iperf.py \ + test_ipmitool.py \ + test_ipsec.py \ + test_iptables.py \ + test_ipv6calc.py \ + test_irb.py \ + test_iscsiadm.py \ + test_isort.py \ + test_isql.py \ + test_iwconfig.py \ + test_iwlist.py \ + test_iwpriv.py \ + test_iwspy.py \ + test_jar.py \ + test_jarsigner.py \ + test_java.py \ + test_javac.py \ + test_javadoc.py \ + test_javaws.py \ + test_jpegoptim.py \ + test_jps.py \ + test_jq.py \ + test_jshint.py \ + test_json_xs.py \ + test_jsonschema.py \ + test_k3b.py \ + test_kcov.py \ + test_kdvi.py \ + test_kill.py \ + test_killall.py \ + test_kldload.py \ + test_kldunload.py \ + test_koji.py \ + test_kpdf.py \ + test_kplayer.py \ + test_ktutil.py \ + test_l2ping.py \ + test_larch.py \ + test_lastlog.py \ + test_ld.py \ + test_ldapadd.py \ + test_ldapcompare.py \ + test_ldapdelete.py \ + test_ldapmodrdn.py \ + test_ldappasswd.py \ + test_ldapsearch.py \ + test_ldapvi.py \ + test_ldapwhoami.py \ + test_ldd.py \ + test_less.py \ + test_lftp.py \ + test_lftpget.py \ + test_lilo.py \ + test_links.py \ + test_lintian.py \ + test_lintian_info.py \ + test_lisp.py \ + test_list_admins.py \ + test_list_lists.py \ + test_list_members.py \ + test_list_owners.py \ + test_ln.py \ + test_locale_gen.py \ + test_look.py \ + test_lpq.py \ + test_lpr.py \ + test_lrzip.py \ + test_ls.py \ + test_lsof.py \ + test_lspci.py \ + test_lsscsi.py \ + test_lsusb.py \ + test_lua.py \ + test_luac.py \ + test_luseradd.py \ + test_luserdel.py \ + test_lusermod.py \ + test_lvchange.py \ + test_lvcreate.py \ + test_lvdisplay.py \ + test_lvextend.py \ + test_lvm.py \ + test_lvmdiskscan.py \ + test_lvreduce.py \ + test_lvremove.py \ + test_lvrename.py \ + test_lvresize.py \ + test_lvs.py \ + test_lvscan.py \ + test_lz4.py \ + test_lzip.py \ + test_lzma.py \ + test_lzop.py \ + test_m4.py \ + test_macof.py \ + test_mailmanctl.py \ + test_mailsnarf.py \ + test_make.py \ + test_makepkg.py \ + test_man.py \ + test_mc.py \ + test_mcrypt.py \ + test_md5sum.py \ + test_mdadm.py \ + test_mdecrypt.py \ + test_mdtool.py \ + test_medusa.py \ + test_mencoder.py \ + test_mii_diag.py \ + test_mii_tool.py \ + test_minicom.py \ + test_mkdir.py \ + test_mkfifo.py \ + test_mkinitrd.py \ + test_mkisofs.py \ + test_mknod.py \ + test_mktemp.py \ + test_mmsitepass.py \ + test_mock.py \ + test_modinfo.py \ + test_modprobe.py \ + test_module.py \ + test_mogrify.py \ + test_monodevelop.py \ + test_montage.py \ + test_mount.py \ + test_mplayer.py \ + test_mr.py \ + test_msgsnarf.py \ + test_msynctool.py \ + test_mtx.py \ + test_munin_node_configure.py \ + test_munin_run.py \ + test_munindoc.py \ + test_mussh.py \ + test_mutt.py \ + test_muttng.py \ + test_mv.py \ + test_mypy.py \ + test_mysql.py \ + test_mysqladmin.py \ + test_nc.py \ + test_ncftp.py \ + test_nethogs.py \ + test_netstat.py \ + test_newgrp.py \ + test_newlist.py \ + test_newusers.py \ + test_ngrep.py \ + test_nl.py \ + test_nm.py \ + test_nmap.py \ + test_nmcli.py \ + test_nproc.py \ + test_nslookup.py \ + test_nsupdate.py \ + test_ntpdate.py \ + test_objcopy.py \ + test_objdump.py \ + test_od.py \ + test_oggdec.py \ + test_op.py \ + test_openssl.py \ + test_opera.py \ + test_optipng.py \ + test_p4.py \ + test_pack200.py \ + test_passwd.py \ + test_paste.py \ + test_patch.py \ + test_pdftotext.py \ + test_perl.py \ + test_perlcritic.py \ + test_perldoc.py \ + test_perltidy.py \ + test_pgrep.py \ + test_phing.py \ + test_pidof.py \ + test_pine.py \ + test_pinfo.py \ + test_ping.py \ + test_pkg_config.py \ + test_pkg_deinstall.py \ + test_pkg_delete.py \ + test_pkg_get.py \ + test_pkg_info.py \ + test_pkgadd.py \ + test_pkgrm.py \ + test_pkgtool.py \ + test_pkgutil.py \ + test_pkill.py \ + test_plague_client.py \ + test_pm_hibernate.py \ + test_pm_is_supported.py \ + test_pm_powersave.py \ + test_pngfix.py \ + test_portinstall.py \ + test_portsnap.py \ + test_portupgrade.py \ + test_postcat.py \ + test_postconf.py \ + test_postfix.py \ + test_postmap.py \ + test_postsuper.py \ + test_povray.py \ + test_pr.py \ + test_prelink.py \ + test_printenv.py \ + test_protoc.py \ + test_psql.py \ + test_ptx.py \ + test_puppet.py \ + test_pushd.py \ + test_pv.py \ + test_pvchange.py \ + test_pvcreate.py \ + test_pvdisplay.py \ + test_pvmove.py \ + test_pvremove.py \ + test_pvs.py \ + test_pvscan.py \ + test_pwck.py \ + test_pwd.py \ + test_pwdx.py \ + test_pwgen.py \ + test_pycodestyle.py \ + test_pydoc.py \ + test_pydocstyle.py \ + test_pyflakes.py \ + test_pylint.py \ + test_pylint_3.py \ + test_pytest.py \ + test_python.py \ + test_python3.py \ + test_pyvenv.py \ + test_qemu.py \ + test_qrunner.py \ + test_querybts.py \ + test_quota.py \ + test_quotacheck.py \ + test_quotaon.py \ + test_radvdump.py \ + test_rcs.py \ + test_rcsdiff.py \ + test_rdesktop.py \ + test_rdict.py \ + test_readelf.py \ + test_readonly.py \ + test_remove_members.py \ + test_removepkg.py \ + test_renice.py \ + test_repomanage.py \ + test_reportbug.py \ + test_reptyr.py \ + test_resolvconf.py \ + test_rfcomm.py \ + test_rfkill.py \ + test_ri.py \ + test_rlog.py \ + test_rm.py \ + test_rmdir.py \ + test_rmlist.py \ + test_rmmod.py \ + test_route.py \ + test_rpcdebug.py \ + test_rpm.py \ + test_rpm2tgz.py \ + test_rpmbuild.py \ + test_rrdtool.py \ + test_rsync.py \ + test_rtcwake.py \ + test_runuser.py \ + 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 \ + test_set.py \ + test_setquota.py \ + test_sftp.py \ + test_sh.py \ + test_sha1sum.py \ + test_shar.py \ + test_shellcheck.py \ + test_sitecopy.py \ + test_slackpkg.py \ + test_slapt_get.py \ + test_slapt_src.py \ + test_smartctl.py \ + test_smbcacls.py \ + test_smbclient.py \ + test_smbcquotas.py \ + test_smbget.py \ + test_smbpasswd.py \ + test_smbtar.py \ + test_smbtree.py \ + test_snownews.py \ + test_sort.py \ + test_split.py \ + test_spovray.py \ + test_sqlite3.py \ + test_ss.py \ + test_ssh.py \ + test_ssh_add.py \ + test_ssh_copy_id.py \ + test_ssh_keygen.py \ + test_sshfs.py \ + test_sshmitm.py \ + test_sshow.py \ + test_strace.py \ + test_stream.py \ + test_strings.py \ + test_strip.py \ + test_su.py \ + test_sudo.py \ + test_sum.py \ + test_svcadm.py \ + test_svk.py \ + test_svn.py \ + test_svnadmin.py \ + test_svnlook.py \ + test_sync_members.py \ + test_synclient.py \ + test_sysbench.py \ + test_sysctl.py \ + test_tac.py \ + test_tail.py \ + test_tar.py \ + test_tcpdump.py \ + test_tcpkill.py \ + test_tcpnice.py \ + test_tee.py \ + test_texindex.py \ + test_tightvncviewer.py \ + 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 \ + test_umount.py \ + test_unace.py \ + test_uname.py \ + test_unexpand.py \ + test_uniq.py \ + test_units.py \ + test_unpack200.py \ + test_unrar.py \ + test_unset.py \ + test_unshunt.py \ + test_update_alternatives.py \ + test_update_rc_d.py \ + test_upgradepkg.py \ + test_urlsnarf.py \ + test_uscan.py \ + test_useradd.py \ + test_userdel.py \ + test_usermod.py \ + test_valgrind.py \ + test_vdir.py \ + test_vgcfgbackup.py \ + test_vgcfgrestore.py \ + test_vgchange.py \ + test_vgck.py \ + test_vgconvert.py \ + test_vgcreate.py \ + test_vgdisplay.py \ + test_vgexport.py \ + test_vgextend.py \ + test_vgimport.py \ + test_vgmerge.py \ + test_vgmknodes.py \ + test_vgreduce.py \ + test_vgremove.py \ + test_vgrename.py \ + test_vgs.py \ + test_vgscan.py \ + test_vgsplit.py \ + test_vi.py \ + test_vipw.py \ + test_vmstat.py \ + test_vncviewer.py \ + test_vpnc.py \ + test_watch.py \ + test_wc.py \ + test_webmitm.py \ + test_wget.py \ + test_who.py \ + test_wine.py \ + test_withlist.py \ + test_wodim.py \ + test_wol.py \ + test_write.py \ + test_wsimport.py \ + test_wtf.py \ + test_wvdial.py \ + test_xdg_mime.py \ + test_xdg_settings.py \ + test_xfreerdp.py \ + test_xgamma.py \ + test_xhost.py \ + test_xm.py \ + test_xmllint.py \ + test_xmlwf.py \ + test_xmms.py \ + test_xmodmap.py \ + test_xpovray.py \ + test_xrandr.py \ + test_xrdb.py \ + test_xsltproc.py \ + test_xvfb_run.py \ + test_xvnc4viewer.py \ + test_xxd.py \ + test_xz.py \ + test_xzdec.py \ + test_ypcat.py \ + test_ypmatch.py \ + test_yum.py \ + test_yum_arch.py \ + test_zopfli.py \ + test_zopflipng.py + +all: + +PYTEST = @PYTEST@ + +check-local: + $(PYTEST) $(PYTESTFLAGS) $(srcdir) + +clean-local: + $(RM) -R __pycache__ diff --git a/test/t/conftest.py b/test/t/conftest.py new file mode 100644 index 0000000..5c1603d --- /dev/null +++ b/test/t/conftest.py @@ -0,0 +1,637 @@ +import difflib +import os +import re +import shlex +import subprocess +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], +) -> Optional[Tuple[str, str]]: + result = None + bestscore = 0 + sitems = sorted(set(items)) + for i in range(len(sitems)): + cur = sitems[i] + curlen = len(cur) + prv = sitems[i - 1] if i != 0 else "" + prvlen = len(prv) + nxt = sitems[i + 1] if i < len(sitems) - 1 else "" + nxtlen = len(nxt) + diffprv = prv == "" + diffnxt = nxt == "" + # Analyse each item of the list and look for the minimum length of the + # partial prefix which is distinct from both nxt and prv. The list + # is sorted so the prefix will be unique in the entire list. + for j in range(curlen): + curchar = cur[j] + if not diffprv and (j >= prvlen or prv[j] != curchar): + diffprv = True + if not diffnxt and (j >= nxtlen or nxt[j] != curchar): + diffnxt = True + if diffprv and diffnxt: + 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. + parlen = 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: + parlen = int(curlen / 2) + score = curlen - parlen + if score > bestscore: + bestscore = score + result = (cur[:parlen], cur) + return result + + +@pytest.fixture(scope="class") +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") + return pair + + +@pytest.fixture(scope="class") +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") + return pair + + +@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 + if os.environ.get("BASHCOMP_TEST_LOGFILE"): + logfile = open(os.environ["BASHCOMP_TEST_LOGFILE"], "w") + testdir = os.path.abspath( + os.path.join(os.path.dirname(__file__), os.pardir) + ) + env = os.environ.copy() + env.update( + dict( + SRCDIR=testdir, # TODO needed at least by bashrc + SRCDIRABS=testdir, # TODO needed? + PS1=PS1, + INPUTRC="%s/config/inputrc" % testdir, + TERM="dumb", + LC_COLLATE="C", # to match Python's default locale unaware sort + ) + ) + + fixturesdir = os.path.join(testdir, "fixtures") + os.chdir(fixturesdir) + + # Start bash + bash = pexpect.spawn( + "%s --norc" % os.environ.get("BASHCOMP_TEST_BASH", "bash"), + maxread=os.environ.get("BASHCOMP_TEST_PEXPECT_MAXREAD", 20000), + logfile=logfile, + cwd=fixturesdir, + env=env, + encoding="utf-8", # TODO? or native or...? + # FIXME: Tests shouldn't depend on dimensions, but it's difficult to + # expect robustly enough for Bash to wrap lines anywhere (e.g. inside + # MAGIC_MARK). Increase window width to reduce wrapping. + dimensions=(24, 160), + # TODO? codec_errors="replace", + ) + bash.expect_exact(PS1) + + # Load bashrc and bash_completion + assert_bash_exec(bash, "source '%s/config/bashrc'" % testdir) + assert_bash_exec(bash, "source '%s/../bash_completion'" % testdir) + + # Use command name from marker if set, or grab from test filename + cmd = None # type: Optional[str] + cmd_found = False + marker = request.node.get_closest_marker("bashcomp") + if marker: + cmd = marker.kwargs.get("cmd") + cmd_found = "cmd" in marker.kwargs + # Run pre-test commands, early so they're usable in skipif + for pre_cmd in marker.kwargs.get("pre_cmds", []): + assert_bash_exec(bash, pre_cmd) + # Process skip and xfail conditions + skipif = marker.kwargs.get("skipif") + if skipif: + try: + assert_bash_exec(bash, skipif, want_output=None) + except AssertionError: + pass + else: + bash.close() + pytest.skip(skipif) + xfail = marker.kwargs.get("xfail") + if xfail: + try: + assert_bash_exec(bash, xfail, want_output=None) + except AssertionError: + pass + else: + pytest.xfail(xfail) + if not cmd_found: + match = re.search( + r"^test_(.+)\.py$", os.path.basename(str(request.fspath)) + ) + if match: + cmd = match.group(1) + + request.cls.cmd = cmd + + if (cmd_found and cmd is None) or is_testable(bash, cmd): + before_env = get_env(bash) + yield bash + # Not exactly sure why, but some errors leave bash in state where + # getting the env here would fail and trash our test output. So + # reset to a good state first (Ctrl+C, expect prompt). + bash.sendintr() + bash.expect_exact(PS1) + diff_env( + before_env, + get_env(bash), + marker.kwargs.get("ignore_env") if marker else "", + ) + + if marker: + for post_cmd in marker.kwargs.get("post_cmds", []): + assert_bash_exec(bash, post_cmd) + + # Clean up + bash.close() + if logfile: + logfile.close() + + +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 + if not load_completion_for(bash, cmd): + pytest.skip("No completion for command %s" % cmd) + return True + + +def is_bash_type(bash: pexpect.spawn, cmd: Optional[str]) -> bool: + if not cmd: + return False + typecmd = "type %s &>/dev/null && echo -n 0 || echo -n 1" % cmd + bash.sendline(typecmd) + bash.expect_exact(typecmd + "\r\n") + result = bash.expect_exact(["0", "1"]) == 0 + bash.expect_exact(PS1) + return result + + +def load_completion_for(bash: pexpect.spawn, cmd: str) -> bool: + try: + # Allow __load_completion to fail so we can test completions + # that are directly loaded in bash_completion without a separate file. + assert_bash_exec(bash, "__load_completion %s || :" % cmd) + assert_bash_exec(bash, "complete -p %s &>/dev/null" % cmd) + except AssertionError: + return False + return True + + +def assert_bash_exec( + 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) + bash.expect_exact(cmd) + + # Find prompt, output is before it + bash.expect_exact("%s%s" % ("\r\n" if want_newline else "", PS1)) + output = bash.before + + # Retrieve exit status + echo = "echo $?" + bash.sendline(echo) + got = bash.expect( + [ + r"^%s\r\n(\d+)\r\n%s" % (re.escape(echo), re.escape(PS1)), + PS1, + pexpect.EOF, + pexpect.TIMEOUT, + ] + ) + status = bash.match.group(1) if got == 0 else "unknown" + + assert status == "0", 'Error running "%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 + + +def get_env(bash: pexpect.spawn) -> List[str]: + return ( + assert_bash_exec( + bash, + "{ (set -o posix ; set); declare -F; shopt -p; set -o; }", + want_output=True, + ) + .strip() + .splitlines() + ) + + +def diff_env(before: List[str], after: List[str], ignore: str): + diff = [ + x + for x in difflib.unified_diff(before, after, n=0, lineterm="") + # Remove unified diff markers: + if not re.search(r"^(---|\+\+\+|@@ )", x) + # Ignore variables expected to change: + and not re.search("^[-+](_|PPID|BASH_REMATCH|OLDPWD)=", x) + # Ignore likely completion functions added by us: + and not re.search(r"^\+declare -f _.+", x) + # ...and additional specified things: + and not re.search(ignore or "^$", x) + ] + # For some reason, COMP_WORDBREAKS gets added to the list after + # saving. Remove its changes, and note that it may take two lines. + for i in range(0, len(diff)): + if re.match("^[-+]COMP_WORDBREAKS=", diff[i]): + if i < len(diff) and not re.match(r"^\+[\w]+=", diff[i + 1]): + del diff[i + 1] + del diff[i] + break + assert not diff, "Environment should not be modified" + + +class CompletionResult(Iterable[str]): + """ + Class to hold completion results. + """ + + def __init__(self, output: Optional[str] = None): + """ + :param output: All completion output as-is. + """ + self.output = output or "" + + def endswith(self, suffix: str) -> bool: + return self.output.endswith(suffix) + + 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. + """ + 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: + return item in self._items() + + def __iter__(self) -> Iterator[str]: + return iter(self._items()) + + def __len__(self) -> int: + return len(self._items()) + + def __repr__(self) -> str: + return "<CompletionResult %s>" % self._items() + + +def assert_complete( + bash: pexpect.spawn, cmd: str, **kwargs +) -> CompletionResult: + skipif = kwargs.get("skipif") + if skipif: + try: + assert_bash_exec(bash, skipif, want_output=None) + except AssertionError: + pass + else: + pytest.skip(skipif) + xfail = kwargs.get("xfail") + if xfail: + try: + assert_bash_exec(bash, xfail, want_output=None) + except AssertionError: + pass + else: + pytest.xfail(xfail) + cwd = kwargs.get("cwd") + if cwd: + assert_bash_exec(bash, "cd '%s'" % cwd) + env_prefix = "_BASHCOMP_TEST_" + env = kwargs.get("env", {}) + if env: + # Back up environment and apply new one + assert_bash_exec( + bash, + " ".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()), + ) + 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 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 + + +@pytest.fixture +def completion(request, bash: pexpect.spawn) -> CompletionResult: + marker = request.node.get_closest_marker("complete") + if not marker: + return CompletionResult() + for pre_cmd in marker.kwargs.get("pre_cmds", []): + assert_bash_exec(bash, pre_cmd) + cmd = getattr(request.cls, "cmd", None) + if marker.kwargs.get("require_longopt"): + # longopt completions require both command presence and that it + # responds something useful to --help + if "require_cmd" not in marker.kwargs: + marker.kwargs["require_cmd"] = True + if "xfail" not in marker.kwargs: + marker.kwargs["xfail"] = ( + "! %s --help &>/dev/null || " + "! %s --help 2>&1 | command grep -qF -- --help" + ) % ((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( + "virt-what || systemd-detect-virt --container", + stderr=subprocess.DEVNULL, + shell=True, + ).strip() + except subprocess.CalledProcessError: + container = b"" + if container and container != b"none": + return True + if os.path.exists("/.dockerenv"): + return True + try: + with open("/proc/1/environ", "rb") as f: + # LXC, others? + if any( + x.startswith(b"container=") for x in f.readline().split(b"\0") + ): + return True + except OSError: + pass + return False + + +class TestUnitBase: + def _test_unit( + self, func, bash, comp_words, comp_cword, comp_line, comp_point, arg="" + ): + assert_bash_exec( + bash, + "COMP_WORDS=%s COMP_CWORD=%d COMP_LINE=%s COMP_POINT=%d" + % (comp_words, comp_cword, shlex.quote(comp_line), comp_point), + ) + output = assert_bash_exec(bash, func % arg, want_output=True) + return output.strip() diff --git a/test/t/test_2to3.py b/test/t/test_2to3.py new file mode 100644 index 0000000..4bce44e --- /dev/null +++ b/test/t/test_2to3.py @@ -0,0 +1,11 @@ +import pytest + + +class Test2to3: + @pytest.mark.complete("2to3 ") + def test_1(self, completion): + assert completion + + @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 new file mode 100644 index 0000000..d4308d9 --- /dev/null +++ b/test/t/test_7z.py @@ -0,0 +1,33 @@ +import pytest + + +class Test7z: + @pytest.mark.complete("7z ") + def test_1(self, completion): + assert completion + + @pytest.mark.complete("7z a ar -tzi") + def test_2(self, completion): + assert completion == "p" + + @pytest.mark.complete(r"7z x -wa\ ", cwd="_filedir") + def test_3(self, completion): + assert completion == "b/" + assert not completion.endswith(" ") + + @pytest.mark.complete("7z x ", cwd="7z") + def test_4(self, completion): + assert completion == "a.7z" + + @pytest.mark.complete("7z d a.7z ", cwd="7z", require_cmd=True) + def test_5(self, completion): + assert completion == "abc" + + @pytest.mark.complete("7z a -air@", cwd="7z") + def test_6(self, completion): + assert completion == sorted("-air@a.7z -air@f.txt".split()) + + @pytest.mark.complete("7z a -o") + def test_7(self, completion): + assert "-o7z/" in completion + assert all(x.endswith("/") for x in completion) diff --git a/test/t/test_a2ps.py b/test/t/test_a2ps.py new file mode 100644 index 0000000..38365f0 --- /dev/null +++ b/test/t/test_a2ps.py @@ -0,0 +1,11 @@ +import pytest + + +class TestA2ps: + @pytest.mark.complete("a2ps ") + def test_1(self, completion): + assert completion + + @pytest.mark.complete("a2ps -", require_cmd=True) + def test_options(self, completion): + assert completion diff --git a/test/t/test_a2x.py b/test/t/test_a2x.py new file mode 100644 index 0000000..4bfb428 --- /dev/null +++ b/test/t/test_a2x.py @@ -0,0 +1,11 @@ +import pytest + + +class TestA2x: + @pytest.mark.complete("a2x ") + def test_1(self, completion): + assert completion + + @pytest.mark.complete("a2x -", require_cmd=True) + def test_2(self, completion): + assert completion diff --git a/test/t/test_abook.py b/test/t/test_abook.py new file mode 100644 index 0000000..9542a4c --- /dev/null +++ b/test/t/test_abook.py @@ -0,0 +1,7 @@ +import pytest + + +class TestAbook: + @pytest.mark.complete("abook -", require_cmd=True) + def test_1(self, completion): + assert completion diff --git a/test/t/test_aclocal.py b/test/t/test_aclocal.py new file mode 100644 index 0000000..ad28b42 --- /dev/null +++ b/test/t/test_aclocal.py @@ -0,0 +1,11 @@ +import pytest + + +class TestAclocal: + @pytest.mark.complete("aclocal ") + def test_1(self, completion): + assert completion + + @pytest.mark.complete("aclocal -", require_cmd=True) + def test_2(self, completion): + assert completion diff --git a/test/t/test_acpi.py b/test/t/test_acpi.py new file mode 100644 index 0000000..bd06d93 --- /dev/null +++ b/test/t/test_acpi.py @@ -0,0 +1,7 @@ +import pytest + + +class TestAcpi: + @pytest.mark.complete("acpi -", require_cmd=True) + def test_1(self, completion): + assert completion diff --git a/test/t/test_acroread.py b/test/t/test_acroread.py new file mode 100644 index 0000000..22d6024 --- /dev/null +++ b/test/t/test_acroread.py @@ -0,0 +1,7 @@ +import pytest + + +class TestAcroread: + @pytest.mark.complete("acroread ", cwd="acroread") + def test_1(self, completion): + assert completion == "foo.d/ t.pdf".split() diff --git a/test/t/test_adb.py b/test/t/test_adb.py new file mode 100644 index 0000000..74b0d37 --- /dev/null +++ b/test/t/test_adb.py @@ -0,0 +1,11 @@ +import pytest + + +class TestAdb: + @pytest.mark.complete("adb ") + def test_1(self, completion): + assert completion + + @pytest.mark.complete("adb -", require_cmd=True) + def test_2(self, completion): + assert completion diff --git a/test/t/test_add_members.py b/test/t/test_add_members.py new file mode 100644 index 0000000..095a5de --- /dev/null +++ b/test/t/test_add_members.py @@ -0,0 +1,7 @@ +import pytest + + +class TestAddMembers: + @pytest.mark.complete("add_members -") + def test_1(self, completion): + assert completion diff --git a/test/t/test_alias.py b/test/t/test_alias.py new file mode 100644 index 0000000..cc592a8 --- /dev/null +++ b/test/t/test_alias.py @@ -0,0 +1,21 @@ +import pytest + + +@pytest.mark.bashcomp( + pre_cmds=("unalias -a", "alias foo=bar", "alias bar='foo foo'"), + post_cmds=("unalias -a",), +) +class TestAlias: + @pytest.mark.complete("alias ") + def test_1(self, completion): + assert completion == "bar foo".split() + + @pytest.mark.xfail # TODO: Would like this completion to work + @pytest.mark.complete("alias foo=") + 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_alpine.py b/test/t/test_alpine.py new file mode 100644 index 0000000..dcc05d3 --- /dev/null +++ b/test/t/test_alpine.py @@ -0,0 +1,7 @@ +import pytest + + +class TestAlpine: + @pytest.mark.complete("alpine -", require_cmd=True) + def test_1(self, completion): + assert completion diff --git a/test/t/test_animate.py b/test/t/test_animate.py new file mode 100644 index 0000000..2103606 --- /dev/null +++ b/test/t/test_animate.py @@ -0,0 +1,7 @@ +import pytest + + +class TestAnimate: + @pytest.mark.complete("animate ") + def test_1(self, completion): + assert completion diff --git a/test/t/test_ant.py b/test/t/test_ant.py new file mode 100644 index 0000000..94acea1 --- /dev/null +++ b/test/t/test_ant.py @@ -0,0 +1,35 @@ +import pytest + +from conftest import assert_bash_exec + + +@pytest.mark.bashcomp(ignore_env=r"^\+ANT_ARGS=") +class TestAnt: + @pytest.mark.complete("ant -", require_cmd=True) + def test_1(self, completion): + assert completion + + @pytest.mark.complete("ant ", cwd="ant") + def test_2(self, completion): + assert completion == "bashcomp clean init realclean".split() + + @pytest.mark.complete("ant -f build-with-import.xml ", cwd="ant") + def test_3(self, completion): + assert completion == "build-with-import imported-build".split() + + @pytest.mark.complete( + "ant ", cwd="ant", env=dict(ANT_ARGS="'-f named-build.xml'") + ) + 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): + assert completion diff --git a/test/t/test_apache2ctl.py b/test/t/test_apache2ctl.py new file mode 100644 index 0000000..856a0e4 --- /dev/null +++ b/test/t/test_apache2ctl.py @@ -0,0 +1,7 @@ +import pytest + + +class TestApache2ctl: + @pytest.mark.complete("apache2ctl ") + def test_1(self, completion): + assert completion diff --git a/test/t/test_appdata_validate.py b/test/t/test_appdata_validate.py new file mode 100644 index 0000000..8166cf8 --- /dev/null +++ b/test/t/test_appdata_validate.py @@ -0,0 +1,12 @@ +import pytest + + +@pytest.mark.bashcomp(cmd="appdata-validate") +class TestAppdataValidate: + @pytest.mark.complete("appdata-validate ") + def test_1(self, completion): + assert completion + + @pytest.mark.complete("appdata-validate -", require_cmd=True) + def test_2(self, completion): + assert completion diff --git a/test/t/test_apt_build.py b/test/t/test_apt_build.py new file mode 100644 index 0000000..8346e11 --- /dev/null +++ b/test/t/test_apt_build.py @@ -0,0 +1,8 @@ +import pytest + + +@pytest.mark.bashcomp(cmd="apt-build") +class TestAptBuild: + @pytest.mark.complete("apt-build ") + def test_1(self, completion): + assert completion diff --git a/test/t/test_apt_cache.py b/test/t/test_apt_cache.py new file mode 100644 index 0000000..f9329f2 --- /dev/null +++ b/test/t/test_apt_cache.py @@ -0,0 +1,17 @@ +import pytest + + +@pytest.mark.bashcomp(cmd="apt-cache") +class TestAptCache: + @pytest.mark.complete("apt-cache ") + def test_1(self, 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 new file mode 100644 index 0000000..dc8299a --- /dev/null +++ b/test/t/test_apt_get.py @@ -0,0 +1,16 @@ +import pytest + + +@pytest.mark.bashcomp(cmd="apt-get") +class TestAptGet: + @pytest.mark.complete("apt-get ") + def test_1(self, completion): + assert all(x in completion for x in "install update".split()) + + @pytest.mark.complete("apt-get install ./", cwd="dpkg") + def test_2(self, completion): + 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 new file mode 100644 index 0000000..29569f1 --- /dev/null +++ b/test/t/test_aptitude.py @@ -0,0 +1,23 @@ +import pytest + + +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_arch.py b/test/t/test_arch.py new file mode 100644 index 0000000..7a0f447 --- /dev/null +++ b/test/t/test_arch.py @@ -0,0 +1,8 @@ +import pytest + + +@pytest.mark.bashcomp(pre_cmds=("PATH=/usr/lib/mailman/bin:$PATH",)) +class TestArch: + @pytest.mark.complete("arch -", require_cmd=True) + def test_1(self, completion): + assert completion diff --git a/test/t/test_arp.py b/test/t/test_arp.py new file mode 100644 index 0000000..cd038bd --- /dev/null +++ b/test/t/test_arp.py @@ -0,0 +1,13 @@ +import pytest + + +class TestArp: + @pytest.mark.complete( + "arp ", require_cmd=True, skipif='test -z "$(arp 2>/dev/null)"' + ) + def test_1(self, completion): + assert completion + + @pytest.mark.complete("arp -", require_cmd=True) + def test_2(self, completion): + assert completion diff --git a/test/t/test_arping.py b/test/t/test_arping.py new file mode 100644 index 0000000..0eef5c9 --- /dev/null +++ b/test/t/test_arping.py @@ -0,0 +1,11 @@ +import pytest + + +class TestArping: + @pytest.mark.complete("arping ") + def test_1(self, completion): + assert completion + + @pytest.mark.complete("arping -", require_cmd=True) + def test_2(self, completion): + assert completion diff --git a/test/t/test_arpspoof.py b/test/t/test_arpspoof.py new file mode 100644 index 0000000..74c09a4 --- /dev/null +++ b/test/t/test_arpspoof.py @@ -0,0 +1,12 @@ +import pytest + + +class TestArpspoof: + @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_asciidoc.py b/test/t/test_asciidoc.py new file mode 100644 index 0000000..b748dcd --- /dev/null +++ b/test/t/test_asciidoc.py @@ -0,0 +1,11 @@ +import pytest + + +class TestAsciidoc: + @pytest.mark.complete("asciidoc ") + def test_1(self, completion): + assert completion + + @pytest.mark.complete("asciidoc -", require_cmd=True) + def test_2(self, completion): + assert completion diff --git a/test/t/test_aspell.py b/test/t/test_aspell.py new file mode 100644 index 0000000..b7a03c4 --- /dev/null +++ b/test/t/test_aspell.py @@ -0,0 +1,7 @@ +import pytest + + +class TestAspell: + @pytest.mark.complete("aspell ") + def test_1(self, completion): + assert completion diff --git a/test/t/test_autoconf.py b/test/t/test_autoconf.py new file mode 100644 index 0000000..9b98b62 --- /dev/null +++ b/test/t/test_autoconf.py @@ -0,0 +1,7 @@ +import pytest + + +class TestAutoconf: + @pytest.mark.complete("autoconf ") + def test_1(self, completion): + assert completion diff --git a/test/t/test_autoheader.py b/test/t/test_autoheader.py new file mode 100644 index 0000000..57ad8af --- /dev/null +++ b/test/t/test_autoheader.py @@ -0,0 +1,7 @@ +import pytest + + +class TestAutoheader: + @pytest.mark.complete("autoheader ") + def test_1(self, completion): + assert completion diff --git a/test/t/test_automake.py b/test/t/test_automake.py new file mode 100644 index 0000000..2174e02 --- /dev/null +++ b/test/t/test_automake.py @@ -0,0 +1,11 @@ +import pytest + + +class TestAutomake: + @pytest.mark.complete("automake ") + def test_1(self, completion): + assert completion + + @pytest.mark.complete("automake -", require_cmd=True) + def test_2(self, completion): + assert completion diff --git a/test/t/test_autoreconf.py b/test/t/test_autoreconf.py new file mode 100644 index 0000000..10e2a2e --- /dev/null +++ b/test/t/test_autoreconf.py @@ -0,0 +1,7 @@ +import pytest + + +class TestAutoreconf: + @pytest.mark.complete("autoreconf ") + def test_1(self, completion): + assert completion diff --git a/test/t/test_autorpm.py b/test/t/test_autorpm.py new file mode 100644 index 0000000..185585e --- /dev/null +++ b/test/t/test_autorpm.py @@ -0,0 +1,7 @@ +import pytest + + +class TestAutorpm: + @pytest.mark.complete("autorpm ") + def test_1(self, completion): + assert completion diff --git a/test/t/test_autoscan.py b/test/t/test_autoscan.py new file mode 100644 index 0000000..d3d45a1 --- /dev/null +++ b/test/t/test_autoscan.py @@ -0,0 +1,11 @@ +import pytest + + +class TestAutoscan: + @pytest.mark.complete("autoscan ") + def test_1(self, completion): + assert completion + + @pytest.mark.complete("autoscan -", require_cmd=True) + def test_2(self, completion): + assert completion diff --git a/test/t/test_autossh.py b/test/t/test_autossh.py new file mode 100644 index 0000000..8640712 --- /dev/null +++ b/test/t/test_autossh.py @@ -0,0 +1,7 @@ +import pytest + + +class TestAutossh: + @pytest.mark.complete("autossh -", require_cmd=True) + def test_1(self, completion): + assert completion diff --git a/test/t/test_autoupdate.py b/test/t/test_autoupdate.py new file mode 100644 index 0000000..13fd8d4 --- /dev/null +++ b/test/t/test_autoupdate.py @@ -0,0 +1,7 @@ +import pytest + + +class TestAutoupdate: + @pytest.mark.complete("autoupdate ") + def test_1(self, completion): + assert completion diff --git a/test/t/test_avctrl.py b/test/t/test_avctrl.py new file mode 100644 index 0000000..6ff1ec3 --- /dev/null +++ b/test/t/test_avctrl.py @@ -0,0 +1,7 @@ +import pytest + + +class TestAvctrl: + @pytest.mark.complete("avctrl ") + def test_1(self, completion): + assert completion diff --git a/test/t/test_awk.py b/test/t/test_awk.py new file mode 100644 index 0000000..9fd7380 --- /dev/null +++ b/test/t/test_awk.py @@ -0,0 +1,11 @@ +import pytest + + +class TestAwk: + @pytest.mark.complete("awk ") + def test_1(self, completion): + assert completion + + @pytest.mark.complete("awk -", require_longopt=True) + def test_options(self, completion): + assert completion diff --git a/test/t/test_badblocks.py b/test/t/test_badblocks.py new file mode 100644 index 0000000..58130b3 --- /dev/null +++ b/test/t/test_badblocks.py @@ -0,0 +1,12 @@ +import pytest + + +class TestBadblocks: + @pytest.mark.complete("badblocks ") + def test_1(self, completion): + assert completion + + @pytest.mark.complete("badblocks -", require_cmd=True) + def test_2(self, completion): + assert completion + assert all(x not in completion for x in "-w -X".split()) diff --git a/test/t/test_base64.py b/test/t/test_base64.py new file mode 100644 index 0000000..957f5a3 --- /dev/null +++ b/test/t/test_base64.py @@ -0,0 +1,11 @@ +import pytest + + +class TestBase64: + @pytest.mark.complete("base64 ") + def test_1(self, completion): + assert completion + + @pytest.mark.complete("base64 -", require_longopt=True) + def test_options(self, completion): + assert completion diff --git a/test/t/test_bash.py b/test/t/test_bash.py new file mode 100644 index 0000000..97a3b8d --- /dev/null +++ b/test/t/test_bash.py @@ -0,0 +1,7 @@ +import pytest + + +class TestBash: + @pytest.mark.complete("bash --", require_cmd=True) + def test_1(self, completion): + assert completion diff --git a/test/t/test_bc.py b/test/t/test_bc.py new file mode 100644 index 0000000..7f8056e --- /dev/null +++ b/test/t/test_bc.py @@ -0,0 +1,7 @@ +import pytest + + +class TestBc: + @pytest.mark.complete("bc --", require_longopt=True) + def test_1(self, completion): + assert completion diff --git a/test/t/test_bind.py b/test/t/test_bind.py new file mode 100644 index 0000000..97a5044 --- /dev/null +++ b/test/t/test_bind.py @@ -0,0 +1,11 @@ +import pytest + + +class TestBind: + @pytest.mark.complete("bind -", require_cmd=True) + def test_1(self, completion): + assert completion + + @pytest.mark.complete("bind k") + def test_2(self, completion): + assert completion diff --git a/test/t/test_bison.py b/test/t/test_bison.py new file mode 100644 index 0000000..a4a481a --- /dev/null +++ b/test/t/test_bison.py @@ -0,0 +1,7 @@ +import pytest + + +class TestBison: + @pytest.mark.complete("bison --", require_cmd=True) + def test_1(self, completion): + assert completion diff --git a/test/t/test_bk.py b/test/t/test_bk.py new file mode 100644 index 0000000..8ab44b6 --- /dev/null +++ b/test/t/test_bk.py @@ -0,0 +1,7 @@ +import pytest + + +class TestBk: + @pytest.mark.complete("bk ") + 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 0000000..bc885d3 --- /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_brctl.py b/test/t/test_brctl.py new file mode 100644 index 0000000..7c773e9 --- /dev/null +++ b/test/t/test_brctl.py @@ -0,0 +1,7 @@ +import pytest + + +class TestBrctl: + @pytest.mark.complete("brctl ") + def test_1(self, completion): + assert completion diff --git a/test/t/test_btdownloadcurses_py.py b/test/t/test_btdownloadcurses_py.py new file mode 100644 index 0000000..0b65519 --- /dev/null +++ b/test/t/test_btdownloadcurses_py.py @@ -0,0 +1,8 @@ +import pytest + + +@pytest.mark.bashcomp(cmd="btdownloadcurses.py") +class TestBtdownloadcursesPy: + @pytest.mark.complete("btdownloadcurses.py ") + def test_1(self, completion): + assert completion diff --git a/test/t/test_btdownloadgui_py.py b/test/t/test_btdownloadgui_py.py new file mode 100644 index 0000000..c1b1b38 --- /dev/null +++ b/test/t/test_btdownloadgui_py.py @@ -0,0 +1,8 @@ +import pytest + + +@pytest.mark.bashcomp(cmd="btdownloadgui.py") +class TestBtdownloadguiPy: + @pytest.mark.complete("btdownloadgui.py ") + def test_1(self, completion): + assert completion diff --git a/test/t/test_btdownloadheadless_py.py b/test/t/test_btdownloadheadless_py.py new file mode 100644 index 0000000..f84592f --- /dev/null +++ b/test/t/test_btdownloadheadless_py.py @@ -0,0 +1,8 @@ +import pytest + + +@pytest.mark.bashcomp(cmd="btdownloadheadless.py") +class TestBtdownloadheadlessPy: + @pytest.mark.complete("btdownloadheadless.py ") + def test_1(self, completion): + assert completion diff --git a/test/t/test_bts.py b/test/t/test_bts.py new file mode 100644 index 0000000..53dd62f --- /dev/null +++ b/test/t/test_bts.py @@ -0,0 +1,11 @@ +import pytest + + +class TestBts: + @pytest.mark.complete("bts ") + def test_1(self, completion): + assert completion + + @pytest.mark.complete("bts -") + def test_2(self, completion): + assert completion diff --git a/test/t/test_bzip2.py b/test/t/test_bzip2.py new file mode 100644 index 0000000..3b501ea --- /dev/null +++ b/test/t/test_bzip2.py @@ -0,0 +1,15 @@ +import pytest + + +class TestBzip2: + @pytest.mark.complete("bzip2 ") + def test_1(self, completion): + assert completion + + @pytest.mark.complete("bzip2 ~") + def test_2(self, completion): + assert completion + + @pytest.mark.complete("bzip2 -") + def test_3(self, completion): + assert completion diff --git a/test/t/test_cal.py b/test/t/test_cal.py new file mode 100644 index 0000000..83d17ff --- /dev/null +++ b/test/t/test_cal.py @@ -0,0 +1,11 @@ +import pytest + + +class TestCal: + @pytest.mark.complete("cal ") + def test_1(self, completion): + assert completion + + @pytest.mark.complete("cal -", require_cmd=True) + def test_2(self, completion): + assert completion diff --git a/test/t/test_cancel.py b/test/t/test_cancel.py new file mode 100644 index 0000000..4aeafd2 --- /dev/null +++ b/test/t/test_cancel.py @@ -0,0 +1,34 @@ +import pytest + +from conftest import assert_bash_exec + + +class TestCancel: + @pytest.fixture(scope="class") + def added_job(self, request, bash): + try: + got = ( + assert_bash_exec( + bash, "lp -H hold shared/default/foo", want_output=True + ) + .strip() + .split() + ) + except AssertionError: + pytest.skip("Could not add test print job") + return + if len(got) > 3: + request.addfinalizer( + lambda: assert_bash_exec(bash, "cancel %s" % got[3]) + ) + + @pytest.mark.complete("cancel ") + def test_1(self, bash, completion, added_job): + got = ( + assert_bash_exec( + bash, "lpstat | awk '{print $1}'", want_output=True + ) + .strip() + .split() + ) + assert completion == sorted(got) diff --git a/test/t/test_cardctl.py b/test/t/test_cardctl.py new file mode 100644 index 0000000..df28b6b --- /dev/null +++ b/test/t/test_cardctl.py @@ -0,0 +1,7 @@ +import pytest + + +class TestCardctl: + @pytest.mark.complete("cardctl ") + def test_1(self, completion): + assert completion diff --git a/test/t/test_carton.py b/test/t/test_carton.py new file mode 100644 index 0000000..1c2e453 --- /dev/null +++ b/test/t/test_carton.py @@ -0,0 +1,11 @@ +import pytest + + +class TestCarton: + @pytest.mark.complete("carton ", require_cmd=True) + def test_commands(self, completion): + assert all(x in completion for x in "help install".split()) + + @pytest.mark.complete("carton install -", require_cmd=True) + def test_install_options(self, completion): + assert all(x in completion for x in "--cached --help".split()) diff --git a/test/t/test_cat.py b/test/t/test_cat.py new file mode 100644 index 0000000..5fa4c8f --- /dev/null +++ b/test/t/test_cat.py @@ -0,0 +1,11 @@ +import pytest + + +class TestCat: + @pytest.mark.complete("cat ") + def test_1(self, completion): + assert completion + + @pytest.mark.complete("cat -", require_longopt=True) + def test_options(self, completion): + assert completion diff --git a/test/t/test_cc.py b/test/t/test_cc.py new file mode 100644 index 0000000..12f6b2b --- /dev/null +++ b/test/t/test_cc.py @@ -0,0 +1,7 @@ +import pytest + + +class TestCc: + @pytest.mark.complete("cc ") + def test_1(self, completion): + assert completion diff --git a/test/t/test_ccache.py b/test/t/test_ccache.py new file mode 100644 index 0000000..ef55d0d --- /dev/null +++ b/test/t/test_ccache.py @@ -0,0 +1,27 @@ +import pytest + + +class TestCcache: + @pytest.mark.complete("ccache -", require_cmd=True) + def test_1(self, completion): + assert completion + + @pytest.mark.complete("ccache --clea", require_cmd=True) + def test_2(self, completion): + assert all(x in completion for x in "--cleanup --clear".split()) + + @pytest.mark.complete("ccache stt") + def test_3(self, completion): + assert completion == "y" or "stty" in completion + + @pytest.mark.complete("ccache --zero-stats stt") + def test_4(self, completion): + assert completion == "y" or "stty" in completion + + @pytest.mark.complete("ccache --hel", require_cmd=True) + def test_5(self, completion): + assert completion == "p" or "--help" in completion + + @pytest.mark.complete("ccache --zero-stats sh +") + def test_6(self, completion): + assert "+x" in completion diff --git a/test/t/test_ccze.py b/test/t/test_ccze.py new file mode 100644 index 0000000..abf1234 --- /dev/null +++ b/test/t/test_ccze.py @@ -0,0 +1,19 @@ +import pytest + + +class TestCcze: + @pytest.mark.complete("ccze ", require_cmd=True) + def test_1(self, completion): + assert completion + + @pytest.mark.complete("ccze -? ") + def test_2(self, completion): + assert not completion + + @pytest.mark.complete("ccze -o ") + def test_3(self, completion): + assert completion + + @pytest.mark.complete("ccze --plugin=", require_cmd=True) + def test_4(self, completion): + assert completion diff --git a/test/t/test_cd.py b/test/t/test_cd.py new file mode 100644 index 0000000..5b7789a --- /dev/null +++ b/test/t/test_cd.py @@ -0,0 +1,26 @@ +import pytest + + +@pytest.mark.bashcomp(ignore_env=r"^\+CDPATH=$") +class TestCd: + @pytest.mark.complete("cd shared/default/") + def test_1(self, completion): + assert completion == ["bar bar.d/", "foo.d/"] + + @pytest.mark.complete("cd fo", env=dict(CDPATH="shared/default")) + def test_2(self, completion): + assert completion == "o.d/" + + @pytest.mark.complete("cd fo") + def test_3(self, completion): + assert not completion + + @pytest.mark.complete( + "cd ", cwd="shared/default/foo.d", env=dict(CDPATH="") + ) + 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_cdrecord.py b/test/t/test_cdrecord.py new file mode 100644 index 0000000..d9d2da1 --- /dev/null +++ b/test/t/test_cdrecord.py @@ -0,0 +1,7 @@ +import pytest + + +class TestCdrecord: + @pytest.mark.complete("cdrecord -d") + def test_1(self, completion): + assert completion diff --git a/test/t/test_cfagent.py b/test/t/test_cfagent.py new file mode 100644 index 0000000..990fc62 --- /dev/null +++ b/test/t/test_cfagent.py @@ -0,0 +1,7 @@ +import pytest + + +class TestCfagent: + @pytest.mark.complete("cfagent -", require_cmd=True) + def test_1(self, completion): + assert completion diff --git a/test/t/test_cfrun.py b/test/t/test_cfrun.py new file mode 100644 index 0000000..a647d76 --- /dev/null +++ b/test/t/test_cfrun.py @@ -0,0 +1,7 @@ +import pytest + + +class TestCfrun: + @pytest.mark.complete("cfrun -") + def test_1(self, completion): + assert completion diff --git a/test/t/test_chage.py b/test/t/test_chage.py new file mode 100644 index 0000000..3957ae3 --- /dev/null +++ b/test/t/test_chage.py @@ -0,0 +1,11 @@ +import pytest + + +class TestChage: + @pytest.mark.complete("chage ") + def test_1(self, completion): + assert completion + + @pytest.mark.complete("chage -", require_cmd=True) + def test_2(self, completion): + assert completion diff --git a/test/t/test_change_pw.py b/test/t/test_change_pw.py new file mode 100644 index 0000000..69909af --- /dev/null +++ b/test/t/test_change_pw.py @@ -0,0 +1,8 @@ +import pytest + + +@pytest.mark.bashcomp(pre_cmds=("PATH=/usr/lib/mailman/bin:$PATH",)) +class TestChangePw: + @pytest.mark.complete("change_pw -") + def test_1(self, completion): + assert completion diff --git a/test/t/test_check_db.py b/test/t/test_check_db.py new file mode 100644 index 0000000..a9f4844 --- /dev/null +++ b/test/t/test_check_db.py @@ -0,0 +1,7 @@ +import pytest + + +class TestCheckDb: + @pytest.mark.complete("check_db -") + def test_1(self, completion): + assert completion diff --git a/test/t/test_check_perms.py b/test/t/test_check_perms.py new file mode 100644 index 0000000..813ae4c --- /dev/null +++ b/test/t/test_check_perms.py @@ -0,0 +1,7 @@ +import pytest + + +class TestCheckPerms: + @pytest.mark.complete("check_perms -") + def test_1(self, completion): + assert completion diff --git a/test/t/test_checksec.py b/test/t/test_checksec.py new file mode 100644 index 0000000..5a11037 --- /dev/null +++ b/test/t/test_checksec.py @@ -0,0 +1,7 @@ +import pytest + + +class TestChecksec: + @pytest.mark.complete("checksec -", require_cmd=True) + def test_1(self, completion): + assert completion diff --git a/test/t/test_chfn.py b/test/t/test_chfn.py new file mode 100644 index 0000000..ca719b8 --- /dev/null +++ b/test/t/test_chfn.py @@ -0,0 +1,7 @@ +import pytest + + +class TestChfn: + @pytest.mark.complete("chfn ") + def test_1(self, completion): + assert completion diff --git a/test/t/test_chgrp.py b/test/t/test_chgrp.py new file mode 100644 index 0000000..87a583e --- /dev/null +++ b/test/t/test_chgrp.py @@ -0,0 +1,7 @@ +import pytest + + +class TestChgrp: + @pytest.mark.complete("chgrp ") + def test_1(self, completion): + assert completion diff --git a/test/t/test_chkconfig.py b/test/t/test_chkconfig.py new file mode 100644 index 0000000..08e9827 --- /dev/null +++ b/test/t/test_chkconfig.py @@ -0,0 +1,15 @@ +import pytest + + +class TestChkconfig: + @pytest.mark.complete("chkconfig -") + def test_1(self, completion): + assert completion + + # systemd may not be running e.g. in a docker container, and listing + # services will then fail. + @pytest.mark.complete( + "chkconfig ", xfail="! systemctl list-units &>/dev/null" + ) + def test_2(self, completion): + assert completion diff --git a/test/t/test_chmod.py b/test/t/test_chmod.py new file mode 100644 index 0000000..3838b55 --- /dev/null +++ b/test/t/test_chmod.py @@ -0,0 +1,25 @@ +import pytest + + +class TestChmod: + + # No completion here until mode completion is implemented + @pytest.mark.complete("chmod ") + def test_1(self, completion): + assert not completion + + @pytest.mark.complete("chmod 755 ") + def test_2(self, completion): + assert completion + + @pytest.mark.complete("chmod -", require_cmd=True) + def test_3(self, completion): + assert completion + + @pytest.mark.complete("chmod -x ") + def test_4(self, completion): + assert completion + + @pytest.mark.complete("chmod -77 ") + def test_5(self, completion): + assert completion diff --git a/test/t/test_chown.py b/test/t/test_chown.py new file mode 100644 index 0000000..9643f3e --- /dev/null +++ b/test/t/test_chown.py @@ -0,0 +1,82 @@ +import getpass + +import pytest + +from conftest import assert_complete + + +@pytest.mark.bashcomp( + pre_cmds=( + # Fake root command to get all users/groups completed at least for now + "root_command=sudo", + ) +) +class TestChown: + @pytest.mark.xfail( + getpass.getuser() != "root", reason="Only root can chown to all users" + ) + @pytest.mark.complete("chown ") + 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/") + def test_2(self, completion): + assert completion == ["bar", "bar bar.d/", "foo", "foo.d/"] + + @pytest.mark.complete("chown :foo shared/default/") + def test_3(self, completion): + assert completion == ["bar", "bar bar.d/", "foo", "foo.d/"] + + def test_4(self, bash, part_full_user): + part, full = part_full_user + completion = assert_complete(bash, "chown %s" % part) + 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 == 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 == full[len(part) :] + assert completion.output.endswith(" ") + + @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\ :", + ], + ) + 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.""" + _, user = part_full_user + partgroup, _ = part_full_group + for x in range(2, 5): + completion = assert_complete( + bash, "chown %s%s:%s" % (user, x * "\\", partgroup) + ) + assert not completion + + def test_9(self, bash, part_full_group): + """Test graceful fail on colon in user/group name.""" + part, _ = part_full_group + completion = assert_complete(bash, "chown foo:bar:%s" % part) + assert not completion diff --git a/test/t/test_chpasswd.py b/test/t/test_chpasswd.py new file mode 100644 index 0000000..ebb292f --- /dev/null +++ b/test/t/test_chpasswd.py @@ -0,0 +1,7 @@ +import pytest + + +class TestChpasswd: + @pytest.mark.complete("chpasswd -", require_cmd=True) + def test_1(self, completion): + assert completion diff --git a/test/t/test_chromium_browser.py b/test/t/test_chromium_browser.py new file mode 100644 index 0000000..b0b19b2 --- /dev/null +++ b/test/t/test_chromium_browser.py @@ -0,0 +1,25 @@ +import pytest + + +@pytest.mark.bashcomp(cmd="chromium-browser") +class TestChromiumBrowser: + @pytest.mark.complete("chromium-browser ") + def test_1(self, completion): + assert completion + + @pytest.mark.complete( + "chromium-browser -", xfail="! chromium-browser --help &>/dev/null" + ) + def test_2(self, completion): + assert completion + assert not completion.endswith(" ") + + @pytest.mark.complete("chromium-browser --proxy-server=") + def test_proxy_server_scheme(self, completion): + assert completion + assert not completion.endswith(" ") + assert all(x.endswith("://") for x in completion) + + @pytest.mark.complete("chromium-browser --proxy-server=http://") + def test_proxy_server_host(self, completion): + assert completion diff --git a/test/t/test_chronyc.py b/test/t/test_chronyc.py new file mode 100644 index 0000000..1fee246 --- /dev/null +++ b/test/t/test_chronyc.py @@ -0,0 +1,11 @@ +import pytest + + +class TestChronyc: + @pytest.mark.complete("chronyc ", require_cmd=True) + def test_1(self, completion): + assert completion + + @pytest.mark.complete("chronyc -", require_cmd=True) + def test_2(self, completion): + assert completion diff --git a/test/t/test_chroot.py b/test/t/test_chroot.py new file mode 100644 index 0000000..08ace86 --- /dev/null +++ b/test/t/test_chroot.py @@ -0,0 +1,16 @@ +import pytest + + +class TestChroot: + @pytest.mark.complete("chroot ") + def test_1(self, completion): + assert completion + + @pytest.mark.complete("/bin/chroot shared/default/") + def test_2(self, completion): + """Should complete dirs only, also when invoked using full path.""" + assert completion == ["bar bar.d/", "foo.d/"] + + @pytest.mark.complete("chroot -", require_longopt=True) + def test_options(self, completion): + assert completion diff --git a/test/t/test_chrpath.py b/test/t/test_chrpath.py new file mode 100644 index 0000000..8e94dcb --- /dev/null +++ b/test/t/test_chrpath.py @@ -0,0 +1,11 @@ +import pytest + + +class TestChrpath: + @pytest.mark.complete("chrpath ") + def test_1(self, completion): + assert completion + + @pytest.mark.complete("chrpath -", require_cmd=True) + def test_2(self, completion): + assert completion diff --git a/test/t/test_chsh.py b/test/t/test_chsh.py new file mode 100644 index 0000000..fe1c7f6 --- /dev/null +++ b/test/t/test_chsh.py @@ -0,0 +1,15 @@ +import pytest + + +class TestChsh: + @pytest.mark.complete("chsh ") + def test_1(self, completion): + assert completion + + @pytest.mark.complete("chsh -s ") + def test_2(self, completion): + assert completion + + @pytest.mark.complete("chsh -", require_cmd=True) + def test_3(self, completion): + assert completion diff --git a/test/t/test_ci.py b/test/t/test_ci.py new file mode 100644 index 0000000..f941b2c --- /dev/null +++ b/test/t/test_ci.py @@ -0,0 +1,7 @@ +import pytest + + +class TestCi: + @pytest.mark.complete("ci ") + def test_1(self, completion): + assert completion diff --git a/test/t/test_ciptool.py b/test/t/test_ciptool.py new file mode 100644 index 0000000..0ff5444 --- /dev/null +++ b/test/t/test_ciptool.py @@ -0,0 +1,7 @@ +import pytest + + +class TestCiptool: + @pytest.mark.complete("ciptool ") + def test_1(self, completion): + assert completion diff --git a/test/t/test_civclient.py b/test/t/test_civclient.py new file mode 100644 index 0000000..bf0c8d8 --- /dev/null +++ b/test/t/test_civclient.py @@ -0,0 +1,7 @@ +import pytest + + +class TestCivclient: + @pytest.mark.complete("civclient -", require_cmd=True) + def test_1(self, completion): + assert completion diff --git a/test/t/test_civserver.py b/test/t/test_civserver.py new file mode 100644 index 0000000..0b8e5d5 --- /dev/null +++ b/test/t/test_civserver.py @@ -0,0 +1,7 @@ +import pytest + + +class TestCivserver: + @pytest.mark.complete("civserver -", require_cmd=True) + def test_1(self, completion): + assert completion diff --git a/test/t/test_cksfv.py b/test/t/test_cksfv.py new file mode 100644 index 0000000..b365659 --- /dev/null +++ b/test/t/test_cksfv.py @@ -0,0 +1,7 @@ +import pytest + + +class TestCksfv: + @pytest.mark.complete("cksfv -", require_cmd=True) + def test_1(self, completion): + assert completion diff --git a/test/t/test_cleanarch.py b/test/t/test_cleanarch.py new file mode 100644 index 0000000..95b268e --- /dev/null +++ b/test/t/test_cleanarch.py @@ -0,0 +1,8 @@ +import pytest + + +@pytest.mark.bashcomp(pre_cmds=("PATH=/usr/lib/mailman/bin:$PATH",)) +class TestCleanarch: + @pytest.mark.complete("cleanarch -") + def test_1(self, completion): + assert completion diff --git a/test/t/test_clisp.py b/test/t/test_clisp.py new file mode 100644 index 0000000..3fcb259 --- /dev/null +++ b/test/t/test_clisp.py @@ -0,0 +1,7 @@ +import pytest + + +class TestClisp: + @pytest.mark.complete("clisp ") + def test_1(self, completion): + assert completion diff --git a/test/t/test_clone_member.py b/test/t/test_clone_member.py new file mode 100644 index 0000000..8f54298 --- /dev/null +++ b/test/t/test_clone_member.py @@ -0,0 +1,7 @@ +import pytest + + +class TestCloneMember: + @pytest.mark.complete("clone_member -") + def test_1(self, completion): + assert completion diff --git a/test/t/test_co.py b/test/t/test_co.py new file mode 100644 index 0000000..0404b45 --- /dev/null +++ b/test/t/test_co.py @@ -0,0 +1,7 @@ +import pytest + + +class TestCo: + @pytest.mark.complete("co ") + def test_1(self, completion): + assert completion diff --git a/test/t/test_colordiff.py b/test/t/test_colordiff.py new file mode 100644 index 0000000..f0e0a29 --- /dev/null +++ b/test/t/test_colordiff.py @@ -0,0 +1,11 @@ +import pytest + + +class TestColordiff: + @pytest.mark.complete("colordiff ") + def test_basic(self, completion): + assert completion + + @pytest.mark.complete("colordiff -", require_cmd=True) + def test_options(self, completion): + assert completion diff --git a/test/t/test_compare.py b/test/t/test_compare.py new file mode 100644 index 0000000..172c8da --- /dev/null +++ b/test/t/test_compare.py @@ -0,0 +1,7 @@ +import pytest + + +class TestCompare: + @pytest.mark.complete("compare ") + def test_1(self, completion): + assert completion diff --git a/test/t/test_compgen.py b/test/t/test_compgen.py new file mode 100644 index 0000000..893abdf --- /dev/null +++ b/test/t/test_compgen.py @@ -0,0 +1,7 @@ +import pytest + + +class TestCompgen: + @pytest.mark.complete(r"compgen -f a\'b/", cwd="compgen") + def test_1(self, completion): + assert not completion diff --git a/test/t/test_complete.py b/test/t/test_complete.py new file mode 100644 index 0000000..7ff56b4 --- /dev/null +++ b/test/t/test_complete.py @@ -0,0 +1,11 @@ +import pytest + + +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_composite.py b/test/t/test_composite.py new file mode 100644 index 0000000..58f4e39 --- /dev/null +++ b/test/t/test_composite.py @@ -0,0 +1,7 @@ +import pytest + + +class TestComposite: + @pytest.mark.complete("composite ") + def test_1(self, completion): + assert completion diff --git a/test/t/test_config_list.py b/test/t/test_config_list.py new file mode 100644 index 0000000..d17fadc --- /dev/null +++ b/test/t/test_config_list.py @@ -0,0 +1,7 @@ +import pytest + + +class TestConfigList: + @pytest.mark.complete("config_list -") + def test_1(self, completion): + assert completion diff --git a/test/t/test_configure.py b/test/t/test_configure.py new file mode 100644 index 0000000..0fc6117 --- /dev/null +++ b/test/t/test_configure.py @@ -0,0 +1,17 @@ +import pytest + + +@pytest.mark.bashcomp( + pre_cmds=( + # Make sure our own ./configure is in PATH + "PATH=$PWD/../..:$PATH", + ) +) +class TestConfigure: + @pytest.mark.complete("configure --", require_cmd=True) + def test_1(self, completion): + assert completion + + @pytest.mark.complete("configure --prefix ") + def test_2(self, completion): + assert completion diff --git a/test/t/test_conjure.py b/test/t/test_conjure.py new file mode 100644 index 0000000..3dcc0db --- /dev/null +++ b/test/t/test_conjure.py @@ -0,0 +1,7 @@ +import pytest + + +class TestConjure: + @pytest.mark.complete("conjure ") + def test_1(self, completion): + assert completion diff --git a/test/t/test_convert.py b/test/t/test_convert.py new file mode 100644 index 0000000..c903ea0 --- /dev/null +++ b/test/t/test_convert.py @@ -0,0 +1,15 @@ +import pytest + + +class TestConvert: + @pytest.mark.complete("convert ") + def test_1(self, completion): + assert completion + + @pytest.mark.complete("convert -format ") + def test_2(self, completion): + assert completion + + @pytest.mark.complete("convert -", require_cmd=True) + def test_3(self, completion): + assert completion diff --git a/test/t/test_cowsay.py b/test/t/test_cowsay.py new file mode 100644 index 0000000..2920d9e --- /dev/null +++ b/test/t/test_cowsay.py @@ -0,0 +1,7 @@ +import pytest + + +class TestCowsay: + @pytest.mark.complete("cowsay ") + def test_1(self, completion): + assert completion diff --git a/test/t/test_cp.py b/test/t/test_cp.py new file mode 100644 index 0000000..7634df7 --- /dev/null +++ b/test/t/test_cp.py @@ -0,0 +1,11 @@ +import pytest + + +class TestCp: + @pytest.mark.complete("cp ") + def test_1(self, completion): + assert completion + + @pytest.mark.complete("cp -", require_longopt=True) + def test_options(self, completion): + assert completion diff --git a/test/t/test_cpan2dist.py b/test/t/test_cpan2dist.py new file mode 100644 index 0000000..1ab5de1 --- /dev/null +++ b/test/t/test_cpan2dist.py @@ -0,0 +1,9 @@ +import pytest + + +class TestCpan2dist: + @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 new file mode 100644 index 0000000..0b73966 --- /dev/null +++ b/test/t/test_cpio.py @@ -0,0 +1,12 @@ +import pytest + + +class TestCpio: + @pytest.mark.complete("cpio --") + def test_1(self, completion): + assert completion + + @pytest.mark.complete("cpio -R ") + def test_2(self, bash, completion, output_sort_uniq): + users = output_sort_uniq("compgen -u") + assert completion == users diff --git a/test/t/test_cplusplus.py b/test/t/test_cplusplus.py new file mode 100644 index 0000000..a2dd3ed --- /dev/null +++ b/test/t/test_cplusplus.py @@ -0,0 +1,8 @@ +import pytest + + +@pytest.mark.bashcomp(cmd="c++") +class TestCPlusPlus: + @pytest.mark.complete("c++ ") + def test_1(self, completion): + assert completion diff --git a/test/t/test_cppcheck.py b/test/t/test_cppcheck.py new file mode 100644 index 0000000..73e64f5 --- /dev/null +++ b/test/t/test_cppcheck.py @@ -0,0 +1,31 @@ +import pytest + + +class TestCppcheck: + @pytest.mark.complete("cppcheck ") + def test_1(self, completion): + assert completion + + @pytest.mark.complete("cppcheck -", require_cmd=True) + def test_2(self, completion): + assert completion + + @pytest.mark.complete("cppcheck -DFOO=BAR ") + def test_3(self, completion): + assert completion + + @pytest.mark.complete("cppcheck -D ") + def test_4(self, completion): + assert not completion + + @pytest.mark.complete("cppcheck --enable=al") + def test_5(self, completion): + assert completion == "l" + + @pytest.mark.complete("cppcheck --enable=xx,styl") + def test_6(self, completion): + assert completion == "e" + + @pytest.mark.complete("cppcheck --enable=xx,yy,styl") + def test_7(self, completion): + assert completion == "e" diff --git a/test/t/test_createdb.py b/test/t/test_createdb.py new file mode 100644 index 0000000..030338a --- /dev/null +++ b/test/t/test_createdb.py @@ -0,0 +1,11 @@ +import pytest + + +class TestCreatedb: + + # --help can fail due to missing package dependencies, e.g. on Ubuntu 14 + @pytest.mark.complete( + "createdb -", require_cmd=True, xfail="! createdb --help &>/dev/null" + ) + def test_1(self, completion): + assert completion diff --git a/test/t/test_createuser.py b/test/t/test_createuser.py new file mode 100644 index 0000000..ea8d0e3 --- /dev/null +++ b/test/t/test_createuser.py @@ -0,0 +1,11 @@ +import pytest + + +class TestCreateuser: + + # --help can fail due to missing package dependencies, e.g. on Ubuntu 14 + @pytest.mark.complete( + "createuser -", xfail="! createuser --help &>/dev/null" + ) + def test_1(self, completion): + assert completion diff --git a/test/t/test_crontab.py b/test/t/test_crontab.py new file mode 100644 index 0000000..a476694 --- /dev/null +++ b/test/t/test_crontab.py @@ -0,0 +1,16 @@ +import pytest + + +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_cryptsetup.py b/test/t/test_cryptsetup.py new file mode 100644 index 0000000..fdc981b --- /dev/null +++ b/test/t/test_cryptsetup.py @@ -0,0 +1,11 @@ +import pytest + + +class TestCryptsetup: + @pytest.mark.complete("cryptsetup ") + def test_1(self, completion): + assert completion + + @pytest.mark.complete("cryptsetup -", require_cmd=True) + def test_2(self, completion): + assert completion diff --git a/test/t/test_csplit.py b/test/t/test_csplit.py new file mode 100644 index 0000000..609c7e5 --- /dev/null +++ b/test/t/test_csplit.py @@ -0,0 +1,11 @@ +import pytest + + +class TestCsplit: + @pytest.mark.complete("csplit ") + def test_1(self, completion): + assert completion + + @pytest.mark.complete("csplit -", require_cmd=True) + def test_options(self, completion): + assert completion diff --git a/test/t/test_curl.py b/test/t/test_curl.py new file mode 100644 index 0000000..63e969f --- /dev/null +++ b/test/t/test_curl.py @@ -0,0 +1,28 @@ +import pytest + + +class TestCurl: + @pytest.mark.complete("curl --h", require_cmd=True) + def test_1(self, completion): + assert completion + + @pytest.mark.complete("curl -o f", cwd="shared/default/foo.d") + def test_2(self, completion): + assert completion == "oo" + + @pytest.mark.complete("curl -LRo f", cwd="shared/default/foo.d") + def test_3(self, completion): + assert completion == "oo" + + @pytest.mark.complete("curl --o f") + def test_4(self, completion): + assert not completion + + @pytest.mark.complete("curl --data @", cwd="shared/default/foo.d") + def test_data_atfile(self, completion): + assert completion == "foo" + + @pytest.mark.complete("curl --data @foo.", cwd="shared/default") + def test_data_atfile_dir(self, completion): + assert completion == "d/" + assert not completion.endswith(" ") diff --git a/test/t/test_cut.py b/test/t/test_cut.py new file mode 100644 index 0000000..b0faca6 --- /dev/null +++ b/test/t/test_cut.py @@ -0,0 +1,11 @@ +import pytest + + +class TestCut: + @pytest.mark.complete("cut ") + def test_1(self, completion): + assert completion + + @pytest.mark.complete("cut -", require_longopt=True) + def test_options(self, completion): + assert completion diff --git a/test/t/test_cvs.py b/test/t/test_cvs.py new file mode 100644 index 0000000..97361e9 --- /dev/null +++ b/test/t/test_cvs.py @@ -0,0 +1,20 @@ +import pytest + + +@pytest.mark.bashcomp(pre_cmds=("HOME=$PWD/cvs",)) +class TestCvs: + @pytest.mark.complete("cvs ") + def test_1(self, completion): + assert completion + + @pytest.mark.complete("cvs -d ") + def test_2(self, completion): + assert [x for x in completion if ":pserver:" in x] + + @pytest.mark.complete("cvs diff foo/", cwd="cvs") + def test_3(self, completion): + assert completion == "bar" + + @pytest.mark.complete("cvs -", require_cmd=True) + def test_4(self, completion): + assert completion diff --git a/test/t/test_cvsps.py b/test/t/test_cvsps.py new file mode 100644 index 0000000..4039893 --- /dev/null +++ b/test/t/test_cvsps.py @@ -0,0 +1,12 @@ +import pytest + + +@pytest.mark.bashcomp(pre_cmds=("HOME=$PWD/cvs",)) +class TestCvsps: + @pytest.mark.complete("cvsps -", require_cmd=True) + def test_1(self, completion): + assert completion + + @pytest.mark.complete("cvsps ") + def test_2(self, completion): + assert [x for x in completion if ":pserver:" in x] diff --git a/test/t/test_date.py b/test/t/test_date.py new file mode 100644 index 0000000..57d61b8 --- /dev/null +++ b/test/t/test_date.py @@ -0,0 +1,11 @@ +import pytest + + +class TestDate: + @pytest.mark.complete("date ") + def test_1(self, completion): + assert completion + + @pytest.mark.complete("date -", require_cmd=True) + def test_options(self, completion): + assert completion diff --git a/test/t/test_dcop.py b/test/t/test_dcop.py new file mode 100644 index 0000000..5c3c04d --- /dev/null +++ b/test/t/test_dcop.py @@ -0,0 +1,7 @@ +import pytest + + +class TestDcop: + @pytest.mark.complete("dcop ", require_cmd=True) + def test_1(self, completion): + assert completion diff --git a/test/t/test_dd.py b/test/t/test_dd.py new file mode 100644 index 0000000..e082faa --- /dev/null +++ b/test/t/test_dd.py @@ -0,0 +1,17 @@ +import pytest + + +class TestDd: + @pytest.mark.complete( + "dd --", + xfail=( + "! dd --help &>/dev/null || " + "! dd --help 2>&1 | command grep -qF -- --help" + ), + ) + def test_1(self, completion): + assert completion + + @pytest.mark.complete("dd bs") + def test_2(self, completion): + assert completion == "=" diff --git a/test/t/test_declare.py b/test/t/test_declare.py new file mode 100644 index 0000000..a61d926 --- /dev/null +++ b/test/t/test_declare.py @@ -0,0 +1,20 @@ +import pytest + + +class TestDeclare: + @pytest.mark.complete("declare -", require_cmd=True) + def test_1(self, completion): + assert completion + + @pytest.mark.complete("declare +", require_cmd=True) + def test_2(self, completion): + assert completion + + @pytest.mark.complete("declare -p BASH_ARG") + def test_3(self, completion): + # bash 5.0 has BASH_ARGV0 too + assert all(x in completion for x in "BASH_ARGC BASH_ARGV".split()) + + @pytest.mark.complete("declare -f _parse_") + def test_4(self, completion): + assert "_parse_help" in completion diff --git a/test/t/test_deja_dup.py b/test/t/test_deja_dup.py new file mode 100644 index 0000000..56e59f9 --- /dev/null +++ b/test/t/test_deja_dup.py @@ -0,0 +1,12 @@ +import pytest + + +@pytest.mark.bashcomp(cmd="deja-dup") +class TestDejaDup: + @pytest.mark.complete("deja-dup -", require_cmd=True) + def test_1(self, completion): + assert completion + + @pytest.mark.complete("deja-dup --help ") + def test_2(self, completion): + assert not completion diff --git a/test/t/test_desktop_file_validate.py b/test/t/test_desktop_file_validate.py new file mode 100644 index 0000000..ed4b55b --- /dev/null +++ b/test/t/test_desktop_file_validate.py @@ -0,0 +1,12 @@ +import pytest + + +@pytest.mark.bashcomp(cmd="desktop-file-validate") +class TestDesktopFileValidate: + @pytest.mark.complete("desktop-file-validate ") + def test_1(self, completion): + assert completion + + @pytest.mark.complete("desktop-file-validate -", require_cmd=True) + def test_2(self, completion): + assert completion diff --git a/test/t/test_df.py b/test/t/test_df.py new file mode 100644 index 0000000..be28e6c --- /dev/null +++ b/test/t/test_df.py @@ -0,0 +1,11 @@ +import pytest + + +class TestDf: + @pytest.mark.complete("df ") + def test_1(self, completion): + assert completion + + @pytest.mark.complete("df -", require_longopt=True) + def test_options(self, completion): + assert completion diff --git a/test/t/test_dfutool.py b/test/t/test_dfutool.py new file mode 100644 index 0000000..7b450bd --- /dev/null +++ b/test/t/test_dfutool.py @@ -0,0 +1,7 @@ +import pytest + + +class TestDfutool: + @pytest.mark.complete("dfutool ") + def test_1(self, completion): + assert completion diff --git a/test/t/test_dhclient.py b/test/t/test_dhclient.py new file mode 100644 index 0000000..c6a1af4 --- /dev/null +++ b/test/t/test_dhclient.py @@ -0,0 +1,7 @@ +import pytest + + +class TestDhclient: + @pytest.mark.complete("dhclient -", require_cmd=True) + def test_1(self, completion): + assert completion diff --git a/test/t/test_dict.py b/test/t/test_dict.py new file mode 100644 index 0000000..99c4a21 --- /dev/null +++ b/test/t/test_dict.py @@ -0,0 +1,7 @@ +import pytest + + +class TestDict: + @pytest.mark.complete("dict -", require_cmd=True) + def test_1(self, completion): + assert completion diff --git a/test/t/test_diff.py b/test/t/test_diff.py new file mode 100644 index 0000000..eb81506 --- /dev/null +++ b/test/t/test_diff.py @@ -0,0 +1,7 @@ +import pytest + + +class TestDiff: + @pytest.mark.complete("diff --", require_cmd=True) + def test_1(self, completion): + assert completion diff --git a/test/t/test_dir.py b/test/t/test_dir.py new file mode 100644 index 0000000..f8568fb --- /dev/null +++ b/test/t/test_dir.py @@ -0,0 +1,11 @@ +import pytest + + +class TestDir: + @pytest.mark.complete("dir ") + def test_1(self, completion): + assert completion + + @pytest.mark.complete("dir -", require_cmd=True) + def test_options(self, completion): + assert completion diff --git a/test/t/test_display.py b/test/t/test_display.py new file mode 100644 index 0000000..4f076b8 --- /dev/null +++ b/test/t/test_display.py @@ -0,0 +1,11 @@ +import pytest + + +class TestDisplay: + @pytest.mark.complete("display ") + def test_1(self, completion): + assert completion + + @pytest.mark.complete("display -", require_cmd=True) + def test_2(self, completion): + assert completion diff --git a/test/t/test_dmesg.py b/test/t/test_dmesg.py new file mode 100644 index 0000000..a081fb6 --- /dev/null +++ b/test/t/test_dmesg.py @@ -0,0 +1,7 @@ +import pytest + + +class TestDmesg: + @pytest.mark.complete("dmesg -", require_cmd=True) + def test_1(self, completion): + assert completion diff --git a/test/t/test_dmypy.py b/test/t/test_dmypy.py new file mode 100644 index 0000000..4c031dd --- /dev/null +++ b/test/t/test_dmypy.py @@ -0,0 +1,14 @@ +import pytest + + +class TestDmypy: + @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, 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 new file mode 100644 index 0000000..f8bd6fb --- /dev/null +++ b/test/t/test_dnssec_keygen.py @@ -0,0 +1,80 @@ +import pytest + + +@pytest.mark.bashcomp( + cmd="dnssec-keygen", pre_cmds=("PATH=$PATH:$PWD/dnssec-keygen",) +) +class TestDnssecKeygen: + @pytest.mark.complete("dnssec-keygen -") + def test_1(self, completion): + assert completion + assert not any(x.endswith(":") for x in completion) + + @pytest.mark.complete("dnssec-keygen -a ") + def test_2(self, completion): + assert 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) + + @pytest.mark.complete("dnssec-keygen -n ") + def test_3(self, completion): + assert completion + assert "HOST" in completion + assert "|" not in completion + assert not any(x.startswith("-") for x in completion) + + @pytest.mark.complete("dnssec-keygen -f ") + def test_4(self, completion): + assert completion + assert "|" not in completion + assert not any(x.startswith("-") for x in completion) + + @pytest.mark.complete("dnssec-keygen ") + def test_5(self, completion): + assert not completion + + @pytest.mark.complete( + "dnssec-keygen -a ", env=dict(PATH="$PWD/dnssec-keygen:$PATH") + ) + def test_6(self, completion): + assert completion == sorted( + "RSA RSAMD5 DSA RSASHA1 NSEC3RSASHA1 NSEC3DSA " + "RSASHA256 RSASHA512 ECCGOST " + "ECDSAP256SHA256 ECDSAP384SHA384 " + "ED25519 ED448 DH " + "HMAC-MD5 HMAC-SHA1 HMAC-SHA224 HMAC-SHA256 " + "HMAC-SHA384 HMAC-SHA512".split() + ) + + @pytest.mark.complete( + "dnssec-keygen -n ", env=dict(PATH="$PWD/dnssec-keygen:$PATH") + ) + def test_7(self, completion): + assert completion == sorted("ZONE HOST ENTITY USER OTHER".split()) + + @pytest.mark.complete( + "dnssec-keygen -f ", env=dict(PATH="$PWD/dnssec-keygen:$PATH") + ) + def test_8(self, completion): + assert completion == sorted("KSK REVOKE".split()) + + @pytest.mark.complete( + "dnssec-keygen -T ", env=dict(PATH="$PWD/dnssec-keygen:$PATH") + ) + def test_9(self, completion): + assert completion == sorted("DNSKEY KEY".split()) + + @pytest.mark.complete( + "dnssec-keygen -t ", env=dict(PATH="$PWD/dnssec-keygen:$PATH") + ) + def test_10(self, completion): + assert completion == sorted( + "AUTHCONF NOAUTHCONF NOAUTH NOCONF".split() + ) + + @pytest.mark.complete( + "dnssec-keygen -m ", env=dict(PATH="$PWD/dnssec-keygen:$PATH") + ) + def test_11(self, completion): + assert completion == sorted("usage trace record size mctx".split()) diff --git a/test/t/test_dnsspoof.py b/test/t/test_dnsspoof.py new file mode 100644 index 0000000..b3380d1 --- /dev/null +++ b/test/t/test_dnsspoof.py @@ -0,0 +1,7 @@ +import pytest + + +class TestDnsspoof: + @pytest.mark.complete("dnsspoof -", require_cmd=True) + def test_1(self, completion): + assert completion diff --git a/test/t/test_dot.py b/test/t/test_dot.py new file mode 100644 index 0000000..a4aa674 --- /dev/null +++ b/test/t/test_dot.py @@ -0,0 +1,7 @@ +import pytest + + +class TestDot: + @pytest.mark.complete("dot ") + def test_1(self, completion): + assert completion diff --git a/test/t/test_dpkg.py b/test/t/test_dpkg.py new file mode 100644 index 0000000..eb1228b --- /dev/null +++ b/test/t/test_dpkg.py @@ -0,0 +1,15 @@ +import pytest + + +class TestDpkg: + @pytest.mark.complete("dpkg --c", require_cmd=True) + def test_1(self, completion): + assert completion + + @pytest.mark.complete("dpkg -L ", xfail='test -z "$(dpkg -l 2>/dev/null)"') + def test_2(self, completion): + assert completion + + @pytest.mark.complete("dpkg -i ~") + def test_3(self, completion): + assert completion diff --git a/test/t/test_dpkg_deb.py b/test/t/test_dpkg_deb.py new file mode 100644 index 0000000..9be85eb --- /dev/null +++ b/test/t/test_dpkg_deb.py @@ -0,0 +1,12 @@ +import pytest + + +@pytest.mark.bashcomp(cmd="dpkg-deb") +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 0000000..37c5621 --- /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_dpkg_reconfigure.py b/test/t/test_dpkg_reconfigure.py new file mode 100644 index 0000000..46347b3 --- /dev/null +++ b/test/t/test_dpkg_reconfigure.py @@ -0,0 +1,8 @@ +import pytest + + +@pytest.mark.bashcomp(cmd="dpkg-reconfigure") +class TestDpkgReconfigure: + @pytest.mark.complete("dpkg-reconfigure --") + def test_1(self, completion): + assert completion diff --git a/test/t/test_dpkg_source.py b/test/t/test_dpkg_source.py new file mode 100644 index 0000000..f2d5f19 --- /dev/null +++ b/test/t/test_dpkg_source.py @@ -0,0 +1,8 @@ +import pytest + + +@pytest.mark.bashcomp(cmd="dpkg-source") +class TestDpkgSource: + @pytest.mark.complete("dpkg-source -") + def test_1(self, completion): + assert completion diff --git a/test/t/test_dropdb.py b/test/t/test_dropdb.py new file mode 100644 index 0000000..2f65857 --- /dev/null +++ b/test/t/test_dropdb.py @@ -0,0 +1,11 @@ +import pytest + + +class TestDropdb: + + # --help can fail due to missing package dependencies, e.g. on Ubuntu 14 + @pytest.mark.complete( + "dropdb -", require_cmd=True, xfail="! dropdb --help &>/dev/null" + ) + def test_1(self, completion): + assert completion diff --git a/test/t/test_dropuser.py b/test/t/test_dropuser.py new file mode 100644 index 0000000..83a99d9 --- /dev/null +++ b/test/t/test_dropuser.py @@ -0,0 +1,7 @@ +import pytest + + +class TestDropuser: + @pytest.mark.complete("dropuser ") + def test_1(self, completion): + assert completion diff --git a/test/t/test_dselect.py b/test/t/test_dselect.py new file mode 100644 index 0000000..8e9d24e --- /dev/null +++ b/test/t/test_dselect.py @@ -0,0 +1,11 @@ +import pytest + + +class TestDselect: + @pytest.mark.complete("dselect ") + def test_1(self, completion): + assert completion + + @pytest.mark.complete("dselect -", require_cmd=True) + def test_2(self, completion): + assert completion diff --git a/test/t/test_dsniff.py b/test/t/test_dsniff.py new file mode 100644 index 0000000..978c436 --- /dev/null +++ b/test/t/test_dsniff.py @@ -0,0 +1,7 @@ +import pytest + + +class TestDsniff: + @pytest.mark.complete("dsniff -") + def test_1(self, completion): + assert completion diff --git a/test/t/test_du.py b/test/t/test_du.py new file mode 100644 index 0000000..3d73e99 --- /dev/null +++ b/test/t/test_du.py @@ -0,0 +1,11 @@ +import pytest + + +class TestDu: + @pytest.mark.complete("du ") + def test_1(self, completion): + assert completion + + @pytest.mark.complete("du -", require_longopt=True) + def test_options(self, completion): + assert completion diff --git a/test/t/test_dumpdb.py b/test/t/test_dumpdb.py new file mode 100644 index 0000000..5077682 --- /dev/null +++ b/test/t/test_dumpdb.py @@ -0,0 +1,8 @@ +import pytest + + +@pytest.mark.bashcomp(pre_cmds=("PATH=/usr/lib/mailman/bin:$PATH",)) +class TestDumpdb: + @pytest.mark.complete("dumpdb ") + def test_1(self, completion): + assert completion diff --git a/test/t/test_dumpe2fs.py b/test/t/test_dumpe2fs.py new file mode 100644 index 0000000..eacb1fe --- /dev/null +++ b/test/t/test_dumpe2fs.py @@ -0,0 +1,11 @@ +import pytest + + +class TestDumpe2fs: + @pytest.mark.complete("dumpe2fs ") + def test_1(self, completion): + assert completion + + @pytest.mark.complete("dumpe2fs -", require_cmd=True) + def test_2(self, completion): + assert completion diff --git a/test/t/test_e2freefrag.py b/test/t/test_e2freefrag.py new file mode 100644 index 0000000..10eb41d --- /dev/null +++ b/test/t/test_e2freefrag.py @@ -0,0 +1,11 @@ +import pytest + + +class TestE2freefrag: + @pytest.mark.complete("e2freefrag ") + def test_1(self, completion): + assert completion + + @pytest.mark.complete("e2freefrag -", require_cmd=True) + def test_2(self, completion): + assert completion diff --git a/test/t/test_e2label.py b/test/t/test_e2label.py new file mode 100644 index 0000000..ca436a6 --- /dev/null +++ b/test/t/test_e2label.py @@ -0,0 +1,7 @@ +import pytest + + +class TestE2label: + @pytest.mark.complete("e2label ") + def test_1(self, completion): + assert completion diff --git a/test/t/test_ebtables.py b/test/t/test_ebtables.py new file mode 100644 index 0000000..bcca3cb --- /dev/null +++ b/test/t/test_ebtables.py @@ -0,0 +1,7 @@ +import pytest + + +class TestEbtables: + @pytest.mark.complete("ebtables -") + def test_1(self, completion): + assert completion diff --git a/test/t/test_ecryptfs_migrate_home.py b/test/t/test_ecryptfs_migrate_home.py new file mode 100644 index 0000000..f2115d2 --- /dev/null +++ b/test/t/test_ecryptfs_migrate_home.py @@ -0,0 +1,12 @@ +import pytest + + +@pytest.mark.bashcomp(cmd="ecryptfs-migrate-home") +class TestEcryptfsMigrateHome: + @pytest.mark.complete("ecryptfs-migrate-home ", require_cmd=True) + def test_1(self, completion): + assert completion + + @pytest.mark.complete("ecryptfs-migrate-home -", require_cmd=True) + def test_2(self, completion): + assert completion diff --git a/test/t/test_eject.py b/test/t/test_eject.py new file mode 100644 index 0000000..d4ec1bd --- /dev/null +++ b/test/t/test_eject.py @@ -0,0 +1,7 @@ +import pytest + + +class TestEject: + @pytest.mark.complete("eject -", require_cmd=True) + def test_1(self, completion): + assert completion diff --git a/test/t/test_enscript.py b/test/t/test_enscript.py new file mode 100644 index 0000000..97120e3 --- /dev/null +++ b/test/t/test_enscript.py @@ -0,0 +1,7 @@ +import pytest + + +class TestEnscript: + @pytest.mark.complete("enscript --", require_cmd=True) + def test_1(self, completion): + assert completion diff --git a/test/t/test_env.py b/test/t/test_env.py new file mode 100644 index 0000000..3d1a684 --- /dev/null +++ b/test/t/test_env.py @@ -0,0 +1,7 @@ +import pytest + + +class TestEnv: + @pytest.mark.complete("env --", require_longopt=True) + def test_1(self, completion): + assert completion diff --git a/test/t/test_eog.py b/test/t/test_eog.py new file mode 100644 index 0000000..5ae21d9 --- /dev/null +++ b/test/t/test_eog.py @@ -0,0 +1,11 @@ +import pytest + + +class TestEog: + @pytest.mark.complete("eog ") + def test_1(self, completion): + assert completion + + @pytest.mark.complete("eog -", require_cmd=True) + def test_2(self, completion): + assert completion diff --git a/test/t/test_ether_wake.py b/test/t/test_ether_wake.py new file mode 100644 index 0000000..7afe286 --- /dev/null +++ b/test/t/test_ether_wake.py @@ -0,0 +1,18 @@ +import os + +import pytest + + +@pytest.mark.bashcomp(cmd="ether-wake") +class TestEtherWake: + @pytest.mark.xfail( + os.environ.get("NETWORK") == "none", + reason="MAC addresses may be N/A with no networking configured", + ) + @pytest.mark.complete("ether-wake ") + def test_1(self, completion): + assert completion + + @pytest.mark.complete("ether-wake -", require_cmd=True) + def test_2(self, completion): + assert completion diff --git a/test/t/test_etherwake.py b/test/t/test_etherwake.py new file mode 100644 index 0000000..b444b43 --- /dev/null +++ b/test/t/test_etherwake.py @@ -0,0 +1,7 @@ +import pytest + + +class TestEtherwake: + @pytest.mark.complete("etherwake -") + def test_1(self, completion): + assert completion diff --git a/test/t/test_evince.py b/test/t/test_evince.py new file mode 100644 index 0000000..9e9245d --- /dev/null +++ b/test/t/test_evince.py @@ -0,0 +1,22 @@ +import pytest + + +class TestEvince: + @pytest.mark.complete("evince ", cwd="evince") + def test_1(self, completion): + # .txt should not be here + assert completion == sorted( + "foo/ .bmp .BMP .cbr .CBR .cbz .CBZ .djv .DJV .djvu .DJVU .dvi " + ".DVI .dvi.bz2 .dvi.BZ2 .DVI.bz2 .DVI.BZ2 .dvi.gz .dvi.GZ " + ".DVI.gz .DVI.GZ .eps .EPS .eps.bz2 .eps.BZ2 .EPS.bz2 .EPS.BZ2 " + ".eps.gz .eps.GZ .EPS.gz .EPS.GZ .gif .GIF .ico .ICO .jpeg " + ".JPEG .jpg .JPG .miff .MIFF .pbm .PBM .pcx .PCX .pdf .PDF " + ".pdf.bz2 .pdf.BZ2 .PDF.bz2 .PDF.BZ2 .pdf.gz .pdf.GZ .PDF.gz " + ".PDF.GZ .pgm .PGM .png .PNG .pnm .PNM .ppm .PPM .ps .PS " + ".ps.bz2 .ps.BZ2 .PS.bz2 .PS.BZ2 .ps.gz .ps.GZ .PS.gz .PS.GZ " + ".tga .TGA .tif .TIF .tiff .TIFF .xpm .XPM .xwd .XWD".split() + ) + + @pytest.mark.complete("evince -", require_cmd=True) + def test_2(self, completion): + assert completion diff --git a/test/t/test_expand.py b/test/t/test_expand.py new file mode 100644 index 0000000..11f4bdb --- /dev/null +++ b/test/t/test_expand.py @@ -0,0 +1,7 @@ +import pytest + + +class TestExpand: + @pytest.mark.complete("expand --", require_longopt=True) + def test_1(self, completion): + assert completion diff --git a/test/t/test_explodepkg.py b/test/t/test_explodepkg.py new file mode 100644 index 0000000..940fec8 --- /dev/null +++ b/test/t/test_explodepkg.py @@ -0,0 +1,23 @@ +import fnmatch +import os + +import pytest + + +class TestExplodepkg: + @pytest.mark.complete("explodepkg ", cwd="slackware/home") + def test_1(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 == expected diff --git a/test/t/test_export.py b/test/t/test_export.py new file mode 100644 index 0000000..8738913 --- /dev/null +++ b/test/t/test_export.py @@ -0,0 +1,36 @@ +import pytest + + +class TestExport: + @pytest.mark.complete("export BASH") + def test_1(self, completion): + assert completion + + @pytest.mark.complete("export -n BASH") + def test_2(self, completion): + assert completion + + @pytest.mark.complete("export -p ") + def test_3(self, completion): + assert not completion + + @pytest.mark.complete("export FOO=", cwd="shared/default") + def test_4(self, completion): + assert completion == ["bar", "bar bar.d/", "foo", "foo.d/"] + + @pytest.mark.complete("export FOO=f", cwd="shared/default") + def test_5(self, completion): + assert completion == ["foo", "foo.d/"] + + @pytest.mark.complete("export -fn _ex") + def test_6(self, completion): + assert "_expand" in completion + assert "_export" in completion + + @pytest.mark.complete(r"export FOO=$BASH") + def test_7(self, completion): + assert completion + + @pytest.mark.complete("export -", require_cmd=True) + def test_8(self, completion): + assert completion diff --git a/test/t/test_faillog.py b/test/t/test_faillog.py new file mode 100644 index 0000000..edf490b --- /dev/null +++ b/test/t/test_faillog.py @@ -0,0 +1,7 @@ +import pytest + + +class TestFaillog: + @pytest.mark.complete("faillog -", require_cmd=True) + def test_1(self, completion): + assert completion diff --git a/test/t/test_fbgs.py b/test/t/test_fbgs.py new file mode 100644 index 0000000..53ff741 --- /dev/null +++ b/test/t/test_fbgs.py @@ -0,0 +1,7 @@ +import pytest + + +class TestFbgs: + @pytest.mark.complete("fbgs ") + def test_1(self, completion): + assert completion diff --git a/test/t/test_fbi.py b/test/t/test_fbi.py new file mode 100644 index 0000000..e27fef5 --- /dev/null +++ b/test/t/test_fbi.py @@ -0,0 +1,7 @@ +import pytest + + +class TestFbi: + @pytest.mark.complete("fbi ") + def test_1(self, completion): + assert completion diff --git a/test/t/test_feh.py b/test/t/test_feh.py new file mode 100644 index 0000000..f2d5317 --- /dev/null +++ b/test/t/test_feh.py @@ -0,0 +1,31 @@ +import pytest + + +class TestFeh: + @pytest.mark.complete("feh ") + def test_1(self, completion): + assert completion + + @pytest.mark.complete( + "feh --lis", + xfail="feh --help 2>&1 | command grep -qF 'man feh'", + require_cmd=True, + ) + def test_2(self, completion): + assert completion + + @pytest.mark.complete("feh -S pix") + def test_3(self, completion): + assert completion == "els" + + @pytest.mark.complete("feh --zoom ma") + def test_4(self, completion): + assert completion == "x" + + @pytest.mark.complete("feh -g 640") + def test_5(self, completion): + assert completion == "0 1 2 3 4 5 6 7 8 9 x".split() + + @pytest.mark.complete("feh -g 640x48") + def test_6(self, completion): + assert completion == "0 1 2 3 4 5 6 7 8 9".split() diff --git a/test/t/test_file.py b/test/t/test_file.py new file mode 100644 index 0000000..0c19eb4 --- /dev/null +++ b/test/t/test_file.py @@ -0,0 +1,11 @@ +import pytest + + +class TestFile: + @pytest.mark.complete("file ") + def test_1(self, completion): + assert completion + + @pytest.mark.complete("file -", require_cmd=True) + def test_2(self, completion): + assert completion diff --git a/test/t/test_file_roller.py b/test/t/test_file_roller.py new file mode 100644 index 0000000..80a1bbc --- /dev/null +++ b/test/t/test_file_roller.py @@ -0,0 +1,8 @@ +import pytest + + +@pytest.mark.bashcomp(cmd="file-roller") +class TestFileRoller: + @pytest.mark.complete("file-roller ") + def test_1(self, completion): + assert completion diff --git a/test/t/test_filefrag.py b/test/t/test_filefrag.py new file mode 100644 index 0000000..342e89c --- /dev/null +++ b/test/t/test_filefrag.py @@ -0,0 +1,11 @@ +import pytest + + +class TestFilefrag: + @pytest.mark.complete("filefrag ") + def test_1(self, completion): + assert completion + + @pytest.mark.complete("filefrag -", require_cmd=True) + def test_2(self, completion): + assert completion diff --git a/test/t/test_filesnarf.py b/test/t/test_filesnarf.py new file mode 100644 index 0000000..cee621e --- /dev/null +++ b/test/t/test_filesnarf.py @@ -0,0 +1,7 @@ +import pytest + + +class TestFilesnarf: + @pytest.mark.complete("filesnarf -", require_cmd=True) + def test_1(self, completion): + assert completion diff --git a/test/t/test_find.py b/test/t/test_find.py new file mode 100644 index 0000000..9968ade --- /dev/null +++ b/test/t/test_find.py @@ -0,0 +1,37 @@ +import pytest + + +class TestFind: + @pytest.mark.complete("find ") + def test_1(self, completion): + assert completion + + @pytest.mark.complete("find -fstype ") + def test_2(self, completion): + assert completion + + @pytest.mark.complete("find -") + def test_3(self, completion): + assert completion + + @pytest.mark.complete("find -wholename ", cwd="shared/default") + def test_4(self, completion): + assert completion == ["bar", "bar bar.d/", "foo", "foo.d/"] + + @pytest.mark.complete("find -uid ") + def test_5(self, completion): + assert not [x for x in completion if not x.isdigit()] + + @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_find_member.py b/test/t/test_find_member.py new file mode 100644 index 0000000..bfcf588 --- /dev/null +++ b/test/t/test_find_member.py @@ -0,0 +1,7 @@ +import pytest + + +class TestFindMember: + @pytest.mark.complete("find_member -") + def test_1(self, completion): + assert completion diff --git a/test/t/test_finger.py b/test/t/test_finger.py new file mode 100644 index 0000000..d765fdd --- /dev/null +++ b/test/t/test_finger.py @@ -0,0 +1,33 @@ +import pytest + +from conftest import assert_complete, partialize + + +class TestFinger: + @pytest.fixture(scope="class") + 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): + assert completion == users_at + + @pytest.mark.complete("finger r") + def test_2(self, bash, completion, users_at): + if not any(x.startswith("r") for x in users_at): + pytest.skip("No users starting with r") + assert 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_fio.py b/test/t/test_fio.py new file mode 100644 index 0000000..0f6eba7 --- /dev/null +++ b/test/t/test_fio.py @@ -0,0 +1,15 @@ +import pytest + + +class TestFio: + @pytest.mark.complete("fio ") + def test_1(self, completion): + assert completion + + @pytest.mark.complete("fio --", require_cmd=True) + def test_2(self, completion): + assert completion + + @pytest.mark.complete("fio --debug=foo,") + def test_3(self, completion): + assert completion diff --git a/test/t/test_firefox.py b/test/t/test_firefox.py new file mode 100644 index 0000000..2e05255 --- /dev/null +++ b/test/t/test_firefox.py @@ -0,0 +1,12 @@ +import pytest + + +class TestFirefox: + @pytest.mark.complete("firefox ") + def test_1(self, completion): + assert completion + + @pytest.mark.complete("firefox -", require_cmd=True) + def test_2(self, completion): + assert completion + assert not completion.endswith(" ") diff --git a/test/t/test_flake8.py b/test/t/test_flake8.py new file mode 100644 index 0000000..67649fa --- /dev/null +++ b/test/t/test_flake8.py @@ -0,0 +1,17 @@ +import pytest + + +class TestFlake8: + @pytest.mark.complete("flake8 ") + def test_1(self, completion): + assert completion + + @pytest.mark.complete( + "flake8 -", require_cmd=True, xfail="! flake8 --help &>/dev/null" + ) + def test_2(self, completion): + assert completion + + @pytest.mark.complete("flake8 --doesnt-exist=") + def test_3(self, completion): + assert not completion diff --git a/test/t/test_fmt.py b/test/t/test_fmt.py new file mode 100644 index 0000000..12706da --- /dev/null +++ b/test/t/test_fmt.py @@ -0,0 +1,9 @@ +import pytest + + +class TestFmt: + @pytest.mark.complete( + "fmt -", require_cmd=True, xfail="! fmt --help &>/dev/null" + ) + def test_1(self, completion): + assert completion diff --git a/test/t/test_fold.py b/test/t/test_fold.py new file mode 100644 index 0000000..1cbaef9 --- /dev/null +++ b/test/t/test_fold.py @@ -0,0 +1,7 @@ +import pytest + + +class TestFold: + @pytest.mark.complete("fold --", require_longopt=True) + def test_1(self, completion): + assert completion diff --git a/test/t/test_freebsd_update.py b/test/t/test_freebsd_update.py new file mode 100644 index 0000000..911a49a --- /dev/null +++ b/test/t/test_freebsd_update.py @@ -0,0 +1,8 @@ +import pytest + + +@pytest.mark.bashcomp(cmd="freebsd-update") +class TestFreebsdUpdate: + @pytest.mark.complete("freebsd-update ") + def test_1(self, completion): + assert completion diff --git a/test/t/test_freeciv.py b/test/t/test_freeciv.py new file mode 100644 index 0000000..a195eb8 --- /dev/null +++ b/test/t/test_freeciv.py @@ -0,0 +1,7 @@ +import pytest + + +class TestFreeciv: + @pytest.mark.complete("freeciv -", require_cmd=True) + def test_1(self, completion): + assert completion diff --git a/test/t/test_freeciv_server.py b/test/t/test_freeciv_server.py new file mode 100644 index 0000000..8543a21 --- /dev/null +++ b/test/t/test_freeciv_server.py @@ -0,0 +1,8 @@ +import pytest + + +@pytest.mark.bashcomp(cmd="freeciv-server") +class TestFreecivServer: + @pytest.mark.complete("freeciv-server -", require_cmd=True) + def test_1(self, completion): + assert completion diff --git a/test/t/test_function.py b/test/t/test_function.py new file mode 100644 index 0000000..4401f02 --- /dev/null +++ b/test/t/test_function.py @@ -0,0 +1,7 @@ +import pytest + + +class TestFunction: + @pytest.mark.complete("function _parse_") + def test_1(self, completion): + assert completion diff --git a/test/t/test_fusermount.py b/test/t/test_fusermount.py new file mode 100644 index 0000000..dbb2bd9 --- /dev/null +++ b/test/t/test_fusermount.py @@ -0,0 +1,11 @@ +import pytest + + +class TestFusermount: + @pytest.mark.complete("fusermount ") + def test_1(self, completion): + assert completion + + @pytest.mark.complete("fusermount -", require_cmd=True) + def test_2(self, completion): + assert completion diff --git a/test/t/test_g4.py b/test/t/test_g4.py new file mode 100644 index 0000000..739c77d --- /dev/null +++ b/test/t/test_g4.py @@ -0,0 +1,7 @@ +import pytest + + +class TestG4: + @pytest.mark.complete("g4 ") + def test_1(self, completion): + assert completion diff --git a/test/t/test_g77.py b/test/t/test_g77.py new file mode 100644 index 0000000..45da624 --- /dev/null +++ b/test/t/test_g77.py @@ -0,0 +1,7 @@ +import pytest + + +class TestG77: + @pytest.mark.complete("g77 ") + def test_1(self, completion): + assert completion diff --git a/test/t/test_gcc.py b/test/t/test_gcc.py new file mode 100644 index 0000000..50906db --- /dev/null +++ b/test/t/test_gcc.py @@ -0,0 +1,64 @@ +import pytest + +from conftest import assert_bash_exec + + +class TestGcc: + @pytest.fixture(scope="class") + def gcc_with_completion(self, bash): + got = assert_bash_exec( + bash, "gcc --help=common || :", want_output=True + ) + if "--completion" not in got: + pytest.skip("GCC does not support --completion") + + @pytest.fixture(scope="class") + def gcc_x86(self, bash): + got = assert_bash_exec(bash, "gcc -v || :", want_output=True) + if "Target: x86" not in got: + pytest.skip("Not a x86 GCC") + + @pytest.mark.complete("gcc ") + def test_1(self, completion): + assert completion + + @pytest.mark.complete("gcc -fsanitize=add") + def test_enum_value(self, completion, gcc_with_completion): + assert completion == "ress" + + @pytest.mark.complete("gcc -fsanitize=") + def test_enum_value_with_eq(self, completion, gcc_with_completion): + assert "address" in completion + + @pytest.mark.complete("gcc -fno-ipa-ic") + def test_negative_option(self, completion, gcc_with_completion): + assert "-fno-ipa-icf" in completion + + @pytest.mark.complete("gcc -fxyz-abc") + def test_no_completion(self, completion): + assert not completion + + @pytest.mark.complete("gcc --param ") + def test_param_with_space(self, completion, gcc_with_completion): + assert len(completion) > 50 + # starting with GCC 10.1 param end with = + assert ( + "lto-partitions" in completion or "lto-partitions=" in completion + ) + + @pytest.mark.complete("gcc --param=lto-max-p") + def test_param_with_eq(self, completion, gcc_with_completion): + # 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 == "fam10" + + @pytest.mark.complete("gcc -march=") + def test_march_native(self, completion, gcc_with_completion): + assert "native" in completion + + @pytest.mark.complete("gcc -mtune=") + def test_mtune_generic(self, completion, gcc_with_completion): + assert "generic" in completion diff --git a/test/t/test_gcj.py b/test/t/test_gcj.py new file mode 100644 index 0000000..17e2f44 --- /dev/null +++ b/test/t/test_gcj.py @@ -0,0 +1,7 @@ +import pytest + + +class TestGcj: + @pytest.mark.complete("gcj ") + def test_1(self, completion): + assert completion diff --git a/test/t/test_gcl.py b/test/t/test_gcl.py new file mode 100644 index 0000000..f1e7a5f --- /dev/null +++ b/test/t/test_gcl.py @@ -0,0 +1,7 @@ +import pytest + + +class TestGcl: + @pytest.mark.complete("gcl ") + def test_1(self, completion): + assert completion diff --git a/test/t/test_gdb.py b/test/t/test_gdb.py new file mode 100644 index 0000000..2ad12c4 --- /dev/null +++ b/test/t/test_gdb.py @@ -0,0 +1,14 @@ +import pytest + + +class TestGdb: + @pytest.mark.complete("gdb - ") + def test_1(self, completion): + assert completion + + @pytest.mark.complete("gdb foo ", cwd="gdb") + def test_2(self, completion): + assert completion == sorted( + "core core.12345 " + "core.weston.1000.deadbeef.5308.1555362132000000".split() + ) diff --git a/test/t/test_genaliases.py b/test/t/test_genaliases.py new file mode 100644 index 0000000..e2f24d6 --- /dev/null +++ b/test/t/test_genaliases.py @@ -0,0 +1,8 @@ +import pytest + + +@pytest.mark.bashcomp(pre_cmds=("PATH=/usr/lib/mailman/bin:$PATH",)) +class TestGenaliases: + @pytest.mark.complete("genaliases -") + def test_1(self, completion): + assert completion diff --git a/test/t/test_gendiff.py b/test/t/test_gendiff.py new file mode 100644 index 0000000..0e2ab4c --- /dev/null +++ b/test/t/test_gendiff.py @@ -0,0 +1,7 @@ +import pytest + + +class TestGendiff: + @pytest.mark.complete("gendiff ") + def test_1(self, completion): + assert completion diff --git a/test/t/test_genisoimage.py b/test/t/test_genisoimage.py new file mode 100644 index 0000000..bfcef3b --- /dev/null +++ b/test/t/test_genisoimage.py @@ -0,0 +1,11 @@ +import pytest + + +class TestGenisoimage: + @pytest.mark.complete("genisoimage ") + def test_1(self, completion): + assert completion + + @pytest.mark.complete("genisoimage -", require_cmd=True) + def test_2(self, completion): + assert completion diff --git a/test/t/test_geoiplookup.py b/test/t/test_geoiplookup.py new file mode 100644 index 0000000..9a1422b --- /dev/null +++ b/test/t/test_geoiplookup.py @@ -0,0 +1,7 @@ +import pytest + + +class TestGeoiplookup: + @pytest.mark.complete("geoiplookup -", require_cmd=True) + def test_1(self, completion): + assert completion diff --git a/test/t/test_getconf.py b/test/t/test_getconf.py new file mode 100644 index 0000000..c80c803 --- /dev/null +++ b/test/t/test_getconf.py @@ -0,0 +1,25 @@ +import pytest + + +class TestGetconf: + @pytest.mark.complete("getconf P") + def test_1(self, completion): + assert completion + + @pytest.mark.complete("getconf -") + def test_2(self, completion): + assert completion + + @pytest.mark.complete("getconf -a ") + def test_3(self, completion): + assert completion + + @pytest.mark.complete( + "getconf -v ", xfail="! getconf -a 2>&1 | command grep -q ^POSIX_V" + ) + def test_4(self, completion): + assert completion + + @pytest.mark.complete("getconf PATH_MAX ") + def test_5(self, completion): + assert completion diff --git a/test/t/test_getent.py b/test/t/test_getent.py new file mode 100644 index 0000000..a1e9fcb --- /dev/null +++ b/test/t/test_getent.py @@ -0,0 +1,18 @@ +import pytest + + +class TestGetent: + @pytest.mark.complete("getent ") + def test_1(self, completion): + assert completion + + @pytest.mark.complete( + "getent -", + require_cmd=True, + xfail=( + "! (getent --help 2>&1 || :) | " + "command grep -q -- '[[:space:]]-'" + ), + ) + def test_2(self, completion): + assert completion diff --git a/test/t/test_gkrellm.py b/test/t/test_gkrellm.py new file mode 100644 index 0000000..fdc2e16 --- /dev/null +++ b/test/t/test_gkrellm.py @@ -0,0 +1,10 @@ +import os + +import pytest + + +@pytest.mark.xfail(not os.environ.get("DISPLAY"), reason="X display required") +class TestGkrellm: + @pytest.mark.complete("gkrellm -", require_cmd=True) + def test_1(self, completion): + assert completion diff --git a/test/t/test_gm.py b/test/t/test_gm.py new file mode 100644 index 0000000..9cdd73c --- /dev/null +++ b/test/t/test_gm.py @@ -0,0 +1,19 @@ +import pytest + + +class TestGm: + @pytest.mark.complete("gm ", require_cmd=True) + def test_1(self, completion): + assert completion + + @pytest.mark.complete("gm help ", require_cmd=True) + def test_2(self, completion): + assert completion + + @pytest.mark.complete("gm time ", require_cmd=True) + def test_3(self, completion): + assert completion + + @pytest.mark.complete("gm version ") + def test_4(self, completion): + assert not completion diff --git a/test/t/test_gmplayer.py b/test/t/test_gmplayer.py new file mode 100644 index 0000000..211ef51 --- /dev/null +++ b/test/t/test_gmplayer.py @@ -0,0 +1,7 @@ +import pytest + + +class TestGmplayer: + @pytest.mark.complete("gmplayer ") + def test_1(self, completion): + assert completion diff --git a/test/t/test_gnatmake.py b/test/t/test_gnatmake.py new file mode 100644 index 0000000..c9f5609 --- /dev/null +++ b/test/t/test_gnatmake.py @@ -0,0 +1,7 @@ +import pytest + + +class TestGnatmake: + @pytest.mark.complete("gnatmake ") + def test_1(self, completion): + assert completion diff --git a/test/t/test_gnokii.py b/test/t/test_gnokii.py new file mode 100644 index 0000000..66af6e9 --- /dev/null +++ b/test/t/test_gnokii.py @@ -0,0 +1,11 @@ +import pytest + + +class TestGnokii: + @pytest.mark.complete("gnokii ", require_cmd=True) + def test_1(self, completion): + assert completion + + @pytest.mark.complete("gnokii -", require_cmd=True) + def test_2(self, completion): + assert completion diff --git a/test/t/test_gnome_mplayer.py b/test/t/test_gnome_mplayer.py new file mode 100644 index 0000000..379c56c --- /dev/null +++ b/test/t/test_gnome_mplayer.py @@ -0,0 +1,17 @@ +import pytest + + +@pytest.mark.bashcomp(cmd="gnome-mplayer", ignore_env=r"^[+-]XDG_DATA_DIRS=") +class TestGnomeMplayer: + @pytest.mark.complete("gnome-mplayer ") + def test_1(self, completion): + assert completion + + # XDG_DATA_DIRS set to a dir with no schemas results in + # "GLib-GIO-ERROR **: No GSettings schemas are installed on the system" + # and a core dump on --help on Ubuntu 14. + @pytest.mark.complete( + "gnome-mplayer -", require_cmd=True, pre_cmds=("unset XDG_DATA_DIRS",) + ) + def test_2(self, completion): + assert completion diff --git a/test/t/test_gnome_screenshot.py b/test/t/test_gnome_screenshot.py new file mode 100644 index 0000000..977e03f --- /dev/null +++ b/test/t/test_gnome_screenshot.py @@ -0,0 +1,8 @@ +import pytest + + +@pytest.mark.bashcomp(cmd="gnome-screenshot") +class TestGnomeScreenshot: + @pytest.mark.complete("gnome-screenshot --help", require_cmd=True) + def test_1(self, completion): + assert completion diff --git a/test/t/test_gpasswd.py b/test/t/test_gpasswd.py new file mode 100644 index 0000000..4f0221b --- /dev/null +++ b/test/t/test_gpasswd.py @@ -0,0 +1,11 @@ +import pytest + + +class TestGpasswd: + @pytest.mark.complete("gpasswd ") + def test_1(self, completion): + assert completion + + @pytest.mark.complete("gpasswd -", require_cmd=True) + def test_2(self, completion): + assert completion diff --git a/test/t/test_gpc.py b/test/t/test_gpc.py new file mode 100644 index 0000000..9903ef4 --- /dev/null +++ b/test/t/test_gpc.py @@ -0,0 +1,7 @@ +import pytest + + +class TestGpc: + @pytest.mark.complete("gpc ") + def test_1(self, completion): + assert completion diff --git a/test/t/test_gperf.py b/test/t/test_gperf.py new file mode 100644 index 0000000..54f75b1 --- /dev/null +++ b/test/t/test_gperf.py @@ -0,0 +1,7 @@ +import pytest + + +class TestGperf: + @pytest.mark.complete("gperf --", require_cmd=True) + def test_1(self, completion): + assert completion diff --git a/test/t/test_gpg.py b/test/t/test_gpg.py new file mode 100644 index 0000000..8ead5e9 --- /dev/null +++ b/test/t/test_gpg.py @@ -0,0 +1,7 @@ +import pytest + + +class TestGpg: + @pytest.mark.complete("gpg ") + def test_1(self, completion): + assert completion diff --git a/test/t/test_gpg2.py b/test/t/test_gpg2.py new file mode 100644 index 0000000..27a39fa --- /dev/null +++ b/test/t/test_gpg2.py @@ -0,0 +1,7 @@ +import pytest + + +class TestGpg2: + @pytest.mark.complete("gpg2 --h", require_cmd=True) + def test_1(self, completion): + assert completion diff --git a/test/t/test_gpgv.py b/test/t/test_gpgv.py new file mode 100644 index 0000000..d600c74 --- /dev/null +++ b/test/t/test_gpgv.py @@ -0,0 +1,15 @@ +import pytest + + +class TestGpgv: + @pytest.mark.complete("gpgv ") + def test_1(self, completion): + assert completion + + @pytest.mark.complete("gpgv -", require_cmd=True) + def test_2(self, completion): + assert completion + + @pytest.mark.complete("gpgv foo.sig foo ") + def test_3(self, completion): + assert not completion diff --git a/test/t/test_gphoto2.py b/test/t/test_gphoto2.py new file mode 100644 index 0000000..bb987f7 --- /dev/null +++ b/test/t/test_gphoto2.py @@ -0,0 +1,7 @@ +import pytest + + +class TestGphoto2: + @pytest.mark.complete("gphoto2 --", require_cmd=True) + def test_1(self, completion): + assert completion diff --git a/test/t/test_gplusplus.py b/test/t/test_gplusplus.py new file mode 100644 index 0000000..eeeb1bf --- /dev/null +++ b/test/t/test_gplusplus.py @@ -0,0 +1,8 @@ +import pytest + + +@pytest.mark.bashcomp(cmd="g++") +class TestGPlusPlus: + @pytest.mark.complete("g++ ") + def test_1(self, completion): + assert completion diff --git a/test/t/test_gprof.py b/test/t/test_gprof.py new file mode 100644 index 0000000..a30cc1e --- /dev/null +++ b/test/t/test_gprof.py @@ -0,0 +1,7 @@ +import pytest + + +class TestGprof: + @pytest.mark.complete("gprof --", require_cmd=True) + def test_1(self, completion): + assert completion diff --git a/test/t/test_grep.py b/test/t/test_grep.py new file mode 100644 index 0000000..a249122 --- /dev/null +++ b/test/t/test_grep.py @@ -0,0 +1,16 @@ +import pytest + + +class TestGrep: + @pytest.mark.complete("grep --", require_longopt=True) + def test_1(self, completion): + assert completion + + @pytest.mark.complete("grep --no-complete-dir f", cwd="shared/default") + def test_2(self, completion): + """ + Test --no-*dir isn't restricted to dirs only. + + Not really a grep option, but tests _longopt. + """ + assert completion == "foo foo.d/".split() diff --git a/test/t/test_groupadd.py b/test/t/test_groupadd.py new file mode 100644 index 0000000..f882d1e --- /dev/null +++ b/test/t/test_groupadd.py @@ -0,0 +1,11 @@ +import pytest + + +class TestGroupadd: + @pytest.mark.complete("groupadd ") + def test_1(self, completion): + assert not completion + + @pytest.mark.complete("groupadd -", require_cmd=True) + def test_2(self, completion): + assert completion diff --git a/test/t/test_groupdel.py b/test/t/test_groupdel.py new file mode 100644 index 0000000..6e55839 --- /dev/null +++ b/test/t/test_groupdel.py @@ -0,0 +1,11 @@ +import pytest + + +class TestGroupdel: + @pytest.mark.complete("groupdel ") + def test_1(self, completion): + assert completion + + @pytest.mark.complete("groupdel -", require_cmd=True) + def test_2(self, completion): + assert completion diff --git a/test/t/test_groupmems.py b/test/t/test_groupmems.py new file mode 100644 index 0000000..c7b9920 --- /dev/null +++ b/test/t/test_groupmems.py @@ -0,0 +1,7 @@ +import pytest + + +class TestGroupmems: + @pytest.mark.complete("groupmems -", require_cmd=True) + def test_1(self, completion): + assert completion diff --git a/test/t/test_groupmod.py b/test/t/test_groupmod.py new file mode 100644 index 0000000..7097118 --- /dev/null +++ b/test/t/test_groupmod.py @@ -0,0 +1,11 @@ +import pytest + + +class TestGroupmod: + @pytest.mark.complete("groupmod ") + def test_1(self, completion): + assert completion + + @pytest.mark.complete("groupmod -", require_cmd=True) + def test_2(self, completion): + assert completion diff --git a/test/t/test_growisofs.py b/test/t/test_growisofs.py new file mode 100644 index 0000000..7ce19f6 --- /dev/null +++ b/test/t/test_growisofs.py @@ -0,0 +1,7 @@ +import pytest + + +class TestGrowisofs: + @pytest.mark.complete("growisofs ") + def test_1(self, completion): + assert completion diff --git a/test/t/test_grpck.py b/test/t/test_grpck.py new file mode 100644 index 0000000..dcd1485 --- /dev/null +++ b/test/t/test_grpck.py @@ -0,0 +1,11 @@ +import pytest + + +class TestGrpck: + @pytest.mark.complete("grpck ") + def test_1(self, completion): + assert completion + + @pytest.mark.complete("grpck -", require_cmd=True) + def test_2(self, completion): + assert completion diff --git a/test/t/test_grub.py b/test/t/test_grub.py new file mode 100644 index 0000000..4a6929f --- /dev/null +++ b/test/t/test_grub.py @@ -0,0 +1,7 @@ +import pytest + + +class TestGrub: + @pytest.mark.complete("grub --", require_cmd=True) + def test_1(self, completion): + assert completion diff --git a/test/t/test_gssdp_discover.py b/test/t/test_gssdp_discover.py new file mode 100644 index 0000000..b545149 --- /dev/null +++ b/test/t/test_gssdp_discover.py @@ -0,0 +1,22 @@ +import pytest + + +@pytest.mark.bashcomp(cmd="gssdp-discover") +class TestGssdpDiscover: + @pytest.mark.complete("gssdp-discover ") + def test_no_args(self, completion): + assert not completion + + @pytest.mark.complete("gssdp-discover --", require_cmd=True) + def test_options(self, completion): + assert completion + + @pytest.mark.complete( + "gssdp-discover --message-type=", + skipif=( + "! gssdp-discover --help 2>&1 " + "| command grep -qF -- --message-type" + ), + ) + def test_message_type(self, completion): + assert completion diff --git a/test/t/test_gzip.py b/test/t/test_gzip.py new file mode 100644 index 0000000..2173cad --- /dev/null +++ b/test/t/test_gzip.py @@ -0,0 +1,15 @@ +import pytest + + +class TestGzip: + @pytest.mark.complete("gzip ") + def test_1(self, completion): + assert completion + + @pytest.mark.complete("gzip ~") + def test_2(self, completion): + assert completion + + @pytest.mark.complete("gzip -", require_cmd=True) + def test_3(self, completion): + assert completion diff --git a/test/t/test_hciattach.py b/test/t/test_hciattach.py new file mode 100644 index 0000000..2dc1095 --- /dev/null +++ b/test/t/test_hciattach.py @@ -0,0 +1,7 @@ +import pytest + + +class TestHciattach: + @pytest.mark.complete("hciattach ") + def test_1(self, completion): + assert completion diff --git a/test/t/test_hciconfig.py b/test/t/test_hciconfig.py new file mode 100644 index 0000000..2a3f1fd --- /dev/null +++ b/test/t/test_hciconfig.py @@ -0,0 +1,7 @@ +import pytest + + +class TestHciconfig: + @pytest.mark.complete("hciconfig ") + def test_1(self, completion): + assert completion diff --git a/test/t/test_hcitool.py b/test/t/test_hcitool.py new file mode 100644 index 0000000..0885385 --- /dev/null +++ b/test/t/test_hcitool.py @@ -0,0 +1,11 @@ +import pytest + + +class TestHcitool: + @pytest.mark.complete("hcitool ") + def test_1(self, completion): + assert completion + + @pytest.mark.complete("hcitool -", require_cmd=True) + def test_2(self, completion): + assert completion diff --git a/test/t/test_hddtemp.py b/test/t/test_hddtemp.py new file mode 100644 index 0000000..e80a46c --- /dev/null +++ b/test/t/test_hddtemp.py @@ -0,0 +1,7 @@ +import pytest + + +class TestHddtemp: + @pytest.mark.complete("hddtemp -") + def test_1(self, completion): + assert completion diff --git a/test/t/test_head.py b/test/t/test_head.py new file mode 100644 index 0000000..815b938 --- /dev/null +++ b/test/t/test_head.py @@ -0,0 +1,7 @@ +import pytest + + +class TestHead: + @pytest.mark.complete("head --", require_longopt=True) + def test_1(self, completion): + assert completion diff --git a/test/t/test_hexdump.py b/test/t/test_hexdump.py new file mode 100644 index 0000000..03a7b1f --- /dev/null +++ b/test/t/test_hexdump.py @@ -0,0 +1,7 @@ +import pytest + + +class TestHexdump: + @pytest.mark.complete("hexdump -", require_cmd=True) + def test_1(self, completion): + assert completion diff --git a/test/t/test_hid2hci.py b/test/t/test_hid2hci.py new file mode 100644 index 0000000..66766fb --- /dev/null +++ b/test/t/test_hid2hci.py @@ -0,0 +1,8 @@ +import pytest + + +@pytest.mark.bashcomp(pre_cmds=("PATH=/lib/udev:$PATH",)) +class TestHid2hci: + @pytest.mark.complete("hid2hci -") + def test_1(self, completion): + assert completion diff --git a/test/t/test_host.py b/test/t/test_host.py new file mode 100644 index 0000000..2ef1790 --- /dev/null +++ b/test/t/test_host.py @@ -0,0 +1,7 @@ +import pytest + + +class TestHost: + @pytest.mark.complete("host -", require_cmd=True) + def test_1(self, completion): + assert completion diff --git a/test/t/test_hostname.py b/test/t/test_hostname.py new file mode 100644 index 0000000..f644c1e --- /dev/null +++ b/test/t/test_hostname.py @@ -0,0 +1,7 @@ +import pytest + + +class TestHostname: + @pytest.mark.complete("hostname -", require_cmd=True) + def test_1(self, completion): + assert completion diff --git a/test/t/test_hping2.py b/test/t/test_hping2.py new file mode 100644 index 0000000..19665ba --- /dev/null +++ b/test/t/test_hping2.py @@ -0,0 +1,11 @@ +import pytest + + +class TestHping2: + @pytest.mark.complete("hping2 ") + def test_1(self, completion): + assert completion + + @pytest.mark.complete("hping2 -", require_cmd=True) + def test_2(self, completion): + assert completion diff --git a/test/t/test_hping3.py b/test/t/test_hping3.py new file mode 100644 index 0000000..a979cfa --- /dev/null +++ b/test/t/test_hping3.py @@ -0,0 +1,7 @@ +import pytest + + +class TestHping3: + @pytest.mark.complete("hping3 ") + def test_1(self, completion): + assert completion diff --git a/test/t/test_htop.py b/test/t/test_htop.py new file mode 100644 index 0000000..e837c5a --- /dev/null +++ b/test/t/test_htop.py @@ -0,0 +1,7 @@ +import pytest + + +class TestHtop: + @pytest.mark.complete("htop -", require_cmd=True) + def test_1(self, completion): + assert completion diff --git a/test/t/test_htpasswd.py b/test/t/test_htpasswd.py new file mode 100644 index 0000000..92989fa --- /dev/null +++ b/test/t/test_htpasswd.py @@ -0,0 +1,23 @@ +import pytest + + +class TestHtpasswd: + @pytest.mark.complete("htpasswd ") + def test_1(self, completion): + assert completion + + @pytest.mark.complete("htpasswd -n htpasswd/ht") + def test_2(self, completion): + assert not completion + + @pytest.mark.complete("htpasswd ", cwd="htpasswd") + def test_3(self, completion): + assert completion == "htpasswd" + + @pytest.mark.complete("htpasswd -D htpasswd ", cwd="htpasswd") + def test_4(self, completion): + assert completion == "foo quux".split() + + @pytest.mark.complete("htpasswd -", require_cmd=True) + def test_5(self, completion): + assert completion diff --git a/test/t/test_hunspell.py b/test/t/test_hunspell.py new file mode 100644 index 0000000..0f27185 --- /dev/null +++ b/test/t/test_hunspell.py @@ -0,0 +1,11 @@ +import pytest + + +class TestHunspell: + @pytest.mark.complete("hunspell ") + def test_1(self, completion): + assert completion + + @pytest.mark.complete("hunspell -", require_cmd=True) + def test_2(self, completion): + assert completion diff --git a/test/t/test_hwclock.py b/test/t/test_hwclock.py new file mode 100644 index 0000000..4717210 --- /dev/null +++ b/test/t/test_hwclock.py @@ -0,0 +1,7 @@ +import pytest + + +class TestHwclock: + @pytest.mark.complete("hwclock -", require_cmd=True) + def test_1(self, completion): + assert completion diff --git a/test/t/test_iconv.py b/test/t/test_iconv.py new file mode 100644 index 0000000..f42a87f --- /dev/null +++ b/test/t/test_iconv.py @@ -0,0 +1,21 @@ +import pytest + + +class TestIconv: + @pytest.mark.complete( + "iconv -", require_cmd=True, xfail="! iconv --help &>/dev/null" + ) + def test_1(self, completion): + assert completion + + @pytest.mark.complete("iconv -f UTF", require_cmd=True) + def test_2(self, completion): + assert completion + + @pytest.mark.complete("iconv ") + def test_3(self, completion): + assert completion + + @pytest.mark.complete("iconv -f ") + def test_4(self, completion): + assert "..." not in completion diff --git a/test/t/test_id.py b/test/t/test_id.py new file mode 100644 index 0000000..41f2868 --- /dev/null +++ b/test/t/test_id.py @@ -0,0 +1,7 @@ +import pytest + + +class TestId: + @pytest.mark.complete("id -") + def test_1(self, completion): + assert completion diff --git a/test/t/test_identify.py b/test/t/test_identify.py new file mode 100644 index 0000000..34ae285 --- /dev/null +++ b/test/t/test_identify.py @@ -0,0 +1,7 @@ +import pytest + + +class TestIdentify: + @pytest.mark.complete("identify -", require_cmd=True) + def test_1(self, completion): + assert completion diff --git a/test/t/test_idn.py b/test/t/test_idn.py new file mode 100644 index 0000000..78172c0 --- /dev/null +++ b/test/t/test_idn.py @@ -0,0 +1,7 @@ +import pytest + + +class TestIdn: + @pytest.mark.complete("idn -", require_cmd=True) + def test_1(self, completion): + assert completion diff --git a/test/t/test_ifdown.py b/test/t/test_ifdown.py new file mode 100644 index 0000000..e91e4ba --- /dev/null +++ b/test/t/test_ifdown.py @@ -0,0 +1,14 @@ +import pytest + +from conftest import in_container + + +class TestIfdown: + @pytest.mark.xfail(in_container(), reason="Probably fails in a container") + @pytest.mark.complete("ifdown ") + def test_1(self, completion): + assert completion + + @pytest.mark.complete("ifdown bash-completion ") + def test_2(self, completion): + assert not completion diff --git a/test/t/test_ifstat.py b/test/t/test_ifstat.py new file mode 100644 index 0000000..89b5a0e --- /dev/null +++ b/test/t/test_ifstat.py @@ -0,0 +1,21 @@ +import pytest + + +class TestIfstat: + @pytest.mark.complete("ifstat -", require_cmd=True) + def test_1(self, completion): + assert completion + + @pytest.mark.complete( + "ifstat -i ", xfail="ifstat -v | command grep -qF iproute2" + ) + def test_2(self, completion): + assert completion + + @pytest.mark.complete( + "ifstat -d ", + require_cmd=True, + xfail="ifstat -v | command grep -qF iproute2", + ) + def test_3(self, completion): + assert completion diff --git a/test/t/test_iftop.py b/test/t/test_iftop.py new file mode 100644 index 0000000..4497310 --- /dev/null +++ b/test/t/test_iftop.py @@ -0,0 +1,11 @@ +import pytest + + +class TestIftop: + @pytest.mark.complete("iftop ", require_cmd=True) + def test_1(self, completion): + assert completion + + @pytest.mark.complete("iftop -", require_cmd=True) + def test_2(self, completion): + assert completion diff --git a/test/t/test_ifup.py b/test/t/test_ifup.py new file mode 100644 index 0000000..843190e --- /dev/null +++ b/test/t/test_ifup.py @@ -0,0 +1,20 @@ +import pytest + +from conftest import in_container + + +class TestIfup: + @pytest.mark.xfail(in_container(), reason="Probably fails in a container") + @pytest.mark.complete("ifup ") + def test_1(self, completion): + assert completion + + @pytest.mark.complete( + "ifup -", require_cmd=True, skipif="! ifup --help &>/dev/null" + ) + def test_2(self, completion): + assert completion + + @pytest.mark.complete("ifup bash-completion ") + def test_3(self, completion): + assert not completion diff --git a/test/t/test_import.py b/test/t/test_import.py new file mode 100644 index 0000000..2e86065 --- /dev/null +++ b/test/t/test_import.py @@ -0,0 +1,7 @@ +import pytest + + +class TestImport: + @pytest.mark.complete("import ") + def test_1(self, completion): + assert completion diff --git a/test/t/test_influx.py b/test/t/test_influx.py new file mode 100644 index 0000000..53a15bf --- /dev/null +++ b/test/t/test_influx.py @@ -0,0 +1,15 @@ +import pytest + + +class TestInflux: + @pytest.mark.complete("influx ") + def test_nothing(self, completion): + assert not completion + + @pytest.mark.complete("influx -", require_cmd=True) + def test_options(self, completion): + assert completion + + @pytest.mark.complete("influx -format ", require_cmd=True) + def test_format(self, completion): + assert completion diff --git a/test/t/test_info.py b/test/t/test_info.py new file mode 100644 index 0000000..e12d900 --- /dev/null +++ b/test/t/test_info.py @@ -0,0 +1,12 @@ +import pytest + + +@pytest.mark.bashcomp(pre_cmds=("INFOPATH+=:$PWD/info:",)) +class TestInfo: + @pytest.mark.complete("info bash") + def test_1(self, completion): + assert completion + + @pytest.mark.complete("info -", require_cmd=True) + def test_2(self, completion): + assert completion diff --git a/test/t/test_inject.py b/test/t/test_inject.py new file mode 100644 index 0000000..37680dc --- /dev/null +++ b/test/t/test_inject.py @@ -0,0 +1,8 @@ +import pytest + + +@pytest.mark.bashcomp(pre_cmds=("PATH=/usr/lib/mailman/bin:$PATH",)) +class TestInject: + @pytest.mark.complete("inject ") + def test_1(self, completion): + assert completion diff --git a/test/t/test_inotifywait.py b/test/t/test_inotifywait.py new file mode 100644 index 0000000..19fa4d5 --- /dev/null +++ b/test/t/test_inotifywait.py @@ -0,0 +1,15 @@ +import pytest + + +class TestInotifywait: + @pytest.mark.complete("inotifywait ") + def test_1(self, completion): + assert completion + + @pytest.mark.complete("inotifywait --", require_cmd=True) + def test_2(self, completion): + assert completion + + @pytest.mark.complete("inotifywait -e ", require_cmd=True) + def test_3(self, completion): + assert completion diff --git a/test/t/test_inotifywatch.py b/test/t/test_inotifywatch.py new file mode 100644 index 0000000..281fec4 --- /dev/null +++ b/test/t/test_inotifywatch.py @@ -0,0 +1,15 @@ +import pytest + + +class TestInotifywatch: + @pytest.mark.complete("inotifywatch ") + def test_1(self, completion): + assert completion + + @pytest.mark.complete("inotifywatch --", require_cmd=True) + def test_2(self, completion): + assert completion + + @pytest.mark.complete("inotifywatch -e ", require_cmd=True) + def test_3(self, completion): + assert len(completion) > 1 diff --git a/test/t/test_insmod.py b/test/t/test_insmod.py new file mode 100644 index 0000000..9636185 --- /dev/null +++ b/test/t/test_insmod.py @@ -0,0 +1,7 @@ +import pytest + + +class TestInsmod: + @pytest.mark.complete("insmod ") + def test_1(self, completion): + assert completion diff --git a/test/t/test_installpkg.py b/test/t/test_installpkg.py new file mode 100644 index 0000000..e665f52 --- /dev/null +++ b/test/t/test_installpkg.py @@ -0,0 +1,39 @@ +import fnmatch +import os + +import pytest + + +class TestInstallpkg: + @pytest.mark.complete("installpkg -") + def test_1(self, completion): + assert completion + + @pytest.mark.complete("installpkg --") + def test_2(self, completion): + assert ( + completion == "--ask --infobox --md5sum --menu " + "--priority --root --tagfile --terse --warn".split() + ) + + @pytest.mark.complete("installpkg --root ") + def test_3(self, completion): + dirs = sorted(x for x in os.listdir(".") if os.path.isdir("./%s" % x)) + assert completion == ["%s/" % x for x in dirs] + + @pytest.mark.complete("installpkg ", cwd="slackware/home") + def test_4(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 == expected diff --git a/test/t/test_interdiff.py b/test/t/test_interdiff.py new file mode 100644 index 0000000..83be115 --- /dev/null +++ b/test/t/test_interdiff.py @@ -0,0 +1,11 @@ +import pytest + + +class TestInterdiff: + @pytest.mark.complete("interdiff ") + def test_1(self, completion): + assert completion + + @pytest.mark.complete("interdiff -", require_cmd=True) + def test_2(self, completion): + assert completion diff --git a/test/t/test_invoke_rc_d.py b/test/t/test_invoke_rc_d.py new file mode 100644 index 0000000..61e2987 --- /dev/null +++ b/test/t/test_invoke_rc_d.py @@ -0,0 +1,14 @@ +import pytest + + +@pytest.mark.bashcomp(cmd="invoke-rc.d") +class TestInvokeRcD: + @pytest.mark.complete("invoke-rc.d ") + def test_1(self, completion): + assert completion + + @pytest.mark.complete("invoke-rc.d --no-fallback --") + def test_2(self, completion): + """Test already specified option is not offered.""" + assert completion + assert "--no-fallback" not in completion diff --git a/test/t/test_ionice.py b/test/t/test_ionice.py new file mode 100644 index 0000000..b097ebe --- /dev/null +++ b/test/t/test_ionice.py @@ -0,0 +1,7 @@ +import pytest + + +class TestIonice: + @pytest.mark.complete("ionice -", require_cmd=True) + def test_1(self, completion): + assert completion diff --git a/test/t/test_ip.py b/test/t/test_ip.py new file mode 100644 index 0000000..320647f --- /dev/null +++ b/test/t/test_ip.py @@ -0,0 +1,15 @@ +import pytest + + +class TestIp: + @pytest.mark.complete("ip ") + def test_1(self, completion): + assert completion + + @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 0000000..5611674 --- /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_iperf.py b/test/t/test_iperf.py new file mode 100644 index 0000000..c38e954 --- /dev/null +++ b/test/t/test_iperf.py @@ -0,0 +1,24 @@ +import pytest + + +class TestIperf: + @pytest.mark.complete("iperf ", require_cmd=True) + def test_1(self, completion): + assert completion + + @pytest.mark.complete("iperf --bind ") + def test_2(self, completion): + assert completion + + @pytest.mark.complete("iperf --client foo --", require_cmd=True) + def test_3(self, completion): + assert completion + assert "--daemon" not in completion + + @pytest.mark.complete("iperf --server --", require_cmd=True) + def test_4(self, completion): + assert "--daemon" in completion + + @pytest.mark.complete("iperf -", require_cmd=True) + def test_5(self, completion): + assert completion diff --git a/test/t/test_iperf3.py b/test/t/test_iperf3.py new file mode 100644 index 0000000..15f3a03 --- /dev/null +++ b/test/t/test_iperf3.py @@ -0,0 +1,20 @@ +import pytest + + +class TestIperf3: + @pytest.mark.complete("iperf3 ", require_cmd=True) + def test_1(self, completion): + assert completion + + @pytest.mark.complete("iperf3 --bind ") + def test_2(self, completion): + assert completion + + @pytest.mark.complete("iperf3 --client foo --", require_cmd=True) + def test_3(self, completion): + assert completion + assert "--daemon" not in completion + + @pytest.mark.complete("iperf3 --server --", require_cmd=True) + def test_4(self, completion): + assert "--daemon" in completion diff --git a/test/t/test_ipmitool.py b/test/t/test_ipmitool.py new file mode 100644 index 0000000..f779f91 --- /dev/null +++ b/test/t/test_ipmitool.py @@ -0,0 +1,11 @@ +import pytest + + +class TestIpmitool: + @pytest.mark.complete("ipmitool ") + def test_1(self, completion): + assert completion + + @pytest.mark.complete("ipmitool -", require_cmd=True) + def test_2(self, completion): + assert completion diff --git a/test/t/test_ipsec.py b/test/t/test_ipsec.py new file mode 100644 index 0000000..5ff29c7 --- /dev/null +++ b/test/t/test_ipsec.py @@ -0,0 +1,7 @@ +import pytest + + +class TestIpsec: + @pytest.mark.complete("ipsec ") + def test_1(self, completion): + assert completion diff --git a/test/t/test_iptables.py b/test/t/test_iptables.py new file mode 100644 index 0000000..a5c82e5 --- /dev/null +++ b/test/t/test_iptables.py @@ -0,0 +1,7 @@ +import pytest + + +class TestIptables: + @pytest.mark.complete("iptables -", require_cmd=True) + def test_1(self, completion): + assert completion diff --git a/test/t/test_ipv6calc.py b/test/t/test_ipv6calc.py new file mode 100644 index 0000000..872d8a3 --- /dev/null +++ b/test/t/test_ipv6calc.py @@ -0,0 +1,11 @@ +import pytest + + +class TestIpv6calc: + @pytest.mark.complete("ipv6calc -", require_cmd=True) + def test_1(self, completion): + assert "--action" in completion + + @pytest.mark.complete("ipv6calc --in ", require_cmd=True) + def test_2(self, completion): + assert completion diff --git a/test/t/test_irb.py b/test/t/test_irb.py new file mode 100644 index 0000000..801d373 --- /dev/null +++ b/test/t/test_irb.py @@ -0,0 +1,11 @@ +import pytest + + +class TestIrb: + @pytest.mark.complete("irb ") + def test_1(self, completion): + assert completion + + @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 new file mode 100644 index 0000000..885ca0a --- /dev/null +++ b/test/t/test_iscsiadm.py @@ -0,0 +1,7 @@ +import pytest + + +class TestIscsiadm: + @pytest.mark.complete("iscsiadm --mod") + def test_1(self, completion): + assert completion == "e" or "--mode" in completion diff --git a/test/t/test_isort.py b/test/t/test_isort.py new file mode 100644 index 0000000..b142d1c --- /dev/null +++ b/test/t/test_isort.py @@ -0,0 +1,11 @@ +import pytest + + +class TestIsort: + @pytest.mark.complete("isort ") + def test_1(self, completion): + assert completion + + @pytest.mark.complete("isort -", require_cmd=True, require_longopt=True) + def test_2(self, completion): + assert completion diff --git a/test/t/test_isql.py b/test/t/test_isql.py new file mode 100644 index 0000000..7ff0bdb --- /dev/null +++ b/test/t/test_isql.py @@ -0,0 +1,8 @@ +import pytest + + +@pytest.mark.bashcomp(pre_cmds=("ODBCINI=isql/odbc.ini",)) +class TestIsql: + @pytest.mark.complete("isql ") + def test_1(self, completion): + assert completion diff --git a/test/t/test_iwconfig.py b/test/t/test_iwconfig.py new file mode 100644 index 0000000..3ac4b31 --- /dev/null +++ b/test/t/test_iwconfig.py @@ -0,0 +1,7 @@ +import pytest + + +class TestIwconfig: + @pytest.mark.complete("iwconfig --") + def test_1(self, completion): + assert completion diff --git a/test/t/test_iwlist.py b/test/t/test_iwlist.py new file mode 100644 index 0000000..77ffb99 --- /dev/null +++ b/test/t/test_iwlist.py @@ -0,0 +1,7 @@ +import pytest + + +class TestIwlist: + @pytest.mark.complete("iwlist --") + def test_1(self, completion): + assert completion diff --git a/test/t/test_iwpriv.py b/test/t/test_iwpriv.py new file mode 100644 index 0000000..dac214a --- /dev/null +++ b/test/t/test_iwpriv.py @@ -0,0 +1,7 @@ +import pytest + + +class TestIwpriv: + @pytest.mark.complete("iwpriv --") + def test_1(self, completion): + assert completion diff --git a/test/t/test_iwspy.py b/test/t/test_iwspy.py new file mode 100644 index 0000000..398df37 --- /dev/null +++ b/test/t/test_iwspy.py @@ -0,0 +1,7 @@ +import pytest + + +class TestIwspy: + @pytest.mark.complete("iwspy --") + def test_1(self, completion): + assert completion diff --git a/test/t/test_jar.py b/test/t/test_jar.py new file mode 100644 index 0000000..5d4ed8a --- /dev/null +++ b/test/t/test_jar.py @@ -0,0 +1,7 @@ +import pytest + + +class TestJar: + @pytest.mark.complete("jar ") + def test_1(self, completion): + assert completion diff --git a/test/t/test_jarsigner.py b/test/t/test_jarsigner.py new file mode 100644 index 0000000..a6efa6a --- /dev/null +++ b/test/t/test_jarsigner.py @@ -0,0 +1,7 @@ +import pytest + + +class TestJarsigner: + @pytest.mark.complete("jarsigner ") + def test_1(self, completion): + assert completion diff --git a/test/t/test_java.py b/test/t/test_java.py new file mode 100644 index 0000000..ce0f773 --- /dev/null +++ b/test/t/test_java.py @@ -0,0 +1,49 @@ +import pytest + +from conftest import is_bash_type + + +@pytest.mark.bashcomp( + pre_cmds=("CLASSPATH=$PWD/java/a:$PWD/java/bashcomp.jar",) +) +class TestJava: + @pytest.fixture(scope="class") + def can_list_jar(self, bash): + return ( + is_bash_type(bash, "zipinfo") + or is_bash_type(bash, "unzip") + or is_bash_type(bash, "jar") + ) + + @pytest.mark.complete("java -", require_cmd=True) + def test_1(self, completion): + assert completion + + @pytest.mark.complete("java ") + def test_2(self, completion, can_list_jar): + if can_list_jar: + assert completion == "b bashcomp.jarred c. toplevel".split() + else: + assert completion == "b c.".split() + + @pytest.mark.complete("java -classpath java/bashcomp.jar ") + def test_3(self, completion, can_list_jar): + if can_list_jar: + assert completion == "bashcomp.jarred toplevel".split() + else: + assert not completion + + @pytest.mark.complete("java -cp java/bashcomp.jar:java/a/c ") + def test_4(self, completion, can_list_jar): + if can_list_jar: + assert completion == "bashcomp.jarred d toplevel".split() + else: + assert completion == ["d"] + + @pytest.mark.complete("java -cp '' ") + def test_5(self, completion): + assert not completion + + @pytest.mark.complete("java -jar java/") + def test_6(self, completion): + assert completion == "a/ bashcomp.jar bashcomp.war".split() diff --git a/test/t/test_javac.py b/test/t/test_javac.py new file mode 100644 index 0000000..197004e --- /dev/null +++ b/test/t/test_javac.py @@ -0,0 +1,11 @@ +import pytest + + +class TestJavac: + @pytest.mark.complete("javac ") + def test_1(self, completion): + assert completion + + @pytest.mark.complete("javac -cp java/") + def test_2(self, completion): + assert completion == "a/ bashcomp.jar".split() diff --git a/test/t/test_javadoc.py b/test/t/test_javadoc.py new file mode 100644 index 0000000..395d196 --- /dev/null +++ b/test/t/test_javadoc.py @@ -0,0 +1,17 @@ +import pytest + + +class TestJavadoc: + @pytest.mark.complete("javadoc ") + def test_1(self, completion): + assert completion + + @pytest.mark.complete("javadoc -linkoffline shared/default/") + def test_2(self, completion): + assert completion == ["bar bar.d/", "foo.d/"] + + @pytest.mark.complete( + "javadoc -nodeprecated -linkoffline foo shared/default/" + ) + def test_3(self, completion): + assert completion == ["bar bar.d/", "foo.d/"] diff --git a/test/t/test_javaws.py b/test/t/test_javaws.py new file mode 100644 index 0000000..596c735 --- /dev/null +++ b/test/t/test_javaws.py @@ -0,0 +1,11 @@ +import pytest + + +class TestJavaws: + @pytest.mark.complete("javaws ") + def test_1(self, completion): + assert completion + + @pytest.mark.complete("javaws -", require_cmd=True) + def test_2(self, completion): + assert completion diff --git a/test/t/test_jpegoptim.py b/test/t/test_jpegoptim.py new file mode 100644 index 0000000..fb52591 --- /dev/null +++ b/test/t/test_jpegoptim.py @@ -0,0 +1,11 @@ +import pytest + + +class TestJpegoptim: + @pytest.mark.complete("jpegoptim ") + def test_1(self, completion): + assert completion + + @pytest.mark.complete("jpegoptim -", require_cmd=True) + def test_2(self, completion): + assert completion diff --git a/test/t/test_jps.py b/test/t/test_jps.py new file mode 100644 index 0000000..add9ef9 --- /dev/null +++ b/test/t/test_jps.py @@ -0,0 +1,7 @@ +import pytest + + +class TestJps: + @pytest.mark.complete("jps -") + def test_1(self, completion): + assert completion diff --git a/test/t/test_jq.py b/test/t/test_jq.py new file mode 100644 index 0000000..4701414 --- /dev/null +++ b/test/t/test_jq.py @@ -0,0 +1,30 @@ +import pytest + + +class TestJq: + @pytest.mark.complete("jq ") + def test_1(self, completion): + assert not completion + + @pytest.mark.complete("jq . ") + def test_2(self, completion): + assert completion + + @pytest.mark.complete( + "jq -", + xfail="! (jq --help 2>&1 || :) | command grep -qF 'options include'", + ) + def test_3(self, completion): + assert completion + + @pytest.mark.complete("jq --arg ") + def test_4(self, completion): + assert not completion + + @pytest.mark.complete("jq --slurpfile ") + def test_5(self, completion): + assert not completion + + @pytest.mark.complete("jq --slurpfile foo ") + def test_6(self, completion): + assert completion diff --git a/test/t/test_jshint.py b/test/t/test_jshint.py new file mode 100644 index 0000000..58049d1 --- /dev/null +++ b/test/t/test_jshint.py @@ -0,0 +1,11 @@ +import pytest + + +class TestJshint: + @pytest.mark.complete("jshint ") + def test_1(self, completion): + assert completion + + @pytest.mark.complete("jshint -", require_cmd=True) + def test_2(self, completion): + assert completion diff --git a/test/t/test_json_xs.py b/test/t/test_json_xs.py new file mode 100644 index 0000000..f6174b1 --- /dev/null +++ b/test/t/test_json_xs.py @@ -0,0 +1,11 @@ +import pytest + + +class TestJsonXs: + @pytest.mark.complete("json_xs ") + def test_1(self, completion): + assert not completion + + @pytest.mark.complete("json_xs -") + def test_2(self, completion): + assert completion diff --git a/test/t/test_jsonschema.py b/test/t/test_jsonschema.py new file mode 100644 index 0000000..6027f5d --- /dev/null +++ b/test/t/test_jsonschema.py @@ -0,0 +1,13 @@ +import pytest + + +class TestJsonschema: + @pytest.mark.complete("jsonschema ") + def test_1(self, completion): + assert completion + + @pytest.mark.complete( + "jsonschema -", require_cmd=True, require_longopt=True + ) + def test_2(self, completion): + assert completion diff --git a/test/t/test_k3b.py b/test/t/test_k3b.py new file mode 100644 index 0000000..61b6a4d --- /dev/null +++ b/test/t/test_k3b.py @@ -0,0 +1,11 @@ +import pytest + + +class TestK3b: + @pytest.mark.complete("k3b ") + def test_1(self, completion): + assert completion + + @pytest.mark.complete("k3b -", require_cmd=True) + def test_2(self, completion): + assert completion diff --git a/test/t/test_kcov.py b/test/t/test_kcov.py new file mode 100644 index 0000000..3e377eb --- /dev/null +++ b/test/t/test_kcov.py @@ -0,0 +1,16 @@ +import pytest + + +class TestKcov: + @pytest.mark.complete("kcov ") + def test_1(self, completion): + assert completion + + @pytest.mark.complete("kcov --exclude-patter", require_cmd=True) + def test_2(self, completion): + assert completion == "n=" + assert completion.endswith("=") + + @pytest.mark.complete("kcov -l 42,") + def test_3(self, completion): + assert completion diff --git a/test/t/test_kdvi.py b/test/t/test_kdvi.py new file mode 100644 index 0000000..c2ab011 --- /dev/null +++ b/test/t/test_kdvi.py @@ -0,0 +1,10 @@ +import pytest + + +class TestKdvi: + @pytest.mark.complete("kdvi ", cwd="kdvi") + def test_1(self, completion): + assert completion == sorted( + "foo/ .dvi .DVI .dvi.bz2 .DVI.bz2 .dvi.gz " + ".DVI.gz .dvi.Z .DVI.Z".split() + ) diff --git a/test/t/test_kill.py b/test/t/test_kill.py new file mode 100644 index 0000000..9699435 --- /dev/null +++ b/test/t/test_kill.py @@ -0,0 +1,15 @@ +import pytest + + +class TestKill: + @pytest.mark.complete("kill 1", xfail="! type ps &>/dev/null") + def test_1(self, completion): + assert completion + + @pytest.mark.complete("kill -s ") + def test_2(self, completion): + assert all(x in completion for x in "HUP QUIT".split()) + + @pytest.mark.complete("kill -") + def test_3(self, completion): + assert all("-%s" % x in completion for x in "l s ABRT USR1".split()) diff --git a/test/t/test_killall.py b/test/t/test_killall.py new file mode 100644 index 0000000..4b67d96 --- /dev/null +++ b/test/t/test_killall.py @@ -0,0 +1,21 @@ +import pytest + + +class TestKillall: + + # "p": Assume our process name completion runs ps and at least it is shown + @pytest.mark.complete("killall p") + def test_1(self, completion): + assert completion + + @pytest.mark.complete("killall --signal ") + def test_2(self, completion): + assert all(x in completion for x in "INT KILL TERM".split()) + + @pytest.mark.complete("killall ") + def test_3(self, completion): + assert "command=" not in completion + + @pytest.mark.complete("killall -", require_cmd=True) + def test_4(self, completion): + assert completion diff --git a/test/t/test_kldload.py b/test/t/test_kldload.py new file mode 100644 index 0000000..2965e44 --- /dev/null +++ b/test/t/test_kldload.py @@ -0,0 +1,7 @@ +import pytest + + +class TestKldload: + @pytest.mark.complete("kldload ") + def test_1(self, completion): + assert completion diff --git a/test/t/test_kldunload.py b/test/t/test_kldunload.py new file mode 100644 index 0000000..a52c99e --- /dev/null +++ b/test/t/test_kldunload.py @@ -0,0 +1,16 @@ +import subprocess + +import pytest + + +class TestKldunload: + @pytest.mark.complete("kldunload ") + def test_1(self, completion): + try: + subprocess.check_call( + r"kldstat 2>/dev/null | command grep -q '\.ko$'", shell=True + ) + except BaseException: + assert not completion + else: + assert completion diff --git a/test/t/test_koji.py b/test/t/test_koji.py new file mode 100644 index 0000000..73d3e4c --- /dev/null +++ b/test/t/test_koji.py @@ -0,0 +1,11 @@ +import pytest + + +class TestKoji: + @pytest.mark.complete("koji ", require_cmd=True) + def test_1(self, completion): + assert completion + + @pytest.mark.complete("koji -", require_cmd=True) + def test_2(self, completion): + assert completion diff --git a/test/t/test_kpdf.py b/test/t/test_kpdf.py new file mode 100644 index 0000000..68b36fe --- /dev/null +++ b/test/t/test_kpdf.py @@ -0,0 +1,7 @@ +import pytest + + +class TestKpdf: + @pytest.mark.complete("kpdf ", cwd="kpdf") + def test_1(self, completion): + assert completion == sorted("foo/ .eps .ps .EPS .PS .pdf .PDF".split()) diff --git a/test/t/test_kplayer.py b/test/t/test_kplayer.py new file mode 100644 index 0000000..ef8a08e --- /dev/null +++ b/test/t/test_kplayer.py @@ -0,0 +1,7 @@ +import pytest + + +class TestKplayer: + @pytest.mark.complete("kplayer ") + def test_1(self, completion): + assert completion diff --git a/test/t/test_ktutil.py b/test/t/test_ktutil.py new file mode 100644 index 0000000..7c90b80 --- /dev/null +++ b/test/t/test_ktutil.py @@ -0,0 +1,11 @@ +import pytest + + +class TestKtutil: + @pytest.mark.complete("ktutil ") + def test_1(self, completion): + assert completion + + @pytest.mark.complete("ktutil -") + def test_2(self, completion): + assert completion diff --git a/test/t/test_l2ping.py b/test/t/test_l2ping.py new file mode 100644 index 0000000..c50651b --- /dev/null +++ b/test/t/test_l2ping.py @@ -0,0 +1,7 @@ +import pytest + + +class TestL2ping: + @pytest.mark.complete("l2ping -", require_cmd=True) + def test_1(self, completion): + assert completion diff --git a/test/t/test_larch.py b/test/t/test_larch.py new file mode 100644 index 0000000..e68183c --- /dev/null +++ b/test/t/test_larch.py @@ -0,0 +1,7 @@ +import pytest + + +class TestLarch: + @pytest.mark.complete("larch library-") + def test_1(self, completion): + assert completion diff --git a/test/t/test_lastlog.py b/test/t/test_lastlog.py new file mode 100644 index 0000000..31a855f --- /dev/null +++ b/test/t/test_lastlog.py @@ -0,0 +1,7 @@ +import pytest + + +class TestLastlog: + @pytest.mark.complete("lastlog -", require_cmd=True) + def test_1(self, completion): + assert completion diff --git a/test/t/test_ld.py b/test/t/test_ld.py new file mode 100644 index 0000000..f6a16bb --- /dev/null +++ b/test/t/test_ld.py @@ -0,0 +1,11 @@ +import pytest + + +class TestLd: + @pytest.mark.complete("ld ") + def test_1(self, completion): + assert completion + + @pytest.mark.complete("ld -", require_cmd=True) + def test_options(self, completion): + assert completion diff --git a/test/t/test_ldapadd.py b/test/t/test_ldapadd.py new file mode 100644 index 0000000..24aa5e3 --- /dev/null +++ b/test/t/test_ldapadd.py @@ -0,0 +1,7 @@ +import pytest + + +class TestLdapadd: + @pytest.mark.complete("ldapadd -") + def test_1(self, completion): + assert completion diff --git a/test/t/test_ldapcompare.py b/test/t/test_ldapcompare.py new file mode 100644 index 0000000..6a3afe9 --- /dev/null +++ b/test/t/test_ldapcompare.py @@ -0,0 +1,7 @@ +import pytest + + +class TestLdapcompare: + @pytest.mark.complete("ldapcompare -") + def test_1(self, completion): + assert completion diff --git a/test/t/test_ldapdelete.py b/test/t/test_ldapdelete.py new file mode 100644 index 0000000..2065d9b --- /dev/null +++ b/test/t/test_ldapdelete.py @@ -0,0 +1,7 @@ +import pytest + + +class TestLdapdelete: + @pytest.mark.complete("ldapdelete -") + def test_1(self, completion): + assert completion diff --git a/test/t/test_ldapmodrdn.py b/test/t/test_ldapmodrdn.py new file mode 100644 index 0000000..da8bdbd --- /dev/null +++ b/test/t/test_ldapmodrdn.py @@ -0,0 +1,7 @@ +import pytest + + +class TestLdapmodrdn: + @pytest.mark.complete("ldapmodrdn -") + def test_1(self, completion): + assert completion diff --git a/test/t/test_ldappasswd.py b/test/t/test_ldappasswd.py new file mode 100644 index 0000000..e559f23 --- /dev/null +++ b/test/t/test_ldappasswd.py @@ -0,0 +1,7 @@ +import pytest + + +class TestLdappasswd: + @pytest.mark.complete("ldappasswd -") + def test_1(self, completion): + assert completion diff --git a/test/t/test_ldapsearch.py b/test/t/test_ldapsearch.py new file mode 100644 index 0000000..43797f4 --- /dev/null +++ b/test/t/test_ldapsearch.py @@ -0,0 +1,7 @@ +import pytest + + +class TestLdapsearch: + @pytest.mark.complete("ldapsearch -") + def test_1(self, completion): + assert completion diff --git a/test/t/test_ldapvi.py b/test/t/test_ldapvi.py new file mode 100644 index 0000000..5e65fc4 --- /dev/null +++ b/test/t/test_ldapvi.py @@ -0,0 +1,7 @@ +import pytest + + +class TestLdapvi: + @pytest.mark.complete("ldapvi -", require_cmd=True) + def test_1(self, completion): + assert completion diff --git a/test/t/test_ldapwhoami.py b/test/t/test_ldapwhoami.py new file mode 100644 index 0000000..9dcfb5f --- /dev/null +++ b/test/t/test_ldapwhoami.py @@ -0,0 +1,7 @@ +import pytest + + +class TestLdapwhoami: + @pytest.mark.complete("ldapwhoami -") + def test_1(self, completion): + assert completion diff --git a/test/t/test_ldd.py b/test/t/test_ldd.py new file mode 100644 index 0000000..7f7201b --- /dev/null +++ b/test/t/test_ldd.py @@ -0,0 +1,13 @@ +import pytest + + +class TestLdd: + @pytest.mark.complete("ldd ") + def test_1(self, completion): + assert completion + + @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 new file mode 100644 index 0000000..70833c3 --- /dev/null +++ b/test/t/test_less.py @@ -0,0 +1,11 @@ +import pytest + + +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 new file mode 100644 index 0000000..f775a4c --- /dev/null +++ b/test/t/test_lftp.py @@ -0,0 +1,16 @@ +import pytest + + +@pytest.mark.bashcomp(pre_cmds=("HOME=$PWD/lftp",)) +class TestLftp: + @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) + # 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): + assert completion diff --git a/test/t/test_lftpget.py b/test/t/test_lftpget.py new file mode 100644 index 0000000..c1f453e --- /dev/null +++ b/test/t/test_lftpget.py @@ -0,0 +1,7 @@ +import pytest + + +class TestLftpget: + @pytest.mark.complete("lftpget -") + def test_1(self, completion): + assert completion diff --git a/test/t/test_lilo.py b/test/t/test_lilo.py new file mode 100644 index 0000000..2c69821 --- /dev/null +++ b/test/t/test_lilo.py @@ -0,0 +1,16 @@ +import pytest + + +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_links.py b/test/t/test_links.py new file mode 100644 index 0000000..0806813 --- /dev/null +++ b/test/t/test_links.py @@ -0,0 +1,11 @@ +import pytest + + +class TestLinks: + @pytest.mark.complete("links ") + def test_1(self, completion): + assert completion + + @pytest.mark.complete("links -", require_cmd=True) + def test_2(self, completion): + assert completion diff --git a/test/t/test_lintian.py b/test/t/test_lintian.py new file mode 100644 index 0000000..c652642 --- /dev/null +++ b/test/t/test_lintian.py @@ -0,0 +1,7 @@ +import pytest + + +class TestLintian: + @pytest.mark.complete("lintian --") + def test_1(self, completion): + assert completion diff --git a/test/t/test_lintian_info.py b/test/t/test_lintian_info.py new file mode 100644 index 0000000..bf9afc5 --- /dev/null +++ b/test/t/test_lintian_info.py @@ -0,0 +1,12 @@ +import pytest + + +@pytest.mark.bashcomp(cmd="lintian-info") +class TestLintianInfo: + @pytest.mark.complete("lintian-info ") + def test_1(self, completion): + assert completion + + @pytest.mark.complete("lintian-info --", require_cmd=True) + def test_2(self, completion): + assert completion diff --git a/test/t/test_lisp.py b/test/t/test_lisp.py new file mode 100644 index 0000000..8477061 --- /dev/null +++ b/test/t/test_lisp.py @@ -0,0 +1,7 @@ +import pytest + + +class TestLisp: + @pytest.mark.complete("lisp ") + def test_1(self, completion): + assert completion diff --git a/test/t/test_list_admins.py b/test/t/test_list_admins.py new file mode 100644 index 0000000..b65387e --- /dev/null +++ b/test/t/test_list_admins.py @@ -0,0 +1,7 @@ +import pytest + + +class TestListAdmins: + @pytest.mark.complete("list_admins -") + def test_1(self, completion): + assert completion diff --git a/test/t/test_list_lists.py b/test/t/test_list_lists.py new file mode 100644 index 0000000..966ca25 --- /dev/null +++ b/test/t/test_list_lists.py @@ -0,0 +1,7 @@ +import pytest + + +class TestListLists: + @pytest.mark.complete("list_lists -") + def test_1(self, completion): + assert completion diff --git a/test/t/test_list_members.py b/test/t/test_list_members.py new file mode 100644 index 0000000..96ea2ef --- /dev/null +++ b/test/t/test_list_members.py @@ -0,0 +1,7 @@ +import pytest + + +class TestListMembers: + @pytest.mark.complete("list_members -") + def test_1(self, completion): + assert completion diff --git a/test/t/test_list_owners.py b/test/t/test_list_owners.py new file mode 100644 index 0000000..2a6bcab --- /dev/null +++ b/test/t/test_list_owners.py @@ -0,0 +1,8 @@ +import pytest + + +@pytest.mark.bashcomp(pre_cmds=("PATH=/usr/lib/mailman/bin:$PATH",)) +class TestListOwners: + @pytest.mark.complete("list_owners -") + def test_1(self, completion): + assert completion diff --git a/test/t/test_ln.py b/test/t/test_ln.py new file mode 100644 index 0000000..6bf809c --- /dev/null +++ b/test/t/test_ln.py @@ -0,0 +1,11 @@ +import pytest + + +class TestLn: + @pytest.mark.complete("ln ") + def test_1(self, completion): + assert completion + + @pytest.mark.complete("ln -", require_longopt=True) + def test_options(self, completion): + assert completion diff --git a/test/t/test_locale_gen.py b/test/t/test_locale_gen.py new file mode 100644 index 0000000..caffb06 --- /dev/null +++ b/test/t/test_locale_gen.py @@ -0,0 +1,13 @@ +import pytest + + +@pytest.mark.bashcomp(cmd="locale-gen") +class TestLocaleGen: + # require_cmd is not strictly true here, but... + @pytest.mark.complete("locale-gen ", require_cmd=True) + def test_1(self, completion): + assert completion + + @pytest.mark.complete("locale-gen --", require_longopt=True) + def test_2(self, completion): + assert completion diff --git a/test/t/test_look.py b/test/t/test_look.py new file mode 100644 index 0000000..fd6800e --- /dev/null +++ b/test/t/test_look.py @@ -0,0 +1,16 @@ +import subprocess + +import pytest + + +class TestLook: + @pytest.mark.complete("look foo") + def test_1(self, completion): + try: + subprocess.check_call( + "look foo 2>/dev/null | command grep -q ^foo", shell=True + ) + except BaseException: + assert not completion + else: + assert completion diff --git a/test/t/test_lpq.py b/test/t/test_lpq.py new file mode 100644 index 0000000..0d69270 --- /dev/null +++ b/test/t/test_lpq.py @@ -0,0 +1,7 @@ +import pytest + + +class TestLpq: + @pytest.mark.complete("lpq ") + def test_1(self, completion): + assert completion diff --git a/test/t/test_lpr.py b/test/t/test_lpr.py new file mode 100644 index 0000000..30c710b --- /dev/null +++ b/test/t/test_lpr.py @@ -0,0 +1,7 @@ +import pytest + + +class TestLpr: + @pytest.mark.complete("lpr ") + def test_1(self, completion): + assert completion diff --git a/test/t/test_lrzip.py b/test/t/test_lrzip.py new file mode 100644 index 0000000..d61ee9d --- /dev/null +++ b/test/t/test_lrzip.py @@ -0,0 +1,15 @@ +import pytest + + +class TestLrzip: + @pytest.mark.complete("lrzip ") + def test_1(self, completion): + assert completion + + @pytest.mark.complete("lrzip ~") + def test_2(self, completion): + assert completion + + @pytest.mark.complete("lrzip -", require_cmd=True) + def test_3(self, completion): + assert completion diff --git a/test/t/test_ls.py b/test/t/test_ls.py new file mode 100644 index 0000000..8abcb59 --- /dev/null +++ b/test/t/test_ls.py @@ -0,0 +1,40 @@ +import pytest + +from conftest import ( + assert_bash_exec, + assert_complete, + find_unique_completion_pair, +) + + +class TestLs: + @pytest.mark.complete( + "ls --", require_cmd=True, xfail="! ls --help &>/dev/null" + ) + def test_1(self, completion): + assert completion + + @pytest.mark.complete("ls ~") + def test_2(self, completion): + assert completion + + def test_3(self, bash): + """~part should complete to ~full<SPACE> if home dir does not exist.""" + res = ( + assert_bash_exec( + bash, + "for u in $(compgen -u); do " + "eval test -d ~$u || echo $u; unset u; done", + want_output=True, + ) + .strip() + .split() + ) + part_full = find_unique_completion_pair(res) + if not part_full: + pytest.skip("No suitable test user found") + return + part, full = part_full + completion = assert_complete(bash, "ls ~%s" % part) + assert completion == full[len(part) :] + assert completion.endswith(" ") diff --git a/test/t/test_lsof.py b/test/t/test_lsof.py new file mode 100644 index 0000000..170d269 --- /dev/null +++ b/test/t/test_lsof.py @@ -0,0 +1,11 @@ +import pytest + + +class TestLsof: + @pytest.mark.complete("lsof ") + def test_1(self, completion): + assert completion + + @pytest.mark.complete("lsof -") + def test_2(self, completion): + assert completion diff --git a/test/t/test_lspci.py b/test/t/test_lspci.py new file mode 100644 index 0000000..aba7b5a --- /dev/null +++ b/test/t/test_lspci.py @@ -0,0 +1,13 @@ +import pytest + + +class TestLspci: + @pytest.mark.complete("lspci -", require_cmd=True) + def test_1(self, completion): + assert completion + + @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_lsscsi.py b/test/t/test_lsscsi.py new file mode 100644 index 0000000..fe01ac1 --- /dev/null +++ b/test/t/test_lsscsi.py @@ -0,0 +1,11 @@ +import pytest + + +class TestLsscsi: + @pytest.mark.complete("lsscsi ") + def test_1(self, completion): + assert not completion + + @pytest.mark.complete("lsscsi -", require_cmd=True) + def test_2(self, completion): + assert completion diff --git a/test/t/test_lsusb.py b/test/t/test_lsusb.py new file mode 100644 index 0000000..c68d046 --- /dev/null +++ b/test/t/test_lsusb.py @@ -0,0 +1,10 @@ +import pytest + + +class TestLsusb: + @pytest.mark.complete( + "lsusb -", + xfail="! (lsusb --help 2>&1 || :) | command grep -qF -- --help", + ) + def test_1(self, completion): + assert completion diff --git a/test/t/test_lua.py b/test/t/test_lua.py new file mode 100644 index 0000000..54c2432 --- /dev/null +++ b/test/t/test_lua.py @@ -0,0 +1,11 @@ +import pytest + + +class TestLua: + @pytest.mark.complete("lua ") + def test_1(self, completion): + assert completion + + @pytest.mark.complete("lua -", require_cmd=True) + def test_2(self, completion): + assert completion diff --git a/test/t/test_luac.py b/test/t/test_luac.py new file mode 100644 index 0000000..28dc0e8 --- /dev/null +++ b/test/t/test_luac.py @@ -0,0 +1,11 @@ +import pytest + + +class TestLuac: + @pytest.mark.complete("luac ") + def test_1(self, completion): + assert completion + + @pytest.mark.complete("luac -", require_cmd=True) + def test_2(self, completion): + assert completion diff --git a/test/t/test_luseradd.py b/test/t/test_luseradd.py new file mode 100644 index 0000000..4f1bec9 --- /dev/null +++ b/test/t/test_luseradd.py @@ -0,0 +1,7 @@ +import pytest + + +class TestLuseradd: + @pytest.mark.complete("luseradd -", require_cmd=True) + def test_1(self, completion): + assert completion diff --git a/test/t/test_luserdel.py b/test/t/test_luserdel.py new file mode 100644 index 0000000..ad88557 --- /dev/null +++ b/test/t/test_luserdel.py @@ -0,0 +1,11 @@ +import pytest + + +class TestLuserdel: + @pytest.mark.complete("luserdel ") + def test_1(self, completion): + assert completion + + @pytest.mark.complete("luserdel -", require_cmd=True) + def test_2(self, completion): + assert completion diff --git a/test/t/test_lusermod.py b/test/t/test_lusermod.py new file mode 100644 index 0000000..69ef07c --- /dev/null +++ b/test/t/test_lusermod.py @@ -0,0 +1,7 @@ +import pytest + + +class TestLusermod: + @pytest.mark.complete("lusermod ") + def test_1(self, completion): + assert completion diff --git a/test/t/test_lvchange.py b/test/t/test_lvchange.py new file mode 100644 index 0000000..3e4feda --- /dev/null +++ b/test/t/test_lvchange.py @@ -0,0 +1,9 @@ +import pytest + + +class TestLvchange: + @pytest.mark.complete( + "lvchange --", require_cmd=True, xfail="! lvchange --help &>/dev/null" + ) + def test_1(self, completion): + assert completion diff --git a/test/t/test_lvcreate.py b/test/t/test_lvcreate.py new file mode 100644 index 0000000..636f625 --- /dev/null +++ b/test/t/test_lvcreate.py @@ -0,0 +1,9 @@ +import pytest + + +class TestLvcreate: + @pytest.mark.complete( + "lvcreate --", require_cmd=True, xfail="! lvcreate --help &>/dev/null" + ) + def test_1(self, completion): + assert completion diff --git a/test/t/test_lvdisplay.py b/test/t/test_lvdisplay.py new file mode 100644 index 0000000..5210662 --- /dev/null +++ b/test/t/test_lvdisplay.py @@ -0,0 +1,11 @@ +import pytest + + +class TestLvdisplay: + @pytest.mark.complete( + "lvdisplay --", + require_cmd=True, + xfail="! lvdisplay --help &>/dev/null", + ) + def test_1(self, completion): + assert completion diff --git a/test/t/test_lvextend.py b/test/t/test_lvextend.py new file mode 100644 index 0000000..4daa888 --- /dev/null +++ b/test/t/test_lvextend.py @@ -0,0 +1,9 @@ +import pytest + + +class TestLvextend: + @pytest.mark.complete( + "lvextend --", require_cmd=True, xfail="! lvextend --help &>/dev/null" + ) + def test_1(self, completion): + assert completion diff --git a/test/t/test_lvm.py b/test/t/test_lvm.py new file mode 100644 index 0000000..ea25b97 --- /dev/null +++ b/test/t/test_lvm.py @@ -0,0 +1,7 @@ +import pytest + + +class TestLvm: + @pytest.mark.complete("lvm pv") + def test_1(self, completion): + assert completion diff --git a/test/t/test_lvmdiskscan.py b/test/t/test_lvmdiskscan.py new file mode 100644 index 0000000..1b334b8 --- /dev/null +++ b/test/t/test_lvmdiskscan.py @@ -0,0 +1,11 @@ +import pytest + + +class TestLvmdiskscan: + @pytest.mark.complete( + "lvmdiskscan --", + require_cmd=True, + xfail="! lvmdiskscan --help &>/dev/null", + ) + def test_1(self, completion): + assert completion diff --git a/test/t/test_lvreduce.py b/test/t/test_lvreduce.py new file mode 100644 index 0000000..3b614cb --- /dev/null +++ b/test/t/test_lvreduce.py @@ -0,0 +1,9 @@ +import pytest + + +class TestLvreduce: + @pytest.mark.complete( + "lvreduce --", require_cmd=True, xfail="! lvreduce --help &>/dev/null" + ) + def test_1(self, completion): + assert completion diff --git a/test/t/test_lvremove.py b/test/t/test_lvremove.py new file mode 100644 index 0000000..17486aa --- /dev/null +++ b/test/t/test_lvremove.py @@ -0,0 +1,9 @@ +import pytest + + +class TestLvremove: + @pytest.mark.complete( + "lvremove --", require_cmd=True, xfail="! lvremove --help &>/dev/null" + ) + def test_1(self, completion): + assert completion diff --git a/test/t/test_lvrename.py b/test/t/test_lvrename.py new file mode 100644 index 0000000..802b72e --- /dev/null +++ b/test/t/test_lvrename.py @@ -0,0 +1,9 @@ +import pytest + + +class TestLvrename: + @pytest.mark.complete( + "lvrename --", require_cmd=True, xfail="! lvrename --help &>/dev/null" + ) + def test_1(self, completion): + assert completion diff --git a/test/t/test_lvresize.py b/test/t/test_lvresize.py new file mode 100644 index 0000000..bb71feb --- /dev/null +++ b/test/t/test_lvresize.py @@ -0,0 +1,9 @@ +import pytest + + +class TestLvresize: + @pytest.mark.complete( + "lvresize --", require_cmd=True, xfail="! lvresize --help &>/dev/null" + ) + def test_1(self, completion): + assert completion diff --git a/test/t/test_lvs.py b/test/t/test_lvs.py new file mode 100644 index 0000000..eadc8df --- /dev/null +++ b/test/t/test_lvs.py @@ -0,0 +1,9 @@ +import pytest + + +class TestLvs: + @pytest.mark.complete( + "lvs --", require_cmd=True, xfail="! lvs --help &>/dev/null" + ) + def test_1(self, completion): + assert completion diff --git a/test/t/test_lvscan.py b/test/t/test_lvscan.py new file mode 100644 index 0000000..a2867b0 --- /dev/null +++ b/test/t/test_lvscan.py @@ -0,0 +1,9 @@ +import pytest + + +class TestLvscan: + @pytest.mark.complete( + "lvscan --", require_cmd=True, xfail="! lvscan --help &>/dev/null" + ) + def test_1(self, completion): + assert completion diff --git a/test/t/test_lz4.py b/test/t/test_lz4.py new file mode 100644 index 0000000..0e1208c --- /dev/null +++ b/test/t/test_lz4.py @@ -0,0 +1,15 @@ +import pytest + + +class TestLz4: + @pytest.mark.complete("lz4 ") + def test_1(self, completion): + assert completion + + @pytest.mark.complete("lz4 ~") + def test_2(self, completion): + assert completion + + @pytest.mark.complete("lz4 -", require_cmd=True) + def test_3(self, completion): + assert completion diff --git a/test/t/test_lzip.py b/test/t/test_lzip.py new file mode 100644 index 0000000..b0313be --- /dev/null +++ b/test/t/test_lzip.py @@ -0,0 +1,11 @@ +import pytest + + +class TestLzip: + @pytest.mark.complete("lzip ") + def test_1(self, completion): + assert completion + + @pytest.mark.complete("lzip -", require_cmd=True) + def test_2(self, completion): + assert completion diff --git a/test/t/test_lzma.py b/test/t/test_lzma.py new file mode 100644 index 0000000..f9d8992 --- /dev/null +++ b/test/t/test_lzma.py @@ -0,0 +1,19 @@ +import pytest + + +class TestLzma: + @pytest.mark.complete("lzma ") + def test_1(self, completion): + assert completion + + @pytest.mark.complete("lzma -") + def test_2(self, completion): + assert completion + + @pytest.mark.complete("lzma -d xz/") + def test_3(self, completion): + assert completion == "a/ bashcomp.lzma bashcomp.tlz".split() + + @pytest.mark.complete("lzma ~") + def test_4(self, completion): + assert completion diff --git a/test/t/test_lzop.py b/test/t/test_lzop.py new file mode 100644 index 0000000..bd010fd --- /dev/null +++ b/test/t/test_lzop.py @@ -0,0 +1,11 @@ +import pytest + + +class TestLzop: + @pytest.mark.complete("lzop ") + def test_1(self, completion): + assert completion + + @pytest.mark.complete("lzop ~") + def test_2(self, completion): + assert completion diff --git a/test/t/test_m4.py b/test/t/test_m4.py new file mode 100644 index 0000000..7ecd774 --- /dev/null +++ b/test/t/test_m4.py @@ -0,0 +1,9 @@ +import pytest + + +class TestM4: + @pytest.mark.complete( + "m4 --", require_cmd=True, xfail="! m4 --help &>/dev/null" + ) + def test_1(self, completion): + assert completion diff --git a/test/t/test_macof.py b/test/t/test_macof.py new file mode 100644 index 0000000..17f0eae --- /dev/null +++ b/test/t/test_macof.py @@ -0,0 +1,7 @@ +import pytest + + +class TestMacof: + @pytest.mark.complete("macof -", require_cmd=True) + def test_1(self, completion): + assert completion diff --git a/test/t/test_mailmanctl.py b/test/t/test_mailmanctl.py new file mode 100644 index 0000000..2baa050 --- /dev/null +++ b/test/t/test_mailmanctl.py @@ -0,0 +1,8 @@ +import pytest + + +@pytest.mark.bashcomp(pre_cmds=("PATH=/usr/lib/mailman/bin:$PATH",)) +class TestMailmanctl: + @pytest.mark.complete("mailmanctl ") + def test_1(self, completion): + assert completion diff --git a/test/t/test_mailsnarf.py b/test/t/test_mailsnarf.py new file mode 100644 index 0000000..0dc3e04 --- /dev/null +++ b/test/t/test_mailsnarf.py @@ -0,0 +1,7 @@ +import pytest + + +class TestMailsnarf: + @pytest.mark.complete("mailsnarf -", require_cmd=True) + def test_1(self, completion): + assert completion diff --git a/test/t/test_make.py b/test/t/test_make.py new file mode 100644 index 0000000..19861b0 --- /dev/null +++ b/test/t/test_make.py @@ -0,0 +1,47 @@ +import os + +import pytest + + +class TestMake: + @pytest.mark.complete("make -f Ma", cwd="make") + def test_1(self, completion): + assert completion == "kefile" + + @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", require_cmd=True) + def test_3(self, bash, completion): + assert completion == "1 2".split() + os.remove("%s/make/%s" % (bash.cwd, "extra_makefile")) + + @pytest.mark.complete("make ", cwd="shared/empty_dir") + def test_4(self, completion): + assert not completion + + @pytest.mark.complete("make -j ") + def test_5(self, completion): + assert completion + + @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.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 ", 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")) + + @pytest.mark.complete("make -", require_cmd=True) + def test_9(self, completion): + assert completion diff --git a/test/t/test_makepkg.py b/test/t/test_makepkg.py new file mode 100644 index 0000000..f643a29 --- /dev/null +++ b/test/t/test_makepkg.py @@ -0,0 +1,17 @@ +import pytest + + +@pytest.mark.bashcomp( + ignore_env=r"^-declare -f _makepkg_bootstrap$", + xfail="! makepkg --help 2>&1 | command grep -qiF slackware", +) +class TestMakepkg: + @pytest.mark.complete("makepkg ") + def test_1(self, completion): + assert completion + + @pytest.mark.complete("makepkg --", require_cmd=True) + def test_2(self, completion): + assert all( + x in completion for x in "--chown --linkadd --prepend".split() + ) diff --git a/test/t/test_man.py b/test/t/test_man.py new file mode 100644 index 0000000..1ff9f84 --- /dev/null +++ b/test/t/test_man.py @@ -0,0 +1,115 @@ +import pytest + +from conftest import assert_bash_exec + + +@pytest.mark.bashcomp( + ignore_env=r"^[+-]((BASHOPTS|MANPATH)=|shopt -. failglob)" +) +class TestMan: + + manpath = "$PWD/man" + assumed_present = "man" + + @pytest.fixture + def colonpath(self, request, bash): + try: + assert_bash_exec(bash, "uname -s 2>&1 | grep -qiF cygwin") + except AssertionError: + pass + else: + pytest.skip("Cygwin doesn't like paths with colons") + return + assert_bash_exec(bash, "mkdir -p $TESTDIR/../tmp/man/man3") + assert_bash_exec( + bash, "touch $TESTDIR/../tmp/man/man3/Bash::Completion.3pm.gz" + ) + request.addfinalizer( + lambda: assert_bash_exec(bash, "rm -r $TESTDIR/../tmp/man") + ) + + @pytest.mark.complete( + "man bash-completion-testcas", + env=dict(MANPATH=manpath), + require_cmd=True, + ) + def test_1(self, completion): + assert completion == "e" + + @pytest.mark.complete("man man1/f", cwd="man", env=dict(MANPATH=manpath)) + def test_2(self, completion): + assert completion == "oo.1" + + @pytest.mark.complete("man man/", cwd="man", env=dict(MANPATH=manpath)) + def test_3(self, completion): + assert completion == "quux.8" + + @pytest.mark.complete( + "man %s" % assumed_present, + cwd="shared/empty_dir", + env=dict(MANPATH=manpath), + ) + def test_4(self, completion): + """ + Assumed present should not be completed complete when there's no + leading/trailing colon in $MANPATH. + """ + assert not completion + + @pytest.mark.complete( + "man %s" % assumed_present, + require_cmd=True, + cwd="shared/empty_dir", + env=dict(MANPATH="%s:" % manpath), + ) + def test_5(self, completion): + """Trailing colon appends system man path.""" + assert completion + + @pytest.mark.complete( + "man bash-completion-testcas", + require_cmd=True, + env=dict(MANPATH="%s:" % manpath), + ) + def test_6(self, completion): + assert completion == "e" + + @pytest.mark.complete( + "man %s" % assumed_present, + require_cmd=True, + cwd="shared/empty_dir", + env=dict(MANPATH=":%s" % manpath), + ) + def test_7(self, completion): + """Leading colon prepends system man path.""" + assert completion + + @pytest.mark.complete( + "man bash-completion-testcas", + require_cmd=True, + env=dict(MANPATH=":%s" % manpath), + ) + def test_8(self, completion): + assert completion == "e" + + @pytest.mark.complete( + "man %s" % assumed_present, + require_cmd=True, + cwd="shared/empty_dir", + pre_cmds=("shopt -s failglob",), + ) + def test_9(self, bash, completion): + assert self.assumed_present in completion + assert_bash_exec(bash, "shopt -u failglob") + + @pytest.mark.complete( + "man Bash::C", + require_cmd=True, + env=dict(MANPATH="%s:../tmp/man" % manpath), + ) + def test_10(self, bash, colonpath, completion): + assert completion == "ompletion" + + @pytest.mark.complete("man -", require_cmd=True) + def test_11(self, completion): + assert completion diff --git a/test/t/test_mc.py b/test/t/test_mc.py new file mode 100644 index 0000000..31f88b7 --- /dev/null +++ b/test/t/test_mc.py @@ -0,0 +1,7 @@ +import pytest + + +class TestMc: + @pytest.mark.complete("mc -", require_cmd=True) + def test_1(self, completion): + assert completion diff --git a/test/t/test_mcrypt.py b/test/t/test_mcrypt.py new file mode 100644 index 0000000..d11f446 --- /dev/null +++ b/test/t/test_mcrypt.py @@ -0,0 +1,19 @@ +import pytest + + +class TestMcrypt: + @pytest.mark.complete("mcrypt ") + def test_1(self, completion): + assert completion + + @pytest.mark.complete("mcrypt -a ", require_cmd=True) + def test_2(self, completion): + assert completion + + @pytest.mark.complete("mcrypt -m ", require_cmd=True) + def test_3(self, completion): + assert completion + + @pytest.mark.complete("mcrypt -", require_cmd=True) + def test_4(self, completion): + assert completion diff --git a/test/t/test_md5sum.py b/test/t/test_md5sum.py new file mode 100644 index 0000000..0a3286a --- /dev/null +++ b/test/t/test_md5sum.py @@ -0,0 +1,11 @@ +import pytest + + +class TestMd5sum: + @pytest.mark.complete("md5sum ") + def test_1(self, completion): + assert completion + + @pytest.mark.complete("md5sum -", require_longopt=True) + def test_options(self, completion): + assert completion diff --git a/test/t/test_mdadm.py b/test/t/test_mdadm.py new file mode 100644 index 0000000..143007b --- /dev/null +++ b/test/t/test_mdadm.py @@ -0,0 +1,7 @@ +import pytest + + +class TestMdadm: + @pytest.mark.complete("mdadm ") + def test_1(self, completion): + assert completion diff --git a/test/t/test_mdecrypt.py b/test/t/test_mdecrypt.py new file mode 100644 index 0000000..f6f4c8e --- /dev/null +++ b/test/t/test_mdecrypt.py @@ -0,0 +1,7 @@ +import pytest + + +class TestMdecrypt: + @pytest.mark.complete("mdecrypt ") + def test_1(self, completion): + assert completion diff --git a/test/t/test_mdtool.py b/test/t/test_mdtool.py new file mode 100644 index 0000000..356e907 --- /dev/null +++ b/test/t/test_mdtool.py @@ -0,0 +1,7 @@ +import pytest + + +class TestMdtool: + @pytest.mark.complete("mdtool ") + def test_1(self, completion): + assert completion diff --git a/test/t/test_medusa.py b/test/t/test_medusa.py new file mode 100644 index 0000000..87fb91b --- /dev/null +++ b/test/t/test_medusa.py @@ -0,0 +1,7 @@ +import pytest + + +class TestMedusa: + @pytest.mark.complete("medusa -", require_cmd=True) + def test_1(self, completion): + assert completion diff --git a/test/t/test_mencoder.py b/test/t/test_mencoder.py new file mode 100644 index 0000000..a17fb96 --- /dev/null +++ b/test/t/test_mencoder.py @@ -0,0 +1,12 @@ +import pytest + + +@pytest.mark.bashcomp(pre_cmds=("HOME=$PWD/mplayer",)) +class TestMencoder: + @pytest.mark.complete("mencoder ") + def test_1(self, completion): + assert completion + + @pytest.mark.complete("mencoder -v", require_cmd=True) + def test_2(self, completion): + assert completion diff --git a/test/t/test_mii_diag.py b/test/t/test_mii_diag.py new file mode 100644 index 0000000..6ed96aa --- /dev/null +++ b/test/t/test_mii_diag.py @@ -0,0 +1,12 @@ +import pytest + + +@pytest.mark.bashcomp(cmd="mii-diag") +class TestMiiDiag: + @pytest.mark.complete("mii-diag ") + def test_1(self, completion): + assert completion + + @pytest.mark.complete("mii-diag -", require_cmd=True) + def test_2(self, completion): + assert completion diff --git a/test/t/test_mii_tool.py b/test/t/test_mii_tool.py new file mode 100644 index 0000000..f028787 --- /dev/null +++ b/test/t/test_mii_tool.py @@ -0,0 +1,12 @@ +import pytest + + +@pytest.mark.bashcomp(cmd="mii-tool") +class TestMiiTool: + @pytest.mark.complete("mii-tool ") + def test_1(self, completion): + assert completion + + @pytest.mark.complete("mii-tool -", require_cmd=True) + def test_2(self, completion): + assert completion diff --git a/test/t/test_minicom.py b/test/t/test_minicom.py new file mode 100644 index 0000000..6fac457 --- /dev/null +++ b/test/t/test_minicom.py @@ -0,0 +1,7 @@ +import pytest + + +class TestMinicom: + @pytest.mark.complete("minicom -", require_cmd=True) + def test_1(self, completion): + assert completion diff --git a/test/t/test_mkdir.py b/test/t/test_mkdir.py new file mode 100644 index 0000000..afc3fd0 --- /dev/null +++ b/test/t/test_mkdir.py @@ -0,0 +1,21 @@ +import pytest + + +class TestMkdir: + @pytest.mark.complete("mkdir ") + def test_1(self, completion): + assert completion + + @pytest.mark.complete("mkdir ", cwd="shared/default") + def test_2(self, completion): + 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/") + def test_3(self, completion): + assert completion.output == "foo" + assert completion == [completion.output] + + @pytest.mark.complete("mkdir -", require_longopt=True) + def test_options(self, completion): + assert completion diff --git a/test/t/test_mkfifo.py b/test/t/test_mkfifo.py new file mode 100644 index 0000000..92e82de --- /dev/null +++ b/test/t/test_mkfifo.py @@ -0,0 +1,11 @@ +import pytest + + +class TestMkfifo: + @pytest.mark.complete("mkfifo ") + def test_1(self, completion): + assert completion + + @pytest.mark.complete("mkfifo -", require_longopt=True) + def test_options(self, completion): + assert completion diff --git a/test/t/test_mkinitrd.py b/test/t/test_mkinitrd.py new file mode 100644 index 0000000..7305925 --- /dev/null +++ b/test/t/test_mkinitrd.py @@ -0,0 +1,7 @@ +import pytest + + +class TestMkinitrd: + @pytest.mark.complete("mkinitrd ") + def test_1(self, completion): + assert completion diff --git a/test/t/test_mkisofs.py b/test/t/test_mkisofs.py new file mode 100644 index 0000000..541c6e7 --- /dev/null +++ b/test/t/test_mkisofs.py @@ -0,0 +1,15 @@ +import pytest + + +class TestMkisofs: + @pytest.mark.complete("mkisofs ") + def test_1(self, completion): + assert completion + + @pytest.mark.complete("mkisofs -uid ") + def test_2(self, completion): + assert not [x for x in completion if not x.isdigit()] + + @pytest.mark.complete("mkisofs -gid ") + def test_3(self, completion): + assert not [x for x in completion if not x.isdigit()] diff --git a/test/t/test_mknod.py b/test/t/test_mknod.py new file mode 100644 index 0000000..03f21e8 --- /dev/null +++ b/test/t/test_mknod.py @@ -0,0 +1,11 @@ +import pytest + + +class TestMknod: + @pytest.mark.complete("mknod ") + def test_1(self, completion): + assert completion + + @pytest.mark.complete("mknod -", require_longopt=True) + def test_options(self, completion): + assert completion diff --git a/test/t/test_mktemp.py b/test/t/test_mktemp.py new file mode 100644 index 0000000..9f61be1 --- /dev/null +++ b/test/t/test_mktemp.py @@ -0,0 +1,7 @@ +import pytest + + +class TestMktemp: + @pytest.mark.complete("mktemp -") + def test_1(self, completion): + assert completion diff --git a/test/t/test_mmsitepass.py b/test/t/test_mmsitepass.py new file mode 100644 index 0000000..4dcd9fb --- /dev/null +++ b/test/t/test_mmsitepass.py @@ -0,0 +1,7 @@ +import pytest + + +class TestMmsitepass: + @pytest.mark.complete("mmsitepass -") + def test_1(self, completion): + assert completion diff --git a/test/t/test_mock.py b/test/t/test_mock.py new file mode 100644 index 0000000..5f9eb3e --- /dev/null +++ b/test/t/test_mock.py @@ -0,0 +1,13 @@ +import pytest + + +class TestMock: + @pytest.mark.complete("mock ") + def test_1(self, completion): + assert completion + + @pytest.mark.complete( + "mock -", require_cmd=True, xfail="! mock --help &>/dev/null" + ) + def test_2(self, completion): + assert completion diff --git a/test/t/test_modinfo.py b/test/t/test_modinfo.py new file mode 100644 index 0000000..a4f5c50 --- /dev/null +++ b/test/t/test_modinfo.py @@ -0,0 +1,32 @@ +import subprocess + +import pytest + + +class TestModinfo: + @pytest.mark.complete("modinfo -", require_cmd=True) + def test_1(self, completion): + assert completion + + # "in": intel*, ... + @pytest.mark.complete( + "modinfo in", + xfail="! ls /lib/modules/%s &>/dev/null" + % subprocess.check_output( + "uname -r 2>/dev/null || " "echo non-existent-kernel", shell=True + ) + .decode() + .strip(), + ) + def test_2(self, completion): + assert completion + + # "in": intel*, ... + @pytest.mark.complete("modinfo -k non-existent-kernel in") + def test_3(self, completion): + assert not completion + + @pytest.mark.complete("modinfo /tm") + def test_4(self, completion): + assert completion + assert not completion.endswith(" ") diff --git a/test/t/test_modprobe.py b/test/t/test_modprobe.py new file mode 100644 index 0000000..9201119 --- /dev/null +++ b/test/t/test_modprobe.py @@ -0,0 +1,36 @@ +import subprocess + +import pytest + + +class TestModprobe: + @pytest.mark.complete("modprobe --al") + def test_1(self, completion): + assert completion == "l" + + # "in": intel*, ... + @pytest.mark.complete( + "modprobe in", + xfail="! ls /lib/modules/%s &>/dev/null" + % subprocess.check_output( + "uname -r 2>/dev/null || " "echo non-existent-kernel", shell=True + ) + .decode() + .strip(), + ) + def test_2(self, completion): + assert completion + + # "in": intel*, ... + @pytest.mark.complete("modprobe -S non-existent-kernel in") + def test_3(self, completion): + assert not completion + + @pytest.mark.complete("modprobe non-existent-module ") + def test_4(self, completion): + assert not completion + + @pytest.mark.complete("modprobe /tm") + def test_5(self, completion): + assert completion + assert not completion.endswith(" ") diff --git a/test/t/test_module.py b/test/t/test_module.py new file mode 100644 index 0000000..a66dea7 --- /dev/null +++ b/test/t/test_module.py @@ -0,0 +1,7 @@ +import pytest + + +class TestModule: + @pytest.mark.complete("module ") + def test_1(self, completion): + assert completion diff --git a/test/t/test_mogrify.py b/test/t/test_mogrify.py new file mode 100644 index 0000000..22d84a8 --- /dev/null +++ b/test/t/test_mogrify.py @@ -0,0 +1,7 @@ +import pytest + + +class TestMogrify: + @pytest.mark.complete("mogrify ") + def test_1(self, completion): + assert completion diff --git a/test/t/test_monodevelop.py b/test/t/test_monodevelop.py new file mode 100644 index 0000000..59435a1 --- /dev/null +++ b/test/t/test_monodevelop.py @@ -0,0 +1,11 @@ +import pytest + + +class TestMonodevelop: + @pytest.mark.complete("monodevelop ") + def test_1(self, completion): + assert completion + + @pytest.mark.complete("monodevelop -", require_cmd=True) + def test_2(self, completion): + assert completion diff --git a/test/t/test_montage.py b/test/t/test_montage.py new file mode 100644 index 0000000..1237c7d --- /dev/null +++ b/test/t/test_montage.py @@ -0,0 +1,7 @@ +import pytest + + +class TestMontage: + @pytest.mark.complete("montage ") + def test_1(self, completion): + assert completion diff --git a/test/t/test_mount.py b/test/t/test_mount.py new file mode 100644 index 0000000..8254fd4 --- /dev/null +++ b/test/t/test_mount.py @@ -0,0 +1,22 @@ +import pytest + + +class TestMount: + @pytest.mark.complete("mount ") + def test_1(self, completion): + assert completion + + @pytest.mark.complete("mount -t ") + def test_2(self, completion): + assert completion + + @pytest.mark.complete("mount /dev/sda1 def", cwd="shared") + def test_3(self, completion): + assert completion == "ault/" + assert not completion.endswith(" ") + + @pytest.mark.complete( + "mount mocksrv:/", env=dict(PATH="$PWD/mount/bin:$PATH") + ) + def test_4(self, completion): + assert completion == "/second/path /test/path /test/path2".split() diff --git a/test/t/test_mplayer.py b/test/t/test_mplayer.py new file mode 100644 index 0000000..a06991b --- /dev/null +++ b/test/t/test_mplayer.py @@ -0,0 +1,12 @@ +import pytest + + +@pytest.mark.bashcomp(pre_cmds=("HOME=$PWD/mplayer",)) +class TestMplayer: + @pytest.mark.complete("mplayer ") + def test_1(self, completion): + assert completion + + @pytest.mark.complete("mplayer -h", require_cmd=True) + def test_2(self, completion): + assert completion diff --git a/test/t/test_mr.py b/test/t/test_mr.py new file mode 100644 index 0000000..bfad643 --- /dev/null +++ b/test/t/test_mr.py @@ -0,0 +1,58 @@ +import pytest + + +class TestMr: + @pytest.mark.complete("mr ") + def test_1(self, completion): + assert completion + + # man -h tests below: Some mr versions require man to be around in order + # to provide useful output. + + @pytest.mark.complete( + "mr --", require_cmd=True, xfail="! man -h &>/dev/null" + ) + def test_2(self, completion): + assert completion + + @pytest.mark.complete( + "mr -c shared/default/foo.d/", xfail="! man -h &>/dev/null" + ) + def test_3(self, completion): + assert completion == "foo" + + @pytest.mark.complete( + "mr bootstrap shared/default/", + require_cmd=True, + xfail="! man -h &>/dev/null", + ) + def test_4(self, completion): + assert completion == ["bar", "bar bar.d/", "foo", "foo.d/"] + + @pytest.mark.complete( + "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" + + @pytest.mark.complete( + "mr commit -", require_cmd=True, xfail="! man -h &>/dev/null" + ) + def test_6(self, completion): + assert completion == "m" + + @pytest.mark.complete( + "mr status ", require_cmd=True, xfail="! man -h &>/dev/null" + ) + def test_7(self, completion): + assert not completion + + @pytest.mark.complete( + "mr run ", require_cmd=True, xfail="! man -h &>/dev/null" + ) + def test_8(self, completion): + assert completion diff --git a/test/t/test_msgsnarf.py b/test/t/test_msgsnarf.py new file mode 100644 index 0000000..7484456 --- /dev/null +++ b/test/t/test_msgsnarf.py @@ -0,0 +1,7 @@ +import pytest + + +class TestMsgsnarf: + @pytest.mark.complete("msgsnarf -", require_cmd=True) + def test_1(self, completion): + assert completion diff --git a/test/t/test_msynctool.py b/test/t/test_msynctool.py new file mode 100644 index 0000000..530d751 --- /dev/null +++ b/test/t/test_msynctool.py @@ -0,0 +1,7 @@ +import pytest + + +class TestMsynctool: + @pytest.mark.complete("msynctool ") + def test_1(self, completion): + assert completion diff --git a/test/t/test_mtx.py b/test/t/test_mtx.py new file mode 100644 index 0000000..6b6f59b --- /dev/null +++ b/test/t/test_mtx.py @@ -0,0 +1,7 @@ +import pytest + + +class TestMtx: + @pytest.mark.complete("mtx ") + def test_1(self, completion): + assert completion diff --git a/test/t/test_munin_node_configure.py b/test/t/test_munin_node_configure.py new file mode 100644 index 0000000..e7570d8 --- /dev/null +++ b/test/t/test_munin_node_configure.py @@ -0,0 +1,19 @@ +import pytest + + +@pytest.mark.bashcomp(cmd="munin-node-configure") +class TestMuninNodeConfigure: + @pytest.mark.complete("munin-node-configure --libdir ") + def test_1(self, completion): + assert completion + + @pytest.mark.complete( + "munin-node-configure -", + require_cmd=True, + xfail=( + "! (munin-node-configure --help 2>&1 || :) " + "| command grep -q -- '[[:space:]]-'" + ), + ) + def test_2(self, completion): + assert completion diff --git a/test/t/test_munin_run.py b/test/t/test_munin_run.py new file mode 100644 index 0000000..a031449 --- /dev/null +++ b/test/t/test_munin_run.py @@ -0,0 +1,8 @@ +import pytest + + +@pytest.mark.bashcomp(cmd="munin-run") +class TestMuninRun: + @pytest.mark.complete("munin-run -", require_cmd=True) + def test_1(self, completion): + assert completion diff --git a/test/t/test_munindoc.py b/test/t/test_munindoc.py new file mode 100644 index 0000000..eea13ca --- /dev/null +++ b/test/t/test_munindoc.py @@ -0,0 +1,10 @@ +import pytest + + +class TestMunindoc: + + # Assume at least munin* available + # require_cmd is not strictly correct here, but... + @pytest.mark.complete("munindoc m", require_cmd=True) + def test_1(self, completion): + assert completion diff --git a/test/t/test_mussh.py b/test/t/test_mussh.py new file mode 100644 index 0000000..357c2b5 --- /dev/null +++ b/test/t/test_mussh.py @@ -0,0 +1,7 @@ +import pytest + + +class TestMussh: + @pytest.mark.complete("mussh -", require_cmd=True) + def test_1(self, completion): + assert completion diff --git a/test/t/test_mutt.py b/test/t/test_mutt.py new file mode 100644 index 0000000..0c4074f --- /dev/null +++ b/test/t/test_mutt.py @@ -0,0 +1,33 @@ +import pytest + +from conftest import assert_bash_exec + + +@pytest.mark.bashcomp(pre_cmds=("HOME=$PWD/mutt",)) +class TestMutt: + @pytest.mark.complete("mutt -") + def test_1(self, completion): + assert completion + + @pytest.mark.complete("mutt -F muttrc -f =", require_cmd=True, cwd="mutt") + def test_2(self, completion): + assert completion == "bar/ foo/ muttrc".split() + + @pytest.mark.complete("mutt -F muttrc -A ", cwd="mutt") + def test_3(self, completion): + assert completion == "a1 a2".split() + + def test_4(self, bash): + got = ( + assert_bash_exec( + bash, + '_muttconffiles "$HOME/muttrc" "$HOME/muttrc"', + want_output=True, + ) + .strip() + .split() + ) + assert got == [ + "%s/mutt/%s" % (bash.cwd, x) + for x in ("muttrc", "bar/muttrc_b", "foo/muttrc_f") + ] diff --git a/test/t/test_muttng.py b/test/t/test_muttng.py new file mode 100644 index 0000000..3ce19ac --- /dev/null +++ b/test/t/test_muttng.py @@ -0,0 +1,7 @@ +import pytest + + +class TestMuttng: + @pytest.mark.complete("muttng -") + def test_1(self, completion): + assert completion diff --git a/test/t/test_mv.py b/test/t/test_mv.py new file mode 100644 index 0000000..4a354db --- /dev/null +++ b/test/t/test_mv.py @@ -0,0 +1,11 @@ +import pytest + + +class TestMv: + @pytest.mark.complete("mv ") + def test_1(self, completion): + assert completion + + @pytest.mark.complete("mv -", require_longopt=True) + def test_options(self, completion): + assert completion diff --git a/test/t/test_mypy.py b/test/t/test_mypy.py new file mode 100644 index 0000000..11628c1 --- /dev/null +++ b/test/t/test_mypy.py @@ -0,0 +1,15 @@ +import pytest + + +class TestMypy: + @pytest.mark.complete("mypy ") + def test_1(self, completion): + assert completion + + @pytest.mark.complete("mypy --", require_cmd=True, require_longopt=True) + def test_2(self, completion): + assert completion + + @pytest.mark.complete("mypy --non-existent-option=--") + def test_3(self, completion): + assert not completion diff --git a/test/t/test_mysql.py b/test/t/test_mysql.py new file mode 100644 index 0000000..6a44b7e --- /dev/null +++ b/test/t/test_mysql.py @@ -0,0 +1,15 @@ +import pytest + + +class TestMysql: + @pytest.mark.complete("mysql --") + def test_1(self, completion): + assert completion + + @pytest.mark.complete("mysql --default-character-set=") + def test_2(self, completion): + assert completion + + @pytest.mark.complete("mysql --non-existent-option=--") + def test_3(self, completion): + assert not completion diff --git a/test/t/test_mysqladmin.py b/test/t/test_mysqladmin.py new file mode 100644 index 0000000..85046fe --- /dev/null +++ b/test/t/test_mysqladmin.py @@ -0,0 +1,7 @@ +import pytest + + +class TestMysqladmin: + @pytest.mark.complete("mysqladmin -", require_cmd=True) + def test_1(self, completion): + assert completion diff --git a/test/t/test_nc.py b/test/t/test_nc.py new file mode 100644 index 0000000..38db5ac --- /dev/null +++ b/test/t/test_nc.py @@ -0,0 +1,7 @@ +import pytest + + +class TestNc: + @pytest.mark.complete("nc -", require_cmd=True) + def test_1(self, completion): + assert completion diff --git a/test/t/test_ncftp.py b/test/t/test_ncftp.py new file mode 100644 index 0000000..b37f48f --- /dev/null +++ b/test/t/test_ncftp.py @@ -0,0 +1,11 @@ +import pytest + + +class TestNcftp: + @pytest.mark.complete("ncftp ") + def test_1(self, completion): + assert completion + + @pytest.mark.complete("ncftp -", require_cmd=True) + def test_2(self, completion): + assert completion diff --git a/test/t/test_nethogs.py b/test/t/test_nethogs.py new file mode 100644 index 0000000..c57185f --- /dev/null +++ b/test/t/test_nethogs.py @@ -0,0 +1,11 @@ +import pytest + + +class TestNethogs: + @pytest.mark.complete("nethogs ") + def test_1(self, completion): + assert completion + + @pytest.mark.complete("nethogs -", require_cmd=True) + def test_2(self, completion): + assert completion diff --git a/test/t/test_netstat.py b/test/t/test_netstat.py new file mode 100644 index 0000000..57ef26c --- /dev/null +++ b/test/t/test_netstat.py @@ -0,0 +1,11 @@ +import pytest + + +class TestNetstat: + @pytest.mark.complete("netstat ") + def test_1(self, completion): + assert completion + + @pytest.mark.complete("netstat -", require_longopt=True) + def test_options(self, completion): + assert completion diff --git a/test/t/test_newgrp.py b/test/t/test_newgrp.py new file mode 100644 index 0000000..7d65a16 --- /dev/null +++ b/test/t/test_newgrp.py @@ -0,0 +1,7 @@ +import pytest + + +class TestNewgrp: + @pytest.mark.complete("newgrp ") + def test_1(self, completion): + assert completion diff --git a/test/t/test_newlist.py b/test/t/test_newlist.py new file mode 100644 index 0000000..1d6b439 --- /dev/null +++ b/test/t/test_newlist.py @@ -0,0 +1,7 @@ +import pytest + + +class TestNewlist: + @pytest.mark.complete("newlist -", require_cmd=True) + def test_1(self, completion): + assert completion diff --git a/test/t/test_newusers.py b/test/t/test_newusers.py new file mode 100644 index 0000000..51d746a --- /dev/null +++ b/test/t/test_newusers.py @@ -0,0 +1,11 @@ +import pytest + + +class TestNewusers: + @pytest.mark.complete("newusers ") + def test_1(self, completion): + assert completion + + @pytest.mark.complete("newusers -", require_cmd=True) + def test_2(self, completion): + assert completion diff --git a/test/t/test_ngrep.py b/test/t/test_ngrep.py new file mode 100644 index 0000000..53fa60d --- /dev/null +++ b/test/t/test_ngrep.py @@ -0,0 +1,11 @@ +import pytest + + +class TestNgrep: + @pytest.mark.complete("ngrep -", require_cmd=True) + def test_1(self, completion): + assert completion + + @pytest.mark.complete("ngrep -d ") + def test_2(self, completion): + assert completion diff --git a/test/t/test_nl.py b/test/t/test_nl.py new file mode 100644 index 0000000..ca910a5 --- /dev/null +++ b/test/t/test_nl.py @@ -0,0 +1,11 @@ +import pytest + + +class TestNl: + @pytest.mark.complete("nl ") + def test_1(self, completion): + assert completion + + @pytest.mark.complete("nl -", require_longopt=True) + def test_options(self, completion): + assert completion diff --git a/test/t/test_nm.py b/test/t/test_nm.py new file mode 100644 index 0000000..328fa50 --- /dev/null +++ b/test/t/test_nm.py @@ -0,0 +1,11 @@ +import pytest + + +class TestNm: + @pytest.mark.complete("nm ") + def test_1(self, completion): + assert completion + + @pytest.mark.complete("nm -", require_cmd=True) + def test_options(self, completion): + assert completion diff --git a/test/t/test_nmap.py b/test/t/test_nmap.py new file mode 100644 index 0000000..9aff8b2 --- /dev/null +++ b/test/t/test_nmap.py @@ -0,0 +1,47 @@ +import pytest + +from conftest import assert_bash_exec + + +class TestNmap: + @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_nmcli.py b/test/t/test_nmcli.py new file mode 100644 index 0000000..f2b7950 --- /dev/null +++ b/test/t/test_nmcli.py @@ -0,0 +1,7 @@ +import pytest + + +class TestNmcli: + @pytest.mark.complete("nmcli ") + def test_1(self, completion): + assert completion diff --git a/test/t/test_nproc.py b/test/t/test_nproc.py new file mode 100644 index 0000000..66a49ac --- /dev/null +++ b/test/t/test_nproc.py @@ -0,0 +1,17 @@ +import pytest + + +class TestNproc: + @pytest.mark.complete("nproc ") + def test_1(self, completion): + assert not completion + + @pytest.mark.complete( + "nproc --", + xfail=( + "! nproc --help &>/dev/null || " + "! nproc --help 2>&1 | command grep -qF -- --help" + ), + ) + def test_2(self, completion): + assert completion diff --git a/test/t/test_nslookup.py b/test/t/test_nslookup.py new file mode 100644 index 0000000..0286509 --- /dev/null +++ b/test/t/test_nslookup.py @@ -0,0 +1,7 @@ +import pytest + + +class TestNslookup: + @pytest.mark.complete("nslookup -") + def test_1(self, completion): + assert completion diff --git a/test/t/test_nsupdate.py b/test/t/test_nsupdate.py new file mode 100644 index 0000000..b8a133c --- /dev/null +++ b/test/t/test_nsupdate.py @@ -0,0 +1,11 @@ +import pytest + + +class TestNsupdate: + @pytest.mark.complete("nsupdate ") + def test_1(self, completion): + assert completion + + @pytest.mark.complete("nsupdate -", require_cmd=True) + def test_2(self, completion): + assert completion diff --git a/test/t/test_ntpdate.py b/test/t/test_ntpdate.py new file mode 100644 index 0000000..c8d65cf --- /dev/null +++ b/test/t/test_ntpdate.py @@ -0,0 +1,7 @@ +import pytest + + +class TestNtpdate: + @pytest.mark.complete("ntpdate -", require_cmd=True) + def test_1(self, completion): + assert completion diff --git a/test/t/test_objcopy.py b/test/t/test_objcopy.py new file mode 100644 index 0000000..e3130fa --- /dev/null +++ b/test/t/test_objcopy.py @@ -0,0 +1,11 @@ +import pytest + + +class TestObjcopy: + @pytest.mark.complete("objcopy ") + def test_1(self, completion): + assert completion + + @pytest.mark.complete("objcopy -", require_cmd=True) + def test_options(self, completion): + assert completion diff --git a/test/t/test_objdump.py b/test/t/test_objdump.py new file mode 100644 index 0000000..6b8bc74 --- /dev/null +++ b/test/t/test_objdump.py @@ -0,0 +1,7 @@ +import pytest + + +class TestObjdump: + @pytest.mark.complete("objdump ") + def test_1(self, completion): + assert completion diff --git a/test/t/test_od.py b/test/t/test_od.py new file mode 100644 index 0000000..e2f5de2 --- /dev/null +++ b/test/t/test_od.py @@ -0,0 +1,11 @@ +import pytest + + +class TestOd: + @pytest.mark.complete("od ") + def test_1(self, completion): + assert completion + + @pytest.mark.complete("od -", require_longopt=True) + def test_options(self, completion): + assert completion diff --git a/test/t/test_oggdec.py b/test/t/test_oggdec.py new file mode 100644 index 0000000..395bb86 --- /dev/null +++ b/test/t/test_oggdec.py @@ -0,0 +1,11 @@ +import pytest + + +class TestOggdec: + @pytest.mark.complete("oggdec ") + def test_1(self, completion): + assert completion + + @pytest.mark.complete("oggdec --", require_cmd=True) + def test_2(self, completion): + assert completion diff --git a/test/t/test_op.py b/test/t/test_op.py new file mode 100644 index 0000000..662cde5 --- /dev/null +++ b/test/t/test_op.py @@ -0,0 +1,11 @@ +import pytest + + +class TestOp: + @pytest.mark.complete("op ", require_cmd=True) + def test_1(self, completion): + assert completion + + @pytest.mark.complete("op --", require_cmd=True) + def test_2(self, completion): + assert completion diff --git a/test/t/test_openssl.py b/test/t/test_openssl.py new file mode 100644 index 0000000..3eaf6d4 --- /dev/null +++ b/test/t/test_openssl.py @@ -0,0 +1,16 @@ +import pytest + + +class TestOpenssl: + @pytest.mark.complete("openssl ") + def test_1(self, completion): + assert completion + + @pytest.mark.complete("openssl pkey -cipher ", require_cmd=True) + def test_2(self, completion): + assert completion + + @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_opera.py b/test/t/test_opera.py new file mode 100644 index 0000000..f0c657e --- /dev/null +++ b/test/t/test_opera.py @@ -0,0 +1,11 @@ +import pytest + + +class TestOpera: + @pytest.mark.complete("opera ") + def test_1(self, completion): + assert completion + + @pytest.mark.complete("opera -", require_cmd=True) + def test_2(self, completion): + assert completion diff --git a/test/t/test_optipng.py b/test/t/test_optipng.py new file mode 100644 index 0000000..615d71f --- /dev/null +++ b/test/t/test_optipng.py @@ -0,0 +1,11 @@ +import pytest + + +class TestOptipng: + @pytest.mark.complete("optipng ") + def test_1(self, completion): + assert completion + + @pytest.mark.complete("optipng -", require_cmd=True) + def test_2(self, completion): + assert completion diff --git a/test/t/test_p4.py b/test/t/test_p4.py new file mode 100644 index 0000000..876d261 --- /dev/null +++ b/test/t/test_p4.py @@ -0,0 +1,7 @@ +import pytest + + +class TestP4: + @pytest.mark.complete("p4 ") + def test_1(self, completion): + assert completion diff --git a/test/t/test_pack200.py b/test/t/test_pack200.py new file mode 100644 index 0000000..0960133 --- /dev/null +++ b/test/t/test_pack200.py @@ -0,0 +1,7 @@ +import pytest + + +class TestPack200: + @pytest.mark.complete("pack200 ") + def test_1(self, completion): + assert completion diff --git a/test/t/test_passwd.py b/test/t/test_passwd.py new file mode 100644 index 0000000..f253701 --- /dev/null +++ b/test/t/test_passwd.py @@ -0,0 +1,11 @@ +import pytest + + +class TestPasswd: + @pytest.mark.complete("passwd ") + def test_1(self, completion): + assert completion + + @pytest.mark.complete("passwd -", require_cmd=True) + def test_2(self, completion): + assert completion diff --git a/test/t/test_paste.py b/test/t/test_paste.py new file mode 100644 index 0000000..ecf030b --- /dev/null +++ b/test/t/test_paste.py @@ -0,0 +1,11 @@ +import pytest + + +class TestPaste: + @pytest.mark.complete("paste ") + def test_1(self, completion): + assert completion + + @pytest.mark.complete("paste -", require_longopt=True) + def test_options(self, completion): + assert completion diff --git a/test/t/test_patch.py b/test/t/test_patch.py new file mode 100644 index 0000000..c68a4b6 --- /dev/null +++ b/test/t/test_patch.py @@ -0,0 +1,11 @@ +import pytest + + +class TestPatch: + @pytest.mark.complete("patch ") + def test_1(self, completion): + assert completion + + @pytest.mark.complete("patch -", require_cmd=True) + def test_2(self, completion): + assert completion diff --git a/test/t/test_pdftotext.py b/test/t/test_pdftotext.py new file mode 100644 index 0000000..90d001f --- /dev/null +++ b/test/t/test_pdftotext.py @@ -0,0 +1,11 @@ +import pytest + + +class TestPdftotext: + @pytest.mark.complete("pdftotext ") + def test_1(self, completion): + assert completion + + @pytest.mark.complete("pdftotext -", require_cmd=True) + def test_2(self, completion): + assert completion diff --git a/test/t/test_perl.py b/test/t/test_perl.py new file mode 100644 index 0000000..049c91e --- /dev/null +++ b/test/t/test_perl.py @@ -0,0 +1,91 @@ +import pytest + + +@pytest.mark.bashcomp(ignore_env=r"^\+PERL5LIB=") +class TestPerl: + @pytest.mark.complete("perl ") + def test_1(self, completion): + assert completion + + @pytest.mark.complete("perl -e ") + def test_2(self, completion): + assert not completion + + @pytest.mark.complete("perl -V:install", require_cmd=True) + def test_3(self, completion): + assert completion + + @pytest.mark.complete("perl -V::install", require_cmd=True) + def test_4(self, completion): + assert completion + + # Assume File::Spec and friends are always installed + + @pytest.mark.complete("perl -MFile", require_cmd=True) + def test_5(self, completion): + assert completion + + @pytest.mark.complete("perl -MFile::Sp", require_cmd=True) + def test_6(self, completion): + assert completion + + @pytest.mark.complete("perl -MFile::Spec::Func", require_cmd=True) + def test_7(self, completion): + assert completion + + @pytest.mark.complete("perl -M-File", require_cmd=True) + def test_8(self, completion): + assert completion + + @pytest.mark.complete("perl -m-File::", require_cmd=True) + def test_9(self, completion): + assert completion + + @pytest.mark.complete("perl -") + def test_10(self, completion): + assert completion + + @pytest.mark.complete("perl foo shared/default/f") + def test_11(self, completion): + """Second arg should complete files+dirs.""" + assert completion == "foo foo.d/".split() + + @pytest.mark.complete("perl -Ishared/default/") + def test_12(self, completion): + """-I without space should complete dirs.""" + assert completion == ["bar bar.d/", "foo.d/"] + + @pytest.mark.complete("perl -I shared/default/") + def test_13(self, completion): + """-I with space should complete dirs.""" + assert completion == ["bar bar.d/", "foo.d/"] + + @pytest.mark.complete("perl -xshared/default/b") + def test_14(self, completion): + """-x without space should complete dirs.""" + assert completion == r"ar\ bar.d/" + + @pytest.mark.complete("perl -x shared/default/b") + def test_15(self, completion): + """-x with space should complete files+dirs.""" + assert completion == ["bar", "bar bar.d/"] + + @pytest.mark.complete( + "perl -d:", env=dict(PERL5LIB="$PWD/perl"), require_cmd=True + ) + def test_16(self, completion): + assert "BashCompletion" in completion + + @pytest.mark.complete( + "perl -dt:", env=dict(PERL5LIB="$PWD/perl"), require_cmd=True + ) + def test_17(self, completion): + assert "BashCompletion" in completion + + @pytest.mark.complete("perl -E ") + def test_dash_capital_e(self, completion): + assert not completion + + @pytest.mark.complete("perl -e") + def test_dash_e(self, completion): + assert not completion diff --git a/test/t/test_perlcritic.py b/test/t/test_perlcritic.py new file mode 100644 index 0000000..51ba201 --- /dev/null +++ b/test/t/test_perlcritic.py @@ -0,0 +1,15 @@ +import pytest + + +class TestPerlcritic: + @pytest.mark.complete("perlcritic ") + def test_1(self, completion): + assert completion + + @pytest.mark.complete("perlcritic --", require_cmd=True) + def test_2(self, completion): + assert completion + + @pytest.mark.complete("perlcritic --theme ", require_cmd=True) + def test_3(self, completion): + assert completion diff --git a/test/t/test_perldoc.py b/test/t/test_perldoc.py new file mode 100644 index 0000000..282f824 --- /dev/null +++ b/test/t/test_perldoc.py @@ -0,0 +1,18 @@ +import pytest + + +@pytest.mark.bashcomp(pre_cmds=("export PERL5LIB=$PWD/perldoc",)) +class TestPerldoc: + @pytest.mark.complete("perldoc File::") + def test_1(self, completion): + assert "Path" in completion # Assume File::Path always installed + assert "fixtures/" not in completion # Our fixtures/ dir + assert not [x for x in completion if "File::File::" in x] + + @pytest.mark.complete("perldoc -", require_cmd=True) + def test_2(self, completion): + assert completion + + @pytest.mark.complete("perldoc BashCompletion") + def test_3(self, completion): + assert completion == "BashCompletionDoc BashCompletionModule".split() diff --git a/test/t/test_perltidy.py b/test/t/test_perltidy.py new file mode 100644 index 0000000..578923a --- /dev/null +++ b/test/t/test_perltidy.py @@ -0,0 +1,19 @@ +import pytest + + +class TestPerltidy: + @pytest.mark.complete("perltidy ") + def test_1(self, completion): + assert completion + + @pytest.mark.complete("perltidy -h", require_cmd=True) + def test_2(self, completion): + assert completion + + @pytest.mark.complete("perltidy -ole=", require_cmd=True) + def test_3(self, completion): + assert completion + + @pytest.mark.complete("perltidy -doesntexist=", require_cmd=True) + def test_4(self, completion): + assert not completion diff --git a/test/t/test_pgrep.py b/test/t/test_pgrep.py new file mode 100644 index 0000000..9a998ed --- /dev/null +++ b/test/t/test_pgrep.py @@ -0,0 +1,35 @@ +import pytest + + +class TestPgrep: + + # "p": Assume that our process name completion runs ps + @pytest.mark.complete("pgrep p") + def test_1(self, completion): + assert completion + + @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_phing.py b/test/t/test_phing.py new file mode 100644 index 0000000..973a957 --- /dev/null +++ b/test/t/test_phing.py @@ -0,0 +1,11 @@ +import pytest + + +class TestPhing: + @pytest.mark.complete("phing -", require_cmd=True) + def test_1(self, completion): + assert completion + + @pytest.mark.complete("phing -l ", require_cmd=True) + def test_2(self, completion): + assert not completion diff --git a/test/t/test_pidof.py b/test/t/test_pidof.py new file mode 100644 index 0000000..c33a4d3 --- /dev/null +++ b/test/t/test_pidof.py @@ -0,0 +1,15 @@ +import pytest + + +class TestPidof: + + # "p": Assume that our process name completion runs ps + @pytest.mark.complete("pidof p") + def test_1(self, completion): + assert completion + + @pytest.mark.complete( + "pidof -", require_cmd=True, xfail="! pidof --help &>/dev/null" + ) + def test_2(self, completion): + assert completion diff --git a/test/t/test_pine.py b/test/t/test_pine.py new file mode 100644 index 0000000..0c95973 --- /dev/null +++ b/test/t/test_pine.py @@ -0,0 +1,7 @@ +import pytest + + +class TestPine: + @pytest.mark.complete("pine -", require_cmd=True) + def test_1(self, completion): + assert completion diff --git a/test/t/test_pinfo.py b/test/t/test_pinfo.py new file mode 100644 index 0000000..a22128e --- /dev/null +++ b/test/t/test_pinfo.py @@ -0,0 +1,12 @@ +import pytest + + +@pytest.mark.bashcomp(pre_cmds=("INFOPATH+=:$PWD/info:",)) +class TestPinfo: + @pytest.mark.complete("pinfo -", require_cmd=True) + def test_1(self, completion): + assert completion + + @pytest.mark.complete("pinfo bash") + def test_2(self, completion): + assert completion diff --git a/test/t/test_ping.py b/test/t/test_ping.py new file mode 100644 index 0000000..f70582a --- /dev/null +++ b/test/t/test_ping.py @@ -0,0 +1,11 @@ +import pytest + + +class TestPing: + @pytest.mark.complete("ping ") + def test_1(self, completion): + assert completion + + @pytest.mark.complete("ping -", require_cmd=True) + def test_2(self, completion): + assert completion diff --git a/test/t/test_pkg_config.py b/test/t/test_pkg_config.py new file mode 100644 index 0000000..81e02ca --- /dev/null +++ b/test/t/test_pkg_config.py @@ -0,0 +1,12 @@ +import pytest + + +@pytest.mark.bashcomp(cmd="pkg-config") +class TestPkgConfig: + @pytest.mark.complete("pkg-config ") + def test_1(self, completion): + assert completion + + @pytest.mark.complete("pkg-config -", require_cmd=True) + def test_2(self, completion): + assert completion diff --git a/test/t/test_pkg_deinstall.py b/test/t/test_pkg_deinstall.py new file mode 100644 index 0000000..5ce6d13 --- /dev/null +++ b/test/t/test_pkg_deinstall.py @@ -0,0 +1,15 @@ +import os + +import pytest + + +@pytest.mark.bashcomp(pre_cmds=("PKG_DBDIR=$PWD/pkgtools/db",)) +class TestPkgDeinstall: + @pytest.mark.complete("pkg_deinstall ") + def test_1(self, completion): + dirs = sorted( + x + for x in os.listdir("pkgtools/db") + if os.path.isdir("pkgtools/db/%s" % x) + ) + assert completion == dirs diff --git a/test/t/test_pkg_delete.py b/test/t/test_pkg_delete.py new file mode 100644 index 0000000..a4b0d85 --- /dev/null +++ b/test/t/test_pkg_delete.py @@ -0,0 +1,7 @@ +import pytest + + +class TestPkgDelete: + @pytest.mark.complete("pkg_delete ") + def test_1(self, completion): + assert completion diff --git a/test/t/test_pkg_get.py b/test/t/test_pkg_get.py new file mode 100644 index 0000000..cb2d283 --- /dev/null +++ b/test/t/test_pkg_get.py @@ -0,0 +1,8 @@ +import pytest + + +@pytest.mark.bashcomp(cmd="pkg-get") +class TestPkgGet: + @pytest.mark.complete("pkg-get ") + def test_1(self, completion): + assert completion diff --git a/test/t/test_pkg_info.py b/test/t/test_pkg_info.py new file mode 100644 index 0000000..6011f81 --- /dev/null +++ b/test/t/test_pkg_info.py @@ -0,0 +1,7 @@ +import pytest + + +class TestPkgInfo: + @pytest.mark.complete("pkg_info ") + def test_1(self, completion): + assert completion diff --git a/test/t/test_pkgadd.py b/test/t/test_pkgadd.py new file mode 100644 index 0000000..69d08dc --- /dev/null +++ b/test/t/test_pkgadd.py @@ -0,0 +1,8 @@ +import pytest + + +class TestPkgadd: + # require_cmd is not strictly true here, but... + @pytest.mark.complete("pkgadd ", require_cmd=True) + def test_1(self, completion): + assert completion diff --git a/test/t/test_pkgrm.py b/test/t/test_pkgrm.py new file mode 100644 index 0000000..2af81ef --- /dev/null +++ b/test/t/test_pkgrm.py @@ -0,0 +1,8 @@ +import pytest + + +class TestPkgrm: + # require_cmd is not strictly true here, but... + @pytest.mark.complete("pkgrm ", require_cmd=True) + def test_1(self, completion): + assert completion diff --git a/test/t/test_pkgtool.py b/test/t/test_pkgtool.py new file mode 100644 index 0000000..7d35637 --- /dev/null +++ b/test/t/test_pkgtool.py @@ -0,0 +1,7 @@ +import pytest + + +class TestPkgtool: + @pytest.mark.complete("pkgtool -") + def test_1(self, completion): + assert completion diff --git a/test/t/test_pkgutil.py b/test/t/test_pkgutil.py new file mode 100644 index 0000000..9664728 --- /dev/null +++ b/test/t/test_pkgutil.py @@ -0,0 +1,7 @@ +import pytest + + +class TestPkgutil: + @pytest.mark.complete("pkgutil ") + def test_1(self, completion): + assert completion diff --git a/test/t/test_pkill.py b/test/t/test_pkill.py new file mode 100644 index 0000000..a779958 --- /dev/null +++ b/test/t/test_pkill.py @@ -0,0 +1,11 @@ +import pytest + + +class TestPkill: + @pytest.mark.complete("pkill ") + def test_1(self, completion): + assert completion + + @pytest.mark.complete("pkill -", require_cmd=True) + def test_2(self, completion): + assert completion diff --git a/test/t/test_plague_client.py b/test/t/test_plague_client.py new file mode 100644 index 0000000..39eac93 --- /dev/null +++ b/test/t/test_plague_client.py @@ -0,0 +1,8 @@ +import pytest + + +@pytest.mark.bashcomp(cmd="plague-client") +class TestPlagueClient: + @pytest.mark.complete("plague-client ") + def test_1(self, completion): + assert completion diff --git a/test/t/test_pm_hibernate.py b/test/t/test_pm_hibernate.py new file mode 100644 index 0000000..31b4625 --- /dev/null +++ b/test/t/test_pm_hibernate.py @@ -0,0 +1,8 @@ +import pytest + + +@pytest.mark.bashcomp(cmd="pm-hibernate") +class TestPmHibernate: + @pytest.mark.complete("pm-hibernate -") + def test_1(self, completion): + assert completion diff --git a/test/t/test_pm_is_supported.py b/test/t/test_pm_is_supported.py new file mode 100644 index 0000000..47f064a --- /dev/null +++ b/test/t/test_pm_is_supported.py @@ -0,0 +1,8 @@ +import pytest + + +@pytest.mark.bashcomp(cmd="pm-is-supported") +class TestPmIsSupported: + @pytest.mark.complete("pm-is-supported -") + def test_1(self, completion): + assert completion diff --git a/test/t/test_pm_powersave.py b/test/t/test_pm_powersave.py new file mode 100644 index 0000000..7630a41 --- /dev/null +++ b/test/t/test_pm_powersave.py @@ -0,0 +1,8 @@ +import pytest + + +@pytest.mark.bashcomp(cmd="pm-powersave") +class TestPmPowersave: + @pytest.mark.complete("pm-powersave ") + def test_1(self, completion): + assert completion diff --git a/test/t/test_pngfix.py b/test/t/test_pngfix.py new file mode 100644 index 0000000..9b35a39 --- /dev/null +++ b/test/t/test_pngfix.py @@ -0,0 +1,11 @@ +import pytest + + +class TestPngfix: + @pytest.mark.complete("pngfix ") + def test_1(self, completion): + assert completion + + @pytest.mark.complete("pngfix -", require_cmd=True) + def test_2(self, completion): + assert completion diff --git a/test/t/test_portinstall.py b/test/t/test_portinstall.py new file mode 100644 index 0000000..eb2118e --- /dev/null +++ b/test/t/test_portinstall.py @@ -0,0 +1,27 @@ +import pytest + +from conftest import assert_bash_exec + + +@pytest.mark.bashcomp(ignore_env=r"^[+-]PORTSDIR=") +class TestPortinstall: + @pytest.fixture(scope="class") + def portsdir(self, request, bash): + assert_bash_exec(bash, "PORTSDIR=$PWD/../tmp") + assert_bash_exec( + bash, + "command sed -e s,PORTSDIR,$PORTSDIR,g " + "pkgtools/ports/INDEX.dist >$PORTSDIR/INDEX", + ) + assert_bash_exec(bash, "cp $PORTSDIR/INDEX $PORTSDIR/INDEX-5") + request.addfinalizer( + lambda: assert_bash_exec(bash, "rm $PORTSDIR/INDEX{,-5}") + ) + + @pytest.mark.complete("portinstall ", env=dict(PORTSDIR="$PWD/../tmp")) + def test_1(self, completion, portsdir): + assert ( + completion + == "bash-2.05b.007_6 bash-3.1.17 bash-completion-20060301_2 " + "shells/bash shells/bash-completion shells/bash2".split() + ) diff --git a/test/t/test_portsnap.py b/test/t/test_portsnap.py new file mode 100644 index 0000000..4f5878e --- /dev/null +++ b/test/t/test_portsnap.py @@ -0,0 +1,7 @@ +import pytest + + +class TestPortsnap: + @pytest.mark.complete("portsnap ") + def test_1(self, completion): + assert completion diff --git a/test/t/test_portupgrade.py b/test/t/test_portupgrade.py new file mode 100644 index 0000000..0b46bbf --- /dev/null +++ b/test/t/test_portupgrade.py @@ -0,0 +1,8 @@ +import pytest + + +@pytest.mark.bashcomp(pre_cmds=("PKG_DBDIR=$PWD/pkgtools/db",)) +class TestPortupgrade: + @pytest.mark.complete("portupgrade ") + def test_1(self, completion): + assert completion == "a b-c-d".split() diff --git a/test/t/test_postcat.py b/test/t/test_postcat.py new file mode 100644 index 0000000..73922e2 --- /dev/null +++ b/test/t/test_postcat.py @@ -0,0 +1,11 @@ +import pytest + + +class TestPostcat: + @pytest.mark.complete("postcat ") + def test_1(self, completion): + assert completion + + @pytest.mark.complete("postcat -", require_cmd=True) + def test_2(self, completion): + assert completion diff --git a/test/t/test_postconf.py b/test/t/test_postconf.py new file mode 100644 index 0000000..e034956 --- /dev/null +++ b/test/t/test_postconf.py @@ -0,0 +1,20 @@ +import pytest + + +class TestPostconf: + @pytest.mark.complete("postconf -", require_cmd=True) + def test_1(self, completion): + assert len(completion) > 1 + + # Broken configs may abort output of postconf halfway through, so use + # something from early output to not trigger false positives because of + # this. For example, inet_protocols=all but no IPv6 configured: + # postconf: fatal: parameter inet_interfaces: no local interface found + # for ::1 + # ...and output can be cut off somewhere near lmtp_tls_secur*. + # ...or be completely missing, so all we can do is to skip. + @pytest.mark.complete( + "postconf al", require_cmd=True, xfail="! postconf &>/dev/null" + ) + def test_2(self, completion): + assert completion diff --git a/test/t/test_postfix.py b/test/t/test_postfix.py new file mode 100644 index 0000000..10020b0 --- /dev/null +++ b/test/t/test_postfix.py @@ -0,0 +1,22 @@ +import getpass + +import pytest + + +class TestPostfix: + @pytest.mark.complete("postfix ") + def test_1(self, completion): + assert 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_postmap.py b/test/t/test_postmap.py new file mode 100644 index 0000000..ee3eee7 --- /dev/null +++ b/test/t/test_postmap.py @@ -0,0 +1,11 @@ +import pytest + + +class TestPostmap: + @pytest.mark.complete("postmap ") + def test_1(self, completion): + assert completion + + @pytest.mark.complete("postmap -", require_cmd=True) + def test_2(self, completion): + assert completion diff --git a/test/t/test_postsuper.py b/test/t/test_postsuper.py new file mode 100644 index 0000000..b74de8e --- /dev/null +++ b/test/t/test_postsuper.py @@ -0,0 +1,7 @@ +import pytest + + +class TestPostsuper: + @pytest.mark.complete("postsuper ") + def test_1(self, completion): + assert completion diff --git a/test/t/test_povray.py b/test/t/test_povray.py new file mode 100644 index 0000000..99d08ea --- /dev/null +++ b/test/t/test_povray.py @@ -0,0 +1,7 @@ +import pytest + + +class TestPovray: + @pytest.mark.complete("povray ") + def test_1(self, completion): + assert completion diff --git a/test/t/test_pr.py b/test/t/test_pr.py new file mode 100644 index 0000000..c790a86 --- /dev/null +++ b/test/t/test_pr.py @@ -0,0 +1,11 @@ +import pytest + + +class TestPr: + @pytest.mark.complete("pr ") + def test_1(self, completion): + assert completion + + @pytest.mark.complete("pr -", require_cmd=True) + def test_options(self, completion): + assert completion diff --git a/test/t/test_prelink.py b/test/t/test_prelink.py new file mode 100644 index 0000000..e75b969 --- /dev/null +++ b/test/t/test_prelink.py @@ -0,0 +1,11 @@ +import pytest + + +class TestPrelink: + @pytest.mark.complete("prelink ") + def test_1(self, completion): + assert completion + + @pytest.mark.complete("prelink -", require_cmd=True) + def test_2(self, completion): + assert completion diff --git a/test/t/test_printenv.py b/test/t/test_printenv.py new file mode 100644 index 0000000..540c4f6 --- /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 new file mode 100644 index 0000000..744b99f --- /dev/null +++ b/test/t/test_protoc.py @@ -0,0 +1,20 @@ +import pytest + + +class TestProtoc: + @pytest.mark.complete("protoc ") + def test_1(self, completion): + assert completion + + @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_psql.py b/test/t/test_psql.py new file mode 100644 index 0000000..ffd6c05 --- /dev/null +++ b/test/t/test_psql.py @@ -0,0 +1,11 @@ +import pytest + + +class TestPsql: + + # --help can fail due to missing package dependencies, e.g. on Ubuntu 14 + @pytest.mark.complete( + "psql -", require_cmd=True, xfail="! psql --help &>/dev/null" + ) + def test_1(self, completion): + assert completion diff --git a/test/t/test_ptx.py b/test/t/test_ptx.py new file mode 100644 index 0000000..9ddc91c --- /dev/null +++ b/test/t/test_ptx.py @@ -0,0 +1,11 @@ +import pytest + + +class TestPtx: + @pytest.mark.complete("ptx ") + def test_1(self, completion): + assert completion + + @pytest.mark.complete("ptx -", require_cmd=True) + def test_options(self, completion): + assert completion diff --git a/test/t/test_puppet.py b/test/t/test_puppet.py new file mode 100644 index 0000000..470f33a --- /dev/null +++ b/test/t/test_puppet.py @@ -0,0 +1,11 @@ +import pytest + + +class TestPuppet: + @pytest.mark.complete("puppet ") + def test_1(self, completion): + assert completion + + @pytest.mark.complete("puppet agent --") + def test_2(self, completion): + assert completion diff --git a/test/t/test_pushd.py b/test/t/test_pushd.py new file mode 100644 index 0000000..290e1d1 --- /dev/null +++ b/test/t/test_pushd.py @@ -0,0 +1,7 @@ +import pytest + + +class TestPushd: + @pytest.mark.complete("pushd ") + def test_1(self, completion): + assert completion diff --git a/test/t/test_pv.py b/test/t/test_pv.py new file mode 100644 index 0000000..ad04c47 --- /dev/null +++ b/test/t/test_pv.py @@ -0,0 +1,15 @@ +import pytest + + +class TestPv: + @pytest.mark.complete("pv ") + def test_1(self, completion): + assert completion + + @pytest.mark.complete("pv -", require_cmd=True) + def test_2(self, completion): + assert completion + + @pytest.mark.complete("pv --pidfile ") + def test_3(self, completion): + assert completion diff --git a/test/t/test_pvchange.py b/test/t/test_pvchange.py new file mode 100644 index 0000000..4b0a94c --- /dev/null +++ b/test/t/test_pvchange.py @@ -0,0 +1,9 @@ +import pytest + + +class TestPvchange: + @pytest.mark.complete( + "pvchange --", require_cmd=True, xfail="! pvchange --help &>/dev/null" + ) + def test_1(self, completion): + assert completion diff --git a/test/t/test_pvcreate.py b/test/t/test_pvcreate.py new file mode 100644 index 0000000..2847c47 --- /dev/null +++ b/test/t/test_pvcreate.py @@ -0,0 +1,9 @@ +import pytest + + +class TestPvcreate: + @pytest.mark.complete( + "pvcreate --", require_cmd=True, xfail="! pvcreate --help &>/dev/null" + ) + def test_1(self, completion): + assert completion diff --git a/test/t/test_pvdisplay.py b/test/t/test_pvdisplay.py new file mode 100644 index 0000000..9d1ea83 --- /dev/null +++ b/test/t/test_pvdisplay.py @@ -0,0 +1,11 @@ +import pytest + + +class TestPvdisplay: + @pytest.mark.complete( + "pvdisplay --", + require_cmd=True, + xfail="! pvdisplay --help &>/dev/null", + ) + def test_1(self, completion): + assert completion diff --git a/test/t/test_pvmove.py b/test/t/test_pvmove.py new file mode 100644 index 0000000..e0e2ee8 --- /dev/null +++ b/test/t/test_pvmove.py @@ -0,0 +1,9 @@ +import pytest + + +class TestPvmove: + @pytest.mark.complete( + "pvmove --", require_cmd=True, xfail="! pvmove --help &>/dev/null" + ) + def test_1(self, completion): + assert completion diff --git a/test/t/test_pvremove.py b/test/t/test_pvremove.py new file mode 100644 index 0000000..c9c031a --- /dev/null +++ b/test/t/test_pvremove.py @@ -0,0 +1,9 @@ +import pytest + + +class TestPvremove: + @pytest.mark.complete( + "pvremove --", require_cmd=True, xfail="! pvremove --help &>/dev/null" + ) + def test_1(self, completion): + assert completion diff --git a/test/t/test_pvs.py b/test/t/test_pvs.py new file mode 100644 index 0000000..ac173a7 --- /dev/null +++ b/test/t/test_pvs.py @@ -0,0 +1,9 @@ +import pytest + + +class TestPvs: + @pytest.mark.complete( + "pvs --", require_cmd=True, xfail="! pvs --help &>/dev/null" + ) + def test_1(self, completion): + assert completion diff --git a/test/t/test_pvscan.py b/test/t/test_pvscan.py new file mode 100644 index 0000000..e278956 --- /dev/null +++ b/test/t/test_pvscan.py @@ -0,0 +1,9 @@ +import pytest + + +class TestPvscan: + @pytest.mark.complete( + "pvscan --", require_cmd=True, xfail="! pvscan --help &>/dev/null" + ) + def test_1(self, completion): + assert completion diff --git a/test/t/test_pwck.py b/test/t/test_pwck.py new file mode 100644 index 0000000..1e36f87 --- /dev/null +++ b/test/t/test_pwck.py @@ -0,0 +1,11 @@ +import pytest + + +class TestPwck: + @pytest.mark.complete("pwck ") + def test_1(self, completion): + assert completion + + @pytest.mark.complete("pwck -", require_cmd=True) + def test_2(self, completion): + assert completion diff --git a/test/t/test_pwd.py b/test/t/test_pwd.py new file mode 100644 index 0000000..fe7dd08 --- /dev/null +++ b/test/t/test_pwd.py @@ -0,0 +1,7 @@ +import pytest + + +class TestPwd: + @pytest.mark.complete("pwd -", require_cmd=True) + def test_1(self, completion): + assert completion diff --git a/test/t/test_pwdx.py b/test/t/test_pwdx.py new file mode 100644 index 0000000..552c82c --- /dev/null +++ b/test/t/test_pwdx.py @@ -0,0 +1,19 @@ +import pytest + + +class TestPwdx: + @pytest.mark.complete("pwdx ") + def test_1(self, completion): + assert completion + + @pytest.mark.complete( + "pwdx -", + require_cmd=True, + xfail=( + "! (pwdx --help 2>&1 || :) | " + "command grep -vF 'invalid process id: --help' | " + "command grep -q -- '[[:space:]]-'" + ), + ) + def test_2(self, completion): + assert completion diff --git a/test/t/test_pwgen.py b/test/t/test_pwgen.py new file mode 100644 index 0000000..20ecd73 --- /dev/null +++ b/test/t/test_pwgen.py @@ -0,0 +1,7 @@ +import pytest + + +class TestPwgen: + @pytest.mark.complete("pwgen -", require_cmd=True) + def test_1(self, completion): + assert completion diff --git a/test/t/test_pycodestyle.py b/test/t/test_pycodestyle.py new file mode 100644 index 0000000..4b4f3a4 --- /dev/null +++ b/test/t/test_pycodestyle.py @@ -0,0 +1,15 @@ +import pytest + + +class TestPycodestyle: + @pytest.mark.complete("pycodestyle ") + def test_1(self, completion): + assert completion + + @pytest.mark.complete("pycodestyle -", require_cmd=True) + def test_2(self, completion): + assert completion + + @pytest.mark.complete("pycodestyle --doesnt-exist=") + def test_3(self, completion): + assert not completion diff --git a/test/t/test_pydoc.py b/test/t/test_pydoc.py new file mode 100644 index 0000000..7cf7eb5 --- /dev/null +++ b/test/t/test_pydoc.py @@ -0,0 +1,11 @@ +import pytest + + +class TestPydoc: + @pytest.mark.complete("pydoc r", require_cmd=True) + def test_1(self, completion): + assert completion + + @pytest.mark.complete("pydoc -", require_cmd=True) + def test_2(self, completion): + assert completion diff --git a/test/t/test_pydocstyle.py b/test/t/test_pydocstyle.py new file mode 100644 index 0000000..1f44320 --- /dev/null +++ b/test/t/test_pydocstyle.py @@ -0,0 +1,13 @@ +import pytest + + +class TestPydocstyle: + @pytest.mark.complete("pydocstyle ") + def test_1(self, completion): + assert completion + + @pytest.mark.complete( + "pydocstyle -", require_cmd=True, require_longopt=True + ) + def test_2(self, completion): + assert completion diff --git a/test/t/test_pyflakes.py b/test/t/test_pyflakes.py new file mode 100644 index 0000000..9670321 --- /dev/null +++ b/test/t/test_pyflakes.py @@ -0,0 +1,11 @@ +import pytest + + +class TestPyflakes: + @pytest.mark.complete("pyflakes ") + def test_1(self, completion): + assert completion + + @pytest.mark.complete("pyflakes -", require_cmd=True) + def test_2(self, completion): + assert completion diff --git a/test/t/test_pylint.py b/test/t/test_pylint.py new file mode 100644 index 0000000..43a4c43 --- /dev/null +++ b/test/t/test_pylint.py @@ -0,0 +1,11 @@ +import pytest + + +class TestPylint: + @pytest.mark.complete("pylint --v", require_cmd=True, require_longopt=True) + def test_1(self, completion): + assert completion + + @pytest.mark.complete("pylint --confidence=HIGH,") + def test_2(self, completion): + assert completion diff --git a/test/t/test_pylint_3.py b/test/t/test_pylint_3.py new file mode 100644 index 0000000..ee498c3 --- /dev/null +++ b/test/t/test_pylint_3.py @@ -0,0 +1,12 @@ +import pytest + + +@pytest.mark.bashcomp(cmd="pylint-3") +class TestPylint3: + @pytest.mark.complete("pylint-3 --v", require_cmd=True) + def test_1(self, completion): + assert completion + + @pytest.mark.complete("pylint-3 http.clien") + def test_2(self, completion): + assert completion diff --git a/test/t/test_pytest.py b/test/t/test_pytest.py new file mode 100644 index 0000000..e70c7a5 --- /dev/null +++ b/test/t/test_pytest.py @@ -0,0 +1,50 @@ +import inspect + +import pytest + + +class TestPytest: + @pytest.mark.complete("pytest ") + def test_1(self, completion): + assert completion + + @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 new file mode 100644 index 0000000..5308dcb --- /dev/null +++ b/test/t/test_python.py @@ -0,0 +1,39 @@ +import pytest + + +class TestPython: + @pytest.mark.complete("python ") + def test_1(self, completion): + assert completion + + @pytest.mark.complete("python -", require_cmd=True) + def test_2(self, completion): + assert len(completion) > 1 + + @pytest.mark.complete("python -c ") + def test_3(self, completion): + assert not completion + + @pytest.mark.complete("python shared/default/") + def test_4(self, completion): + assert completion == ["bar bar.d/", "foo.d/"] + + @pytest.mark.complete("python -c foo shared/default/") + def test_5(self, completion): + assert completion == ["bar", "bar bar.d/", "foo", "foo.d/"] + + @pytest.mark.complete("python -c foo -") + def test_6(self, completion): + assert not completion + + @pytest.mark.complete("python -m foo -") + def test_7(self, completion): + assert not completion + + @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 new file mode 100644 index 0000000..a4f6d96 --- /dev/null +++ b/test/t/test_python3.py @@ -0,0 +1,39 @@ +import pytest + + +class TestPython3: + @pytest.mark.complete("python3 ") + def test_1(self, completion): + assert completion + + @pytest.mark.complete("python3 -", require_cmd=True) + def test_2(self, completion): + assert len(completion) > 1 + + @pytest.mark.complete("python3 -c ") + def test_3(self, completion): + assert not completion + + @pytest.mark.complete("python3 shared/default/") + def test_4(self, completion): + assert completion == ["bar bar.d/", "foo.d/"] + + @pytest.mark.complete("python3 -c foo shared/default/") + def test_5(self, completion): + assert completion == ["bar", "bar bar.d/", "foo", "foo.d/"] + + @pytest.mark.complete("python3 -c foo -") + def test_6(self, completion): + assert not completion + + @pytest.mark.complete("python3 -m foo -") + def test_7(self, completion): + assert not completion + + @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_pyvenv.py b/test/t/test_pyvenv.py new file mode 100644 index 0000000..5e9152a --- /dev/null +++ b/test/t/test_pyvenv.py @@ -0,0 +1,7 @@ +import pytest + + +class TestPyvenv: + @pytest.mark.complete("pyvenv ") + def test_1(self, completion): + assert completion diff --git a/test/t/test_qemu.py b/test/t/test_qemu.py new file mode 100644 index 0000000..129c0b4 --- /dev/null +++ b/test/t/test_qemu.py @@ -0,0 +1,11 @@ +import pytest + + +class TestQemu: + @pytest.mark.complete("qemu ") + def test_1(self, completion): + assert completion + + @pytest.mark.complete("qemu -", require_cmd=True) + def test_2(self, completion): + assert completion diff --git a/test/t/test_qrunner.py b/test/t/test_qrunner.py new file mode 100644 index 0000000..4e4cdd8 --- /dev/null +++ b/test/t/test_qrunner.py @@ -0,0 +1,7 @@ +import pytest + + +class TestQrunner: + @pytest.mark.complete("qrunner -") + def test_1(self, completion): + assert completion diff --git a/test/t/test_querybts.py b/test/t/test_querybts.py new file mode 100644 index 0000000..9c81d13 --- /dev/null +++ b/test/t/test_querybts.py @@ -0,0 +1,7 @@ +import pytest + + +class TestQuerybts: + @pytest.mark.complete("querybts --", require_cmd=True) + def test_1(self, completion): + assert completion diff --git a/test/t/test_quota.py b/test/t/test_quota.py new file mode 100644 index 0000000..c744535 --- /dev/null +++ b/test/t/test_quota.py @@ -0,0 +1,11 @@ +import pytest + + +class TestQuota: + @pytest.mark.complete("quota ") + def test_1(self, completion): + assert completion + + @pytest.mark.complete("quota -", require_cmd=True) + def test_2(self, completion): + assert completion diff --git a/test/t/test_quotacheck.py b/test/t/test_quotacheck.py new file mode 100644 index 0000000..8140604 --- /dev/null +++ b/test/t/test_quotacheck.py @@ -0,0 +1,7 @@ +import pytest + + +class TestQuotacheck: + @pytest.mark.complete("quotacheck -", require_cmd=True) + def test_1(self, completion): + assert completion diff --git a/test/t/test_quotaon.py b/test/t/test_quotaon.py new file mode 100644 index 0000000..c4386c6 --- /dev/null +++ b/test/t/test_quotaon.py @@ -0,0 +1,7 @@ +import pytest + + +class TestQuotaon: + @pytest.mark.complete("quotaon -", require_cmd=True) + def test_1(self, completion): + assert completion diff --git a/test/t/test_radvdump.py b/test/t/test_radvdump.py new file mode 100644 index 0000000..a8a16d9 --- /dev/null +++ b/test/t/test_radvdump.py @@ -0,0 +1,11 @@ +import pytest + + +class TestRadvdump: + @pytest.mark.complete("radvdump ", require_cmd=True) + def test_1(self, completion): + assert completion + + @pytest.mark.complete("radvdump -", require_cmd=True) + def test_2(self, completion): + assert completion diff --git a/test/t/test_rcs.py b/test/t/test_rcs.py new file mode 100644 index 0000000..985bb44 --- /dev/null +++ b/test/t/test_rcs.py @@ -0,0 +1,7 @@ +import pytest + + +class TestRcs: + @pytest.mark.complete("rcs ") + def test_1(self, completion): + assert completion diff --git a/test/t/test_rcsdiff.py b/test/t/test_rcsdiff.py new file mode 100644 index 0000000..d54934c --- /dev/null +++ b/test/t/test_rcsdiff.py @@ -0,0 +1,7 @@ +import pytest + + +class TestRcsdiff: + @pytest.mark.complete("rcsdiff ") + def test_1(self, completion): + assert completion diff --git a/test/t/test_rdesktop.py b/test/t/test_rdesktop.py new file mode 100644 index 0000000..f20ca51 --- /dev/null +++ b/test/t/test_rdesktop.py @@ -0,0 +1,7 @@ +import pytest + + +class TestRdesktop: + @pytest.mark.complete("rdesktop -", require_cmd=True) + def test_1(self, completion): + assert completion diff --git a/test/t/test_rdict.py b/test/t/test_rdict.py new file mode 100644 index 0000000..da6fb1b --- /dev/null +++ b/test/t/test_rdict.py @@ -0,0 +1,7 @@ +import pytest + + +class TestRdict: + @pytest.mark.complete("rdict --", require_cmd=True) + def test_1(self, completion): + assert completion diff --git a/test/t/test_readelf.py b/test/t/test_readelf.py new file mode 100644 index 0000000..07ce347 --- /dev/null +++ b/test/t/test_readelf.py @@ -0,0 +1,7 @@ +import pytest + + +class TestReadelf: + @pytest.mark.complete("readelf --", require_cmd=True) + def test_1(self, completion): + assert completion diff --git a/test/t/test_readonly.py b/test/t/test_readonly.py new file mode 100644 index 0000000..0ac310c --- /dev/null +++ b/test/t/test_readonly.py @@ -0,0 +1,7 @@ +import pytest + + +class TestReadonly: + @pytest.mark.complete("readonly BASH_ARG") + def test_1(self, completion): + assert completion diff --git a/test/t/test_remove_members.py b/test/t/test_remove_members.py new file mode 100644 index 0000000..a3b0afd --- /dev/null +++ b/test/t/test_remove_members.py @@ -0,0 +1,7 @@ +import pytest + + +class TestRemoveMembers: + @pytest.mark.complete("remove_members --") + def test_1(self, completion): + assert completion diff --git a/test/t/test_removepkg.py b/test/t/test_removepkg.py new file mode 100644 index 0000000..9fd7a9d --- /dev/null +++ b/test/t/test_removepkg.py @@ -0,0 +1,15 @@ +import os + +import pytest + + +@pytest.mark.bashcomp(ignore_env=r"^\+ROOT=") +class TestRemovepkg: + @pytest.mark.complete("removepkg -") + def test_1(self, completion): + assert completion == "-copy -keep -preserve -warn".split() + + @pytest.mark.complete("removepkg ", env=dict(ROOT="./slackware")) + def test_2(self, completion): + files = sorted(x for x in os.listdir("slackware/var/log/packages")) + assert completion == files diff --git a/test/t/test_renice.py b/test/t/test_renice.py new file mode 100644 index 0000000..20d59a3 --- /dev/null +++ b/test/t/test_renice.py @@ -0,0 +1,11 @@ +import pytest + + +class TestRenice: + @pytest.mark.complete("renice 1") + def test_1(self, completion): + assert completion + + @pytest.mark.complete("renice -g ") + def test_2(self, completion): + assert completion diff --git a/test/t/test_repomanage.py b/test/t/test_repomanage.py new file mode 100644 index 0000000..bdaba15 --- /dev/null +++ b/test/t/test_repomanage.py @@ -0,0 +1,11 @@ +import pytest + + +class TestRepomanage: + @pytest.mark.complete("repomanage ") + def test_1(self, completion): + assert completion + + @pytest.mark.complete("repomanage -", require_cmd=True) + def test_2(self, completion): + assert completion diff --git a/test/t/test_reportbug.py b/test/t/test_reportbug.py new file mode 100644 index 0000000..2c57b56 --- /dev/null +++ b/test/t/test_reportbug.py @@ -0,0 +1,7 @@ +import pytest + + +class TestReportbug: + @pytest.mark.complete("reportbug --m", require_cmd=True) + def test_1(self, completion): + assert completion diff --git a/test/t/test_reptyr.py b/test/t/test_reptyr.py new file mode 100644 index 0000000..7c27cb5 --- /dev/null +++ b/test/t/test_reptyr.py @@ -0,0 +1,11 @@ +import pytest + + +class TestReptyr: + @pytest.mark.complete("reptyr ") + def test_1(self, completion): + assert completion + + @pytest.mark.complete("reptyr -", require_cmd=True) + def test_2(self, completion): + assert completion diff --git a/test/t/test_resolvconf.py b/test/t/test_resolvconf.py new file mode 100644 index 0000000..fdcf584 --- /dev/null +++ b/test/t/test_resolvconf.py @@ -0,0 +1,7 @@ +import pytest + + +class TestResolvconf: + @pytest.mark.complete("resolvconf -") + def test_1(self, completion): + assert completion diff --git a/test/t/test_rfcomm.py b/test/t/test_rfcomm.py new file mode 100644 index 0000000..c30d23b --- /dev/null +++ b/test/t/test_rfcomm.py @@ -0,0 +1,7 @@ +import pytest + + +class TestRfcomm: + @pytest.mark.complete("rfcomm ") + def test_1(self, completion): + assert completion diff --git a/test/t/test_rfkill.py b/test/t/test_rfkill.py new file mode 100644 index 0000000..f8248ff --- /dev/null +++ b/test/t/test_rfkill.py @@ -0,0 +1,11 @@ +import pytest + + +class TestRfkill: + @pytest.mark.complete("rfkill ") + def test_1(self, completion): + assert completion + + @pytest.mark.complete("rfkill -") + def test_2(self, completion): + assert completion diff --git a/test/t/test_ri.py b/test/t/test_ri.py new file mode 100644 index 0000000..420b6cb --- /dev/null +++ b/test/t/test_ri.py @@ -0,0 +1,16 @@ +import pytest + + +@pytest.mark.bashcomp(pre_cmds=("export RI='-d ri'",)) +class TestRi: + @pytest.mark.complete("ri -", require_cmd=True) + def test_1(self, completion): + assert completion + + @pytest.mark.complete("ri --dump=ri/") + def test_2(self, completion): + assert completion == "BashCompletion/ cache.ri".split() + + @pytest.mark.complete("ri BashCompletio", require_cmd=True) + def test_3(self, completion): + assert completion == "n" diff --git a/test/t/test_rlog.py b/test/t/test_rlog.py new file mode 100644 index 0000000..87a4da1 --- /dev/null +++ b/test/t/test_rlog.py @@ -0,0 +1,7 @@ +import pytest + + +class TestRlog: + @pytest.mark.complete("rlog ") + def test_1(self, completion): + assert completion diff --git a/test/t/test_rm.py b/test/t/test_rm.py new file mode 100644 index 0000000..6fda5a1 --- /dev/null +++ b/test/t/test_rm.py @@ -0,0 +1,11 @@ +import pytest + + +class TestRm: + @pytest.mark.complete("rm ") + def test_1(self, completion): + assert completion + + @pytest.mark.complete("rm -", require_longopt=True) + def test_options(self, completion): + assert completion diff --git a/test/t/test_rmdir.py b/test/t/test_rmdir.py new file mode 100644 index 0000000..b981677 --- /dev/null +++ b/test/t/test_rmdir.py @@ -0,0 +1,16 @@ +import pytest + + +class TestRmdir: + @pytest.mark.complete("rmdir ") + def test_1(self, completion): + assert completion + + @pytest.mark.complete("/bin/rmdir shared/default/") + def test_2(self, completion): + """Should complete dirs only, also when invoked using full path.""" + assert completion == ["bar bar.d/", "foo.d/"] + + @pytest.mark.complete("rmdir -", require_cmd=True) + def test_options(self, completion): + assert completion diff --git a/test/t/test_rmlist.py b/test/t/test_rmlist.py new file mode 100644 index 0000000..3a6c6ec --- /dev/null +++ b/test/t/test_rmlist.py @@ -0,0 +1,7 @@ +import pytest + + +class TestRmlist: + @pytest.mark.complete("rmlist -") + def test_1(self, completion): + assert completion diff --git a/test/t/test_rmmod.py b/test/t/test_rmmod.py new file mode 100644 index 0000000..5528705 --- /dev/null +++ b/test/t/test_rmmod.py @@ -0,0 +1,7 @@ +import pytest + + +class TestRmmod: + @pytest.mark.complete("rmmod -", require_cmd=True) + def test_1(self, completion): + assert completion diff --git a/test/t/test_route.py b/test/t/test_route.py new file mode 100644 index 0000000..741ef58 --- /dev/null +++ b/test/t/test_route.py @@ -0,0 +1,7 @@ +import pytest + + +class TestRoute: + @pytest.mark.complete("route ") + def test_1(self, completion): + assert completion diff --git a/test/t/test_rpcdebug.py b/test/t/test_rpcdebug.py new file mode 100644 index 0000000..e92bdee --- /dev/null +++ b/test/t/test_rpcdebug.py @@ -0,0 +1,7 @@ +import pytest + + +class TestRpcdebug: + @pytest.mark.complete("rpcdebug -") + def test_1(self, completion): + assert completion diff --git a/test/t/test_rpm.py b/test/t/test_rpm.py new file mode 100644 index 0000000..e6f7198 --- /dev/null +++ b/test/t/test_rpm.py @@ -0,0 +1,15 @@ +import pytest + + +class TestRpm: + @pytest.mark.complete("rpm ") + def test_1(self, completion): + assert completion + + @pytest.mark.complete("rpm -q ", skipif='test -z "$(rpm -qa 2>/dev/null)"') + def test_2(self, completion): + assert completion + + @pytest.mark.complete("rpm -", require_cmd=True) + def test_3(self, completion): + assert completion diff --git a/test/t/test_rpm2tgz.py b/test/t/test_rpm2tgz.py new file mode 100644 index 0000000..ad6e8bc --- /dev/null +++ b/test/t/test_rpm2tgz.py @@ -0,0 +1,26 @@ +import os + +import pytest + + +class TestRpm2tgz: + @pytest.mark.complete("rpm2tgz -") + def test_1(self, completion): + assert completion + + @pytest.mark.complete("rpm2tgz ", cwd="slackware/home") + def test_2(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 x.endswith(".rpm") + ] + ) + assert completion == expected diff --git a/test/t/test_rpmbuild.py b/test/t/test_rpmbuild.py new file mode 100644 index 0000000..06c8087 --- /dev/null +++ b/test/t/test_rpmbuild.py @@ -0,0 +1,7 @@ +import pytest + + +class TestRpmbuild: + @pytest.mark.complete("rpmbuild -", require_cmd=True) + def test_1(self, completion): + assert completion diff --git a/test/t/test_rrdtool.py b/test/t/test_rrdtool.py new file mode 100644 index 0000000..9da8310 --- /dev/null +++ b/test/t/test_rrdtool.py @@ -0,0 +1,7 @@ +import pytest + + +class TestRrdtool: + @pytest.mark.complete("rrdtool ") + def test_1(self, completion): + assert completion diff --git a/test/t/test_rsync.py b/test/t/test_rsync.py new file mode 100644 index 0000000..d54ce6f --- /dev/null +++ b/test/t/test_rsync.py @@ -0,0 +1,16 @@ +import pytest + + +@pytest.mark.bashcomp(ignore_env=r"^[+-]_scp_path_esc=") +class TestRsync: + @pytest.mark.complete("rsync ") + def test_1(self, completion): + assert completion + + @pytest.mark.complete("rsync --rsh ") + def test_2(self, completion): + assert completion == "rsh ssh".split() + + @pytest.mark.complete("rsync --rsh=") + def test_3(self, completion): + assert completion == "rsh ssh".split() diff --git a/test/t/test_rtcwake.py b/test/t/test_rtcwake.py new file mode 100644 index 0000000..19d1dfe --- /dev/null +++ b/test/t/test_rtcwake.py @@ -0,0 +1,11 @@ +import pytest + + +class TestRtcwake: + @pytest.mark.complete("rtcwake ", require_cmd=True) + def test_1(self, completion): + assert completion + + @pytest.mark.complete("rtcwake -", require_cmd=True) + def test_2(self, completion): + assert completion diff --git a/test/t/test_runuser.py b/test/t/test_runuser.py new file mode 100644 index 0000000..01a6d88 --- /dev/null +++ b/test/t/test_runuser.py @@ -0,0 +1,7 @@ +import pytest + + +class TestRunuser: + @pytest.mark.complete("runuser ") + def test_1(self, completion): + assert completion diff --git a/test/t/test_sbcl.py b/test/t/test_sbcl.py new file mode 100644 index 0000000..f05741a --- /dev/null +++ b/test/t/test_sbcl.py @@ -0,0 +1,7 @@ +import pytest + + +class TestSbcl: + @pytest.mark.complete("sbcl shared/default/") + def test_1(self, completion): + 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 new file mode 100644 index 0000000..c396539 --- /dev/null +++ b/test/t/test_sbcl_mt.py @@ -0,0 +1,8 @@ +import pytest + + +@pytest.mark.bashcomp(cmd="sbcl-mt") +class TestSbclMt: + @pytest.mark.complete("sbcl-mt shared/default/") + def test_1(self, completion): + assert completion == ["bar", "bar bar.d/", "foo", "foo.d/"] diff --git a/test/t/test_sbopkg.py b/test/t/test_sbopkg.py new file mode 100644 index 0000000..44f1521 --- /dev/null +++ b/test/t/test_sbopkg.py @@ -0,0 +1,7 @@ +import pytest + + +class TestSbopkg: + @pytest.mark.complete("sbopkg -", require_cmd=True) + def test_1(self, completion): + assert completion diff --git a/test/t/test_scp.py b/test/t/test_scp.py new file mode 100644 index 0000000..66b8da2 --- /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 new file mode 100644 index 0000000..3e98837 --- /dev/null +++ b/test/t/test_screen.py @@ -0,0 +1,48 @@ +import pytest + + +class TestScreen: + @pytest.mark.complete("screen -", require_cmd=True) + def test_1(self, completion): + assert completion + + @pytest.mark.complete("screen -c shared/default/") + def test_2(self, completion): + assert completion == ["bar", "bar bar.d/", "foo", "foo.d/"] + + @pytest.mark.complete("screen cat ") + def test_3(self, completion): + assert completion + + # Assume at least vt100 and friends are there + @pytest.mark.complete("screen -T vt") + def test_4(self, completion): + assert completion + + @pytest.mark.complete("screen -T foo ca") + def test_5(self, completion): + assert completion == "t" or "cat" in completion + + @pytest.mark.complete("screen //") + def test_telnet(self, completion): + assert completion == "telnet" + + @pytest.mark.complete("screen cat //") + def test_not_telnet(self, completion): + assert completion != "telnet" + + @pytest.mark.complete("screen //telnet ", env=dict(HOME="$PWD/shared")) + def test_telnet_first_arg(self, completion): + assert "bash-completion-canary-host.local" in completion + + @pytest.mark.complete("screen //telnet foo ", env=dict(HOME="$PWD/shared")) + def test_telnet_other_args(self, completion): + assert not completion + + @pytest.mark.complete("screen /dev/ttyUSB0 ") + def test_serial_2nd_arg(self, completion): + assert "19200" in completion + + @pytest.mark.complete("screen /dev/ttyUSB0 9600 ") + def test_serial_3rdplus_arg(self, completion): + assert not completion diff --git a/test/t/test_scrub.py b/test/t/test_scrub.py new file mode 100644 index 0000000..5853ad2 --- /dev/null +++ b/test/t/test_scrub.py @@ -0,0 +1,19 @@ +import pytest + + +class TestScrub: + @pytest.mark.complete("scrub ") + def test_1(self, completion): + assert completion + + @pytest.mark.complete("scrub -", require_cmd=True) + def test_2(self, completion): + assert completion + + # Not all scrub versions list available patterns in --help output + @pytest.mark.complete( + "scrub -p ", + xfail="! (scrub --help 2>&1 || :) | command grep -q ^Available", + ) + def test_3(self, completion): + assert completion diff --git a/test/t/test_sdptool.py b/test/t/test_sdptool.py new file mode 100644 index 0000000..095d90e --- /dev/null +++ b/test/t/test_sdptool.py @@ -0,0 +1,7 @@ +import pytest + + +class TestSdptool: + @pytest.mark.complete("sdptool ") + def test_1(self, completion): + assert completion diff --git a/test/t/test_secret_tool.py b/test/t/test_secret_tool.py new file mode 100644 index 0000000..cbfc0cb --- /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_sed.py b/test/t/test_sed.py new file mode 100644 index 0000000..53079c9 --- /dev/null +++ b/test/t/test_sed.py @@ -0,0 +1,7 @@ +import pytest + + +class TestSed: + @pytest.mark.complete("sed --", require_longopt=True) + def test_1(self, completion): + assert completion diff --git a/test/t/test_seq.py b/test/t/test_seq.py new file mode 100644 index 0000000..b672238 --- /dev/null +++ b/test/t/test_seq.py @@ -0,0 +1,7 @@ +import pytest + + +class TestSeq: + @pytest.mark.complete("seq --", require_longopt=True) + def test_1(self, completion): + assert completion diff --git a/test/t/test_service.py b/test/t/test_service.py new file mode 100644 index 0000000..7ce4312 --- /dev/null +++ b/test/t/test_service.py @@ -0,0 +1,7 @@ +import pytest + + +class TestService: + @pytest.mark.complete("service ") + def test_1(self, completion): + assert completion diff --git a/test/t/test_set.py b/test/t/test_set.py new file mode 100644 index 0000000..08c1671 --- /dev/null +++ b/test/t/test_set.py @@ -0,0 +1,7 @@ +import pytest + + +class TestSet: + @pytest.mark.complete("set no") + def test_1(self, completion): + assert completion diff --git a/test/t/test_setquota.py b/test/t/test_setquota.py new file mode 100644 index 0000000..76fd7b9 --- /dev/null +++ b/test/t/test_setquota.py @@ -0,0 +1,11 @@ +import pytest + + +class TestSetquota: + @pytest.mark.complete("setquota ") + def test_1(self, completion): + assert completion + + @pytest.mark.complete("setquota -", require_cmd=True) + def test_2(self, completion): + assert completion diff --git a/test/t/test_sftp.py b/test/t/test_sftp.py new file mode 100644 index 0000000..a421a44 --- /dev/null +++ b/test/t/test_sftp.py @@ -0,0 +1,46 @@ +from itertools import chain + +import pytest + + +class TestSftp: + @pytest.mark.complete("sftp -Fsp", cwd="sftp") + def test_1(self, completion): + 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_sh.py b/test/t/test_sh.py new file mode 100644 index 0000000..f49a168 --- /dev/null +++ b/test/t/test_sh.py @@ -0,0 +1,19 @@ +import pytest + + +class TestSh: + @pytest.mark.complete("sh -") + def test_1(self, completion): + assert completion + + @pytest.mark.complete("sh +") + def test_2(self, completion): + assert completion + + @pytest.mark.complete("sh -o ") + def test_3(self, completion): + assert completion + + @pytest.mark.complete("sh -c ") + def test_4(self, completion): + assert not completion diff --git a/test/t/test_sha1sum.py b/test/t/test_sha1sum.py new file mode 100644 index 0000000..e4296d4 --- /dev/null +++ b/test/t/test_sha1sum.py @@ -0,0 +1,7 @@ +import pytest + + +class TestSha1sum: + @pytest.mark.complete("sha1sum --", require_longopt=True) + def test_1(self, completion): + assert completion diff --git a/test/t/test_shar.py b/test/t/test_shar.py new file mode 100644 index 0000000..5c23004 --- /dev/null +++ b/test/t/test_shar.py @@ -0,0 +1,7 @@ +import pytest + + +class TestShar: + @pytest.mark.complete("shar --", require_cmd=True) + def test_1(self, completion): + assert completion diff --git a/test/t/test_shellcheck.py b/test/t/test_shellcheck.py new file mode 100644 index 0000000..703128f --- /dev/null +++ b/test/t/test_shellcheck.py @@ -0,0 +1,19 @@ +import pytest + + +class TestShellcheck: + @pytest.mark.complete("shellcheck ") + def test_1(self, completion): + assert completion + + @pytest.mark.complete("shellcheck -", require_cmd=True) + def test_2(self, completion): + assert completion + + @pytest.mark.complete("shellcheck --format=", require_cmd=True) + def test_3(self, completion): + assert completion + + @pytest.mark.complete("shellcheck -s ", require_cmd=True) + def test_4(self, completion): + assert "bash" in completion diff --git a/test/t/test_sitecopy.py b/test/t/test_sitecopy.py new file mode 100644 index 0000000..afdeeaa --- /dev/null +++ b/test/t/test_sitecopy.py @@ -0,0 +1,7 @@ +import pytest + + +class TestSitecopy: + @pytest.mark.complete("sitecopy --", require_cmd=True) + def test_1(self, completion): + assert completion diff --git a/test/t/test_slackpkg.py b/test/t/test_slackpkg.py new file mode 100644 index 0000000..3997bb0 --- /dev/null +++ b/test/t/test_slackpkg.py @@ -0,0 +1,7 @@ +import pytest + + +class TestSlackpkg: + @pytest.mark.complete("slackpkg -") + def test_1(self, completion): + assert completion diff --git a/test/t/test_slapt_get.py b/test/t/test_slapt_get.py new file mode 100644 index 0000000..9244971 --- /dev/null +++ b/test/t/test_slapt_get.py @@ -0,0 +1,44 @@ +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 + + @pytest.mark.complete("slapt-get --up", require_cmd=True) + def test_2(self, completion): + assert completion == "--update --upgrade".split() + + @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 new file mode 100644 index 0000000..b55b722 --- /dev/null +++ b/test/t/test_slapt_src.py @@ -0,0 +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 == "ild" or "--build" in completion + + @pytest.mark.complete("slapt-src --ins", require_cmd=True) + def test_3(self, completion): + 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_smartctl.py b/test/t/test_smartctl.py new file mode 100644 index 0000000..26d0147 --- /dev/null +++ b/test/t/test_smartctl.py @@ -0,0 +1,7 @@ +import pytest + + +class TestSmartctl: + @pytest.mark.complete("smartctl --", require_cmd=True) + def test_1(self, completion): + assert completion diff --git a/test/t/test_smbcacls.py b/test/t/test_smbcacls.py new file mode 100644 index 0000000..0fe84e3 --- /dev/null +++ b/test/t/test_smbcacls.py @@ -0,0 +1,7 @@ +import pytest + + +class TestSmbcacls: + @pytest.mark.complete("smbcacls -", require_cmd=True) + def test_1(self, completion): + assert completion diff --git a/test/t/test_smbclient.py b/test/t/test_smbclient.py new file mode 100644 index 0000000..250ab87 --- /dev/null +++ b/test/t/test_smbclient.py @@ -0,0 +1,7 @@ +import pytest + + +class TestSmbclient: + @pytest.mark.complete("smbclient -", require_cmd=True) + def test_1(self, completion): + assert completion diff --git a/test/t/test_smbcquotas.py b/test/t/test_smbcquotas.py new file mode 100644 index 0000000..16157ed --- /dev/null +++ b/test/t/test_smbcquotas.py @@ -0,0 +1,7 @@ +import pytest + + +class TestSmbcquotas: + @pytest.mark.complete("smbcquotas -", require_cmd=True) + def test_1(self, completion): + assert completion diff --git a/test/t/test_smbget.py b/test/t/test_smbget.py new file mode 100644 index 0000000..a6df717 --- /dev/null +++ b/test/t/test_smbget.py @@ -0,0 +1,7 @@ +import pytest + + +class TestSmbget: + @pytest.mark.complete("smbget -", require_cmd=True) + def test_1(self, completion): + assert completion diff --git a/test/t/test_smbpasswd.py b/test/t/test_smbpasswd.py new file mode 100644 index 0000000..9fae8f2 --- /dev/null +++ b/test/t/test_smbpasswd.py @@ -0,0 +1,7 @@ +import pytest + + +class TestSmbpasswd: + @pytest.mark.complete("smbpasswd -", require_cmd=True) + def test_1(self, completion): + assert completion diff --git a/test/t/test_smbtar.py b/test/t/test_smbtar.py new file mode 100644 index 0000000..2a0e01e --- /dev/null +++ b/test/t/test_smbtar.py @@ -0,0 +1,7 @@ +import pytest + + +class TestSmbtar: + @pytest.mark.complete("smbtar -", require_cmd=True) + def test_1(self, completion): + assert completion diff --git a/test/t/test_smbtree.py b/test/t/test_smbtree.py new file mode 100644 index 0000000..2cb6767 --- /dev/null +++ b/test/t/test_smbtree.py @@ -0,0 +1,7 @@ +import pytest + + +class TestSmbtree: + @pytest.mark.complete("smbtree -", require_cmd=True) + def test_1(self, completion): + assert completion diff --git a/test/t/test_snownews.py b/test/t/test_snownews.py new file mode 100644 index 0000000..a05df98 --- /dev/null +++ b/test/t/test_snownews.py @@ -0,0 +1,7 @@ +import pytest + + +class TestSnownews: + @pytest.mark.complete("snownews --", require_cmd=True) + def test_1(self, completion): + assert completion diff --git a/test/t/test_sort.py b/test/t/test_sort.py new file mode 100644 index 0000000..d1a4e36 --- /dev/null +++ b/test/t/test_sort.py @@ -0,0 +1,7 @@ +import pytest + + +class TestSort: + @pytest.mark.complete("sort --", require_longopt=True) + def test_1(self, completion): + assert completion diff --git a/test/t/test_split.py b/test/t/test_split.py new file mode 100644 index 0000000..8c3f1f4 --- /dev/null +++ b/test/t/test_split.py @@ -0,0 +1,7 @@ +import pytest + + +class TestSplit: + @pytest.mark.complete("split --", require_longopt=True) + def test_1(self, completion): + assert completion diff --git a/test/t/test_spovray.py b/test/t/test_spovray.py new file mode 100644 index 0000000..9033f83 --- /dev/null +++ b/test/t/test_spovray.py @@ -0,0 +1,7 @@ +import pytest + + +class TestSpovray: + @pytest.mark.complete("spovray ") + def test_1(self, completion): + assert completion diff --git a/test/t/test_sqlite3.py b/test/t/test_sqlite3.py new file mode 100644 index 0000000..69a1316 --- /dev/null +++ b/test/t/test_sqlite3.py @@ -0,0 +1,15 @@ +import pytest + + +class TestSqlite3: + @pytest.mark.complete("sqlite3 ") + def test_1(self, completion): + assert completion + + @pytest.mark.complete("sqlite3 -", require_cmd=True) + def test_2(self, completion): + assert completion + + @pytest.mark.complete("sqlite3 -scratch foo ", require_cmd=True) + def test_3(self, completion): + assert not completion diff --git a/test/t/test_ss.py b/test/t/test_ss.py new file mode 100644 index 0000000..716c0fd --- /dev/null +++ b/test/t/test_ss.py @@ -0,0 +1,15 @@ +import pytest + + +class TestSs: + @pytest.mark.complete("ss -", require_cmd=True) + def test_1(self, completion): + assert completion + + @pytest.mark.complete("ss -A ", require_cmd=True) + def test_2(self, completion): + assert completion + + @pytest.mark.complete("ss -A foo,", require_cmd=True) + def test_3(self, completion): + assert completion diff --git a/test/t/test_ssh.py b/test/t/test_ssh.py new file mode 100644 index 0000000..8e95819 --- /dev/null +++ b/test/t/test_ssh.py @@ -0,0 +1,60 @@ +import pytest + +from conftest import assert_complete, partialize + + +class TestSsh: + @pytest.mark.complete("ssh -Fsp", cwd="ssh") + def test_1(self, completion): + assert completion == r"aced\ \ conf" + + @pytest.mark.complete("ssh -F config ls", cwd="ssh") + def test_2(self, completion): + """Should complete both commands and hostname.""" + assert all(x in completion for x in "ls ls_known_host".split()) + + @pytest.mark.complete("ssh bash", cwd="ssh") + def test_3(self, completion): + """ + First arg should not complete with commands. + + Assumes there's no "bash" known host. + """ + assert "bash" not in completion + + @pytest.mark.complete("ssh -vo AddressFamily=") + def test_4(self, completion): + assert completion + + @pytest.mark.xfail # TODO our test facilities don't support case change? + @pytest.mark.complete("ssh -vo userknownhostsf") + def test_5(self, completion): + assert "UserKnownHostsFile=" in completion + + @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_add.py b/test/t/test_ssh_add.py new file mode 100644 index 0000000..7e49372 --- /dev/null +++ b/test/t/test_ssh_add.py @@ -0,0 +1,17 @@ +import pytest + + +@pytest.mark.bashcomp(cmd="ssh-add") +class TestSshAdd: + @pytest.mark.complete("ssh-add ") + def test_1(self, completion): + assert completion + + @pytest.mark.complete( + "ssh-add -", + require_cmd=True, + xfail="ssh-add --help 2>&1 | " + "command grep -qiF 'Could not open a connection'", + ) + def test_2(self, completion): + assert completion diff --git a/test/t/test_ssh_copy_id.py b/test/t/test_ssh_copy_id.py new file mode 100644 index 0000000..e38e901 --- /dev/null +++ b/test/t/test_ssh_copy_id.py @@ -0,0 +1,16 @@ +import pytest + + +@pytest.mark.bashcomp( + cmd="ssh-copy-id", + pre_cmds=( + # Some old versions of ssh-copy-id won't output even usage if no + # identities are found. Try to make sure there is at least one. + "HOME=$PWD/ssh-copy-id", + ), + ignore_env=r"^[+-]_scp_path_esc=", +) +class TestSshCopyId: + @pytest.mark.complete("ssh-copy-id -", require_cmd=True) + def test_1(self, completion): + assert completion diff --git a/test/t/test_ssh_keygen.py b/test/t/test_ssh_keygen.py new file mode 100644 index 0000000..b773ab4 --- /dev/null +++ b/test/t/test_ssh_keygen.py @@ -0,0 +1,59 @@ +import pytest + + +@pytest.mark.bashcomp(cmd="ssh-keygen") +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_sshfs.py b/test/t/test_sshfs.py new file mode 100644 index 0000000..44daed3 --- /dev/null +++ b/test/t/test_sshfs.py @@ -0,0 +1,8 @@ +import pytest + + +@pytest.mark.bashcomp(ignore_env=r"^[+-]_scp_path_esc=") +class TestSshfs: + @pytest.mark.complete("sshfs ./") + def test_1(self, completion): + assert completion diff --git a/test/t/test_sshmitm.py b/test/t/test_sshmitm.py new file mode 100644 index 0000000..671fcf5 --- /dev/null +++ b/test/t/test_sshmitm.py @@ -0,0 +1,7 @@ +import pytest + + +class TestSshmitm: + @pytest.mark.complete("sshmitm -", require_cmd=True) + def test_1(self, completion): + assert completion diff --git a/test/t/test_sshow.py b/test/t/test_sshow.py new file mode 100644 index 0000000..563bc6b --- /dev/null +++ b/test/t/test_sshow.py @@ -0,0 +1,7 @@ +import pytest + + +class TestSshow: + @pytest.mark.complete("sshow -", require_cmd=True) + def test_1(self, completion): + assert completion diff --git a/test/t/test_strace.py b/test/t/test_strace.py new file mode 100644 index 0000000..e0d6aed --- /dev/null +++ b/test/t/test_strace.py @@ -0,0 +1,7 @@ +import pytest + + +class TestStrace: + @pytest.mark.complete("strace -", require_cmd=True) + def test_1(self, completion): + assert completion diff --git a/test/t/test_stream.py b/test/t/test_stream.py new file mode 100644 index 0000000..a46e901 --- /dev/null +++ b/test/t/test_stream.py @@ -0,0 +1,7 @@ +import pytest + + +class TestStream: + @pytest.mark.complete("stream ") + def test_1(self, completion): + assert completion diff --git a/test/t/test_strings.py b/test/t/test_strings.py new file mode 100644 index 0000000..6b5d012 --- /dev/null +++ b/test/t/test_strings.py @@ -0,0 +1,11 @@ +import pytest + + +class TestStrings: + @pytest.mark.complete("strings ") + def test_1(self, completion): + assert completion + + @pytest.mark.complete("strings -", require_cmd=True) + def test_2(self, completion): + assert completion diff --git a/test/t/test_strip.py b/test/t/test_strip.py new file mode 100644 index 0000000..105012f --- /dev/null +++ b/test/t/test_strip.py @@ -0,0 +1,7 @@ +import pytest + + +class TestStrip: + @pytest.mark.complete("strip --", require_cmd=True) + def test_1(self, completion): + assert completion diff --git a/test/t/test_su.py b/test/t/test_su.py new file mode 100644 index 0000000..9aa064d --- /dev/null +++ b/test/t/test_su.py @@ -0,0 +1,11 @@ +import pytest + + +class TestSu: + @pytest.mark.complete("su ") + def test_1(self, completion): + assert completion + + @pytest.mark.complete("su -", require_cmd=True) + def test_2(self, completion): + assert completion diff --git a/test/t/test_sudo.py b/test/t/test_sudo.py new file mode 100644 index 0000000..a349466 --- /dev/null +++ b/test/t/test_sudo.py @@ -0,0 +1,83 @@ +import pytest + +from conftest import assert_complete + + +class TestSudo: + @pytest.mark.complete("sudo -", require_cmd=True) + def test_1(self, completion): + assert completion + + @pytest.mark.complete("sudo cd fo", cwd="shared/default") + def test_2(self, completion): + assert completion == "o.d/" + assert not completion.endswith(" ") + + @pytest.mark.complete("sudo sh share") + def test_3(self, completion): + assert completion == "d/" + assert not completion.endswith(" ") + + @pytest.mark.complete("sudo mount /dev/sda1 def", cwd="shared") + def test_4(self, completion): + 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/".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[len(part) :] + assert completion.endswith(" ") + + def test_7(self, bash, part_full_user, part_full_group): + _, user = part_full_user + partgroup, fullgroup = part_full_group + completion = assert_complete( + bash, "sudo chown %s:%s" % (user, partgroup) + ) + 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 == full[len(part) :] + assert completion.endswith(" ") + + @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\ :", + ], + ) + 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.""" + _, user = part_full_user + partgroup, _ = part_full_group + for x in range(2, 5): + completion = assert_complete( + bash, "sudo chown %s%s:%s" % (user, x * "\\", partgroup) + ) + assert not completion + + def test_11(self, bash, part_full_group): + """Test graceful fail on colon in user/group name.""" + part, _ = part_full_group + completion = assert_complete(bash, "sudo chown foo:bar:%s" % part) + assert not completion diff --git a/test/t/test_sum.py b/test/t/test_sum.py new file mode 100644 index 0000000..bfb2cf4 --- /dev/null +++ b/test/t/test_sum.py @@ -0,0 +1,11 @@ +import pytest + + +class TestSum: + @pytest.mark.complete("sum ") + def test_1(self, completion): + assert completion + + @pytest.mark.complete("sum -", require_longopt=True) + def test_options(self, completion): + assert completion diff --git a/test/t/test_svcadm.py b/test/t/test_svcadm.py new file mode 100644 index 0000000..76d86a4 --- /dev/null +++ b/test/t/test_svcadm.py @@ -0,0 +1,7 @@ +import pytest + + +class TestSvcadm: + @pytest.mark.complete("svcadm ") + def test_1(self, completion): + assert completion diff --git a/test/t/test_svk.py b/test/t/test_svk.py new file mode 100644 index 0000000..8014bb0 --- /dev/null +++ b/test/t/test_svk.py @@ -0,0 +1,7 @@ +import pytest + + +class TestSvk: + @pytest.mark.complete("svk ") + def test_1(self, completion): + assert completion diff --git a/test/t/test_svn.py b/test/t/test_svn.py new file mode 100644 index 0000000..d8bbee7 --- /dev/null +++ b/test/t/test_svn.py @@ -0,0 +1,7 @@ +import pytest + + +class TestSvn: + @pytest.mark.complete("svn ") + def test_1(self, completion): + assert completion diff --git a/test/t/test_svnadmin.py b/test/t/test_svnadmin.py new file mode 100644 index 0000000..2dc7c6c --- /dev/null +++ b/test/t/test_svnadmin.py @@ -0,0 +1,7 @@ +import pytest + + +class TestSvnadmin: + @pytest.mark.complete("svnadmin ") + def test_1(self, completion): + assert completion diff --git a/test/t/test_svnlook.py b/test/t/test_svnlook.py new file mode 100644 index 0000000..26761b0 --- /dev/null +++ b/test/t/test_svnlook.py @@ -0,0 +1,7 @@ +import pytest + + +class TestSvnlook: + @pytest.mark.complete("svnlook ") + def test_1(self, completion): + assert completion diff --git a/test/t/test_sync_members.py b/test/t/test_sync_members.py new file mode 100644 index 0000000..f0d2dcf --- /dev/null +++ b/test/t/test_sync_members.py @@ -0,0 +1,7 @@ +import pytest + + +class TestSyncMembers: + @pytest.mark.complete("sync_members --") + def test_1(self, completion): + assert completion diff --git a/test/t/test_synclient.py b/test/t/test_synclient.py new file mode 100644 index 0000000..8a31a65 --- /dev/null +++ b/test/t/test_synclient.py @@ -0,0 +1,16 @@ +import pytest + + +class TestSynclient: + + # synclient -l may error out with e.g. + # "Couldn't find synaptics properties. No synaptics driver loaded?" + @pytest.mark.complete( + "synclient ", require_cmd=True, xfail="! synclient -l &>/dev/null" + ) + def test_1(self, completion): + assert completion + + @pytest.mark.complete("synclient -", require_cmd=True) + def test_2(self, completion): + assert completion diff --git a/test/t/test_sysbench.py b/test/t/test_sysbench.py new file mode 100644 index 0000000..4992d8a --- /dev/null +++ b/test/t/test_sysbench.py @@ -0,0 +1,11 @@ +import pytest + + +class TestSysbench: + @pytest.mark.complete("sysbench ", require_cmd=True) + def test_1(self, completion): + assert completion + + @pytest.mark.complete("sysbench -", require_cmd=True) + def test_2(self, completion): + assert completion diff --git a/test/t/test_sysctl.py b/test/t/test_sysctl.py new file mode 100644 index 0000000..f8db50b --- /dev/null +++ b/test/t/test_sysctl.py @@ -0,0 +1,15 @@ +import pytest + + +class TestSysctl: + @pytest.mark.complete("sysctl -", require_cmd=True) + def test_1(self, completion): + assert completion + + @pytest.mark.complete( + "sysctl kern", + require_cmd=True, + xfail="! sysctl -N -a 2>/dev/null | command grep -q ^kern", + ) + def test_2(self, completion): + assert completion diff --git a/test/t/test_tac.py b/test/t/test_tac.py new file mode 100644 index 0000000..db433cc --- /dev/null +++ b/test/t/test_tac.py @@ -0,0 +1,7 @@ +import pytest + + +class TestTac: + @pytest.mark.complete("tac --", require_longopt=True) + def test_1(self, completion): + assert completion diff --git a/test/t/test_tail.py b/test/t/test_tail.py new file mode 100644 index 0000000..6f2b3c6 --- /dev/null +++ b/test/t/test_tail.py @@ -0,0 +1,7 @@ +import pytest + + +class TestTail: + @pytest.mark.complete("tail --", require_longopt=True) + def test_1(self, completion): + assert completion diff --git a/test/t/test_tar.py b/test/t/test_tar.py new file mode 100644 index 0000000..4518d0b --- /dev/null +++ b/test/t/test_tar.py @@ -0,0 +1,120 @@ +import re + +import pytest + +from conftest import assert_bash_exec + + +@pytest.mark.bashcomp(ignore_env=r"^-declare -f _tar$") +class TestTar: + @pytest.fixture(scope="class") + def gnu_tar(self, bash): + got = assert_bash_exec(bash, "tar --version || :", want_output=True) + if not re.search(r"\bGNU ", got): + pytest.skip("Not GNU tar") + + @pytest.mark.complete("tar ") + def test_1(self, completion): + assert completion + + # Test "f" when mode is not as first option + @pytest.mark.complete("tar zfc ", cwd="tar") + def test_2(self, completion): + assert completion == "dir/ dir2/".split() + + @pytest.mark.complete("tar cf ", cwd="tar") + def test_3(self, completion): + assert completion == "dir/ dir2/".split() + + @pytest.mark.complete("tar tf archive.tar.xz dir/file", cwd="tar") + def test_4(self, completion): + assert completion == "dir/fileA dir/fileB dir/fileC".split() + + @pytest.mark.complete("tar cTfvv NOT_EXISTS DONT_CREATE.tar ", cwd="tar") + def test_5(self, completion): + assert completion == "archive.tar.xz dir/ dir2/ escape.tar".split() + + @pytest.mark.complete("tar xvf ", cwd="tar") + def test_6(self, completion): + assert completion == "archive.tar.xz dir/ dir2/ escape.tar".split() + + @pytest.mark.complete("tar -c") + def test_7(self, completion, gnu_tar): + """Test short options.""" + assert completion + + @pytest.mark.complete("tar -zcf ", cwd="tar") + def test_8(self, completion, gnu_tar): + """Test mode not as first option.""" + assert completion == "dir/ dir2/".split() + + @pytest.mark.complete("tar -cf ", cwd="tar") + def test_9(self, completion, gnu_tar): + """Test that we don't suggest rewriting existing archive.""" + assert completion == "dir/ dir2/".split() + + @pytest.mark.complete("tar -c --file ", cwd="tar") + def test_10(self, completion, gnu_tar): + assert completion == "dir/ dir2/".split() + + @pytest.mark.complete("tar -cvv --file ", cwd="tar") + def test_11(self, completion, gnu_tar): + assert completion == "dir/ dir2/".split() + + @pytest.mark.complete("tar -tf archive.tar.xz dir/file", cwd="tar") + def test_12(self, completion, gnu_tar): + """Test archive listing.""" + assert completion == "dir/fileA dir/fileB dir/fileC".split() + + @pytest.mark.complete("tar -t --file archive.tar.xz dir/file", cwd="tar") + def test_13(self, completion, gnu_tar): + """Test archive listing with --file.""" + assert completion == "dir/fileA dir/fileB dir/fileC".split() + + @pytest.mark.complete("tar --block") + def test_14(self, completion, gnu_tar): + assert completion == "--block-number --blocking-factor=".split() + + @pytest.mark.complete("tar --add-fil") + def test_15(self, completion, gnu_tar): + assert completion == "e=" + assert not completion.endswith(" ") + + @pytest.mark.complete("tar -cf /dev/null --posi") + def test_16(self, completion, gnu_tar): + assert completion == "x" + assert completion.endswith(" ") + + @pytest.mark.complete("tar --owner=") + 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, 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 + @pytest.mark.complete("tar -cvvfb ") + def test_19(self, bash, completion, gnu_tar): + """Test short option -XXXb <TAB> (arg required).""" + assert not completion + + # Use bsdtar here as it completes to only 'zc zt zx' + # -- 'tar' can be GNU tar and have more options + @pytest.mark.complete("bsdtar z") + def test_20(self, bash, completion): + assert completion == "zc zt zx".split() + + @pytest.mark.complete("bsdtar cbfvv NON_EXISTENT ", cwd="tar") + def test_21(self, bash, completion): + """Test _second_ option in "old" argument.""" + assert completion == "dir/ dir2/".split() + + @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 == "c/" + + # TODO: "tar tf escape.tar a/b" diff --git a/test/t/test_tcpdump.py b/test/t/test_tcpdump.py new file mode 100644 index 0000000..a557364 --- /dev/null +++ b/test/t/test_tcpdump.py @@ -0,0 +1,7 @@ +import pytest + + +class TestTcpdump: + @pytest.mark.complete("tcpdump -", require_cmd=True) + def test_1(self, completion): + assert completion diff --git a/test/t/test_tcpkill.py b/test/t/test_tcpkill.py new file mode 100644 index 0000000..4581a34 --- /dev/null +++ b/test/t/test_tcpkill.py @@ -0,0 +1,7 @@ +import pytest + + +class TestTcpkill: + @pytest.mark.complete("tcpkill -") + def test_1(self, completion): + assert completion diff --git a/test/t/test_tcpnice.py b/test/t/test_tcpnice.py new file mode 100644 index 0000000..fbe9592 --- /dev/null +++ b/test/t/test_tcpnice.py @@ -0,0 +1,7 @@ +import pytest + + +class TestTcpnice: + @pytest.mark.complete("tcpnice -", require_cmd=True) + def test_1(self, completion): + assert completion diff --git a/test/t/test_tee.py b/test/t/test_tee.py new file mode 100644 index 0000000..3d8bcd7 --- /dev/null +++ b/test/t/test_tee.py @@ -0,0 +1,11 @@ +import pytest + + +class TestTee: + @pytest.mark.complete("tee ") + def test_1(self, completion): + assert completion + + @pytest.mark.complete("tee -", require_longopt=True) + def test_options(self, completion): + assert completion diff --git a/test/t/test_texindex.py b/test/t/test_texindex.py new file mode 100644 index 0000000..c3f6a0b --- /dev/null +++ b/test/t/test_texindex.py @@ -0,0 +1,7 @@ +import pytest + + +class TestTexindex: + @pytest.mark.complete("texindex --", require_cmd=True) + def test_1(self, completion): + assert completion diff --git a/test/t/test_tightvncviewer.py b/test/t/test_tightvncviewer.py new file mode 100644 index 0000000..04ebece --- /dev/null +++ b/test/t/test_tightvncviewer.py @@ -0,0 +1,7 @@ +import pytest + + +class TestTightvncviewer: + @pytest.mark.complete("tightvncviewer ") + def test_1(self, completion): + assert completion diff --git a/test/t/test_time.py b/test/t/test_time.py new file mode 100644 index 0000000..231f14e --- /dev/null +++ b/test/t/test_time.py @@ -0,0 +1,23 @@ +import os + +import pytest + + +class TestTime: + @pytest.mark.complete("time set") + def test_1(self, completion): + assert completion + + @pytest.mark.complete("time -p find -typ") + def test_2(self, completion): + assert completion # find's options + + @pytest.mark.complete("time shared/bin/") + def test_3(self, completion): + execs = sorted( + x + for x in os.listdir("shared/bin") + if os.path.isfile("shared/bin/%s" % x) + and os.access("shared/bin/%s" % x, os.X_OK) + ) + assert completion == execs diff --git a/test/t/test_timeout.py b/test/t/test_timeout.py new file mode 100644 index 0000000..46fe2e0 --- /dev/null +++ b/test/t/test_timeout.py @@ -0,0 +1,11 @@ +import pytest + + +class TestTimeout: + @pytest.mark.complete("timeout ") + def test_1(self, completion): + assert not completion + + @pytest.mark.complete("timeout -", require_cmd=True) + def test_2(self, completion): + assert completion diff --git a/test/t/test_tipc.py b/test/t/test_tipc.py new file mode 100644 index 0000000..17b2bfd --- /dev/null +++ b/test/t/test_tipc.py @@ -0,0 +1,7 @@ +import pytest + + +class TestTipc: + @pytest.mark.complete("tipc ") + def test_1(self, completion): + assert completion diff --git a/test/t/test_totem.py b/test/t/test_totem.py new file mode 100644 index 0000000..f6fb26f --- /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_touch.py b/test/t/test_touch.py new file mode 100644 index 0000000..8a49e50 --- /dev/null +++ b/test/t/test_touch.py @@ -0,0 +1,7 @@ +import pytest + + +class TestTouch: + @pytest.mark.complete("touch --", require_longopt=True) + def test_1(self, completion): + assert completion diff --git a/test/t/test_tox.py b/test/t/test_tox.py new file mode 100644 index 0000000..f012a03 --- /dev/null +++ b/test/t/test_tox.py @@ -0,0 +1,19 @@ +import pytest + + +class TestTox: + @pytest.mark.complete("tox -") + def test_1(self, completion): + assert completion + + @pytest.mark.complete("tox -e ", cwd="tox") + def test_2(self, completion): + assert all(x in completion for x in "py37 ALL".split()) + + @pytest.mark.complete("tox -e foo,", cwd="tox") + def test_3(self, completion): + assert all(x in completion for x in "py37 ALL".split()) + + @pytest.mark.complete("tox -e foo -- ", cwd="tox") + def test_default_after_dashdash(self, completion): + assert "tox.ini" in completion diff --git a/test/t/test_tr.py b/test/t/test_tr.py new file mode 100644 index 0000000..0a51e9e --- /dev/null +++ b/test/t/test_tr.py @@ -0,0 +1,7 @@ +import pytest + + +class TestTr: + @pytest.mark.complete("tr --", require_longopt=True) + def test_1(self, completion): + assert completion diff --git a/test/t/test_tracepath.py b/test/t/test_tracepath.py new file mode 100644 index 0000000..e4cac65 --- /dev/null +++ b/test/t/test_tracepath.py @@ -0,0 +1,11 @@ +import pytest + + +class TestTracepath: + @pytest.mark.complete("tracepath ") + def test_1(self, completion): + assert completion + + @pytest.mark.complete("tracepath -", require_cmd=True) + def test_2(self, completion): + assert completion diff --git a/test/t/test_tshark.py b/test/t/test_tshark.py new file mode 100644 index 0000000..f49533e --- /dev/null +++ b/test/t/test_tshark.py @@ -0,0 +1,34 @@ +import pytest + + +@pytest.mark.bashcomp(ignore_env=r"^\+_tshark_pr(ef|otocol)s=") +class TestTshark: + @pytest.mark.complete("tshark -", require_cmd=True) + def test_1(self, completion): + assert completion + + @pytest.mark.complete("tshark -G ", require_cmd=True) + def test_2(self, completion): + assert completion + + @pytest.mark.complete("tshark -O foo,htt", require_cmd=True) + def test_3(self, 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): + assert "tcp.desegment_tcp_streams:" in completion + + @pytest.mark.complete("tshark -otcp", require_cmd=True) + def test_5(self, completion): + assert "-otcp.desegment_tcp_streams:" in completion + + @pytest.mark.complete("tshark -O http") + 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 0000000..8c8a64a --- /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_tune2fs.py b/test/t/test_tune2fs.py new file mode 100644 index 0000000..5cc0e41 --- /dev/null +++ b/test/t/test_tune2fs.py @@ -0,0 +1,11 @@ +import pytest + + +class TestTune2fs: + @pytest.mark.complete("tune2fs ") + def test_1(self, completion): + assert completion + + @pytest.mark.complete("tune2fs -", require_cmd=True) + def test_2(self, completion): + assert completion diff --git a/test/t/test_udevadm.py b/test/t/test_udevadm.py new file mode 100644 index 0000000..6191c77 --- /dev/null +++ b/test/t/test_udevadm.py @@ -0,0 +1,11 @@ +import pytest + + +class TestUdevadm: + @pytest.mark.complete("udevadm ", require_cmd=True) + def test_1(self, completion): + assert completion + + @pytest.mark.complete("udevadm -", require_cmd=True) + def test_2(self, completion): + assert completion diff --git a/test/t/test_ulimit.py b/test/t/test_ulimit.py new file mode 100644 index 0000000..3ab974c --- /dev/null +++ b/test/t/test_ulimit.py @@ -0,0 +1,35 @@ +import pytest + + +class TestUlimit: + @pytest.mark.complete("ulimit ") + def test_1(self, completion): + assert completion + + @pytest.mark.complete("ulimit -", require_cmd=True) + def test_2(self, completion): + assert completion + + @pytest.mark.complete("ulimit -S -") + def test_3(self, completion): + """Test modes are completed after -S (-S not treated as mode).""" + assert completion + + @pytest.mark.complete("ulimit -u -") + def test_4(self, completion): + """Test modes are NOT completed if one is specified.""" + assert not completion + + @pytest.mark.complete("ulimit -c ") + def test_5(self, completion): + assert completion + assert not any(x.startswith("-") for x in completion) + + @pytest.mark.complete("ulimit -a ") + def test_6(self, completion): + assert completion == sorted("-S -H".split()) + + @pytest.mark.complete("ulimit -a -H -") + def test_7(self, completion): + """Test modes are NOT completed with -a given somewhere.""" + assert not completion diff --git a/test/t/test_umount.py b/test/t/test_umount.py new file mode 100644 index 0000000..2baf0da --- /dev/null +++ b/test/t/test_umount.py @@ -0,0 +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_unace.py b/test/t/test_unace.py new file mode 100644 index 0000000..e4d5acb --- /dev/null +++ b/test/t/test_unace.py @@ -0,0 +1,7 @@ +import pytest + + +class TestUnace: + @pytest.mark.complete("unace -") + def test_1(self, completion): + assert completion diff --git a/test/t/test_uname.py b/test/t/test_uname.py new file mode 100644 index 0000000..e71a433 --- /dev/null +++ b/test/t/test_uname.py @@ -0,0 +1,7 @@ +import pytest + + +class TestUname: + @pytest.mark.complete("uname --", require_longopt=True) + def test_1(self, completion): + assert completion diff --git a/test/t/test_unexpand.py b/test/t/test_unexpand.py new file mode 100644 index 0000000..2f1359b --- /dev/null +++ b/test/t/test_unexpand.py @@ -0,0 +1,7 @@ +import pytest + + +class TestUnexpand: + @pytest.mark.complete("unexpand --", require_longopt=True) + def test_1(self, completion): + assert completion diff --git a/test/t/test_uniq.py b/test/t/test_uniq.py new file mode 100644 index 0000000..73691fd --- /dev/null +++ b/test/t/test_uniq.py @@ -0,0 +1,7 @@ +import pytest + + +class TestUniq: + @pytest.mark.complete("uniq --", require_longopt=True) + def test_1(self, completion): + assert completion diff --git a/test/t/test_units.py b/test/t/test_units.py new file mode 100644 index 0000000..824e2ce --- /dev/null +++ b/test/t/test_units.py @@ -0,0 +1,9 @@ +import pytest + + +class TestUnits: + @pytest.mark.complete( + "units --", require_cmd=True, xfail="! units --help &>/dev/null" + ) + def test_1(self, completion): + assert completion diff --git a/test/t/test_unpack200.py b/test/t/test_unpack200.py new file mode 100644 index 0000000..16c0402 --- /dev/null +++ b/test/t/test_unpack200.py @@ -0,0 +1,7 @@ +import pytest + + +class TestUnpack200: + @pytest.mark.complete("unpack200 ") + def test_1(self, completion): + assert completion diff --git a/test/t/test_unrar.py b/test/t/test_unrar.py new file mode 100644 index 0000000..45e336e --- /dev/null +++ b/test/t/test_unrar.py @@ -0,0 +1,7 @@ +import pytest + + +class TestUnrar: + @pytest.mark.complete("unrar -") + def test_1(self, completion): + assert completion diff --git a/test/t/test_unset.py b/test/t/test_unset.py new file mode 100644 index 0000000..9f3eade --- /dev/null +++ b/test/t/test_unset.py @@ -0,0 +1,7 @@ +import pytest + + +class TestUnset: + @pytest.mark.complete("unset BASH_ARG") + def test_1(self, completion): + assert completion diff --git a/test/t/test_unshunt.py b/test/t/test_unshunt.py new file mode 100644 index 0000000..a354239 --- /dev/null +++ b/test/t/test_unshunt.py @@ -0,0 +1,7 @@ +import pytest + + +class TestUnshunt: + @pytest.mark.complete("unshunt --", require_cmd=True) + def test_1(self, completion): + assert completion diff --git a/test/t/test_update_alternatives.py b/test/t/test_update_alternatives.py new file mode 100644 index 0000000..7c77730 --- /dev/null +++ b/test/t/test_update_alternatives.py @@ -0,0 +1,8 @@ +import pytest + + +@pytest.mark.bashcomp(cmd="update-alternatives") +class TestUpdateAlternatives: + @pytest.mark.complete("update-alternatives --", require_cmd=True) + def test_1(self, completion): + assert completion diff --git a/test/t/test_update_rc_d.py b/test/t/test_update_rc_d.py new file mode 100644 index 0000000..6f57416 --- /dev/null +++ b/test/t/test_update_rc_d.py @@ -0,0 +1,8 @@ +import pytest + + +@pytest.mark.bashcomp(cmd="update-rc.d") +class TestUpdateRcD: + @pytest.mark.complete("update-rc.d -") + def test_1(self, completion): + assert completion diff --git a/test/t/test_upgradepkg.py b/test/t/test_upgradepkg.py new file mode 100644 index 0000000..87fe8e4 --- /dev/null +++ b/test/t/test_upgradepkg.py @@ -0,0 +1,51 @@ +import fnmatch +import os + +import pytest + + +class TestUpgradepkg: + @pytest.mark.complete("upgradepkg -") + def test_1(self, completion): + assert completion + + @pytest.mark.complete("upgradepkg --") + def test_2(self, completion): + assert ( + completion == "--dry-run --install-new --reinstall " + "--verbose".split() + ) + + @pytest.mark.complete("upgradepkg ", cwd="slackware/home") + def test_4(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 == 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_urlsnarf.py b/test/t/test_urlsnarf.py new file mode 100644 index 0000000..8551c60 --- /dev/null +++ b/test/t/test_urlsnarf.py @@ -0,0 +1,7 @@ +import pytest + + +class TestUrlsnarf: + @pytest.mark.complete("urlsnarf -", require_cmd=True) + def test_1(self, completion): + assert completion diff --git a/test/t/test_uscan.py b/test/t/test_uscan.py new file mode 100644 index 0000000..142c325 --- /dev/null +++ b/test/t/test_uscan.py @@ -0,0 +1,7 @@ +import pytest + + +class TestUscan: + @pytest.mark.complete("uscan -", require_cmd=True) + def test_1(self, completion): + assert completion diff --git a/test/t/test_useradd.py b/test/t/test_useradd.py new file mode 100644 index 0000000..5cbf6ce --- /dev/null +++ b/test/t/test_useradd.py @@ -0,0 +1,11 @@ +import pytest + + +class TestUseradd: + @pytest.mark.complete("useradd ") + def test_1(self, completion): + assert not completion + + @pytest.mark.complete("useradd -", require_cmd=True) + def test_2(self, completion): + assert completion diff --git a/test/t/test_userdel.py b/test/t/test_userdel.py new file mode 100644 index 0000000..3405e12 --- /dev/null +++ b/test/t/test_userdel.py @@ -0,0 +1,11 @@ +import pytest + + +class TestUserdel: + @pytest.mark.complete("userdel -", require_cmd=True) + def test_1(self, completion): + assert completion + + @pytest.mark.complete("userdel roo") + def test_2(self, completion): + assert completion == "t" or "root" in completion diff --git a/test/t/test_usermod.py b/test/t/test_usermod.py new file mode 100644 index 0000000..ef3dd5a --- /dev/null +++ b/test/t/test_usermod.py @@ -0,0 +1,11 @@ +import pytest + + +class TestUsermod: + @pytest.mark.complete("usermod ") + def test_1(self, completion): + assert completion + + @pytest.mark.complete("usermod -", require_cmd=True) + def test_2(self, completion): + assert completion diff --git a/test/t/test_valgrind.py b/test/t/test_valgrind.py new file mode 100644 index 0000000..0553b55 --- /dev/null +++ b/test/t/test_valgrind.py @@ -0,0 +1,42 @@ +import os + +import pytest + + +class TestValgrind: + + # b: Assume we have at least bash that starts with b in PATH + @pytest.mark.complete("valgrind b") + def test_1(self, completion): + assert completion + + @pytest.mark.complete("valgrind -", require_cmd=True) + def test_2(self, completion): + assert completion + + @pytest.mark.complete("valgrind --tool=memche", require_cmd=True) + def test_3(self, 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 completion == "evel=" or "--history-level=" in completion + assert not completion.endswith(" ") + + @pytest.mark.complete(r"valgrind --log-file=v\ 0.log ./bin/", cwd="shared") + def test_5(self, completion): + expected = sorted( + [ + "%s/" + for x in os.listdir("shared/bin") + if os.path.isdir("shared/bin/%s" % x) + ] + + [ + x + for x in os.listdir("shared/bin") + if os.path.isfile("shared/bin/%s" % x) + ] + ) + assert completion == expected diff --git a/test/t/test_vdir.py b/test/t/test_vdir.py new file mode 100644 index 0000000..e186989 --- /dev/null +++ b/test/t/test_vdir.py @@ -0,0 +1,11 @@ +import pytest + + +class TestVdir: + @pytest.mark.complete("vdir ") + def test_1(self, completion): + assert completion + + @pytest.mark.complete("vdir -", require_cmd=True) + def test_options(self, completion): + assert completion diff --git a/test/t/test_vgcfgbackup.py b/test/t/test_vgcfgbackup.py new file mode 100644 index 0000000..2e6c6f1 --- /dev/null +++ b/test/t/test_vgcfgbackup.py @@ -0,0 +1,11 @@ +import pytest + + +class TestVgcfgbackup: + @pytest.mark.complete( + "vgcfgbackup -", + require_cmd=True, + xfail="! vgcfgbackup --help &>/dev/null", + ) + def test_1(self, completion): + assert completion diff --git a/test/t/test_vgcfgrestore.py b/test/t/test_vgcfgrestore.py new file mode 100644 index 0000000..acb1a38 --- /dev/null +++ b/test/t/test_vgcfgrestore.py @@ -0,0 +1,11 @@ +import pytest + + +class TestVgcfgrestore: + @pytest.mark.complete( + "vgcfgrestore -", + require_cmd=True, + xfail="! vgcfgrestore --help &>/dev/null", + ) + def test_1(self, completion): + assert completion diff --git a/test/t/test_vgchange.py b/test/t/test_vgchange.py new file mode 100644 index 0000000..ed14f2a --- /dev/null +++ b/test/t/test_vgchange.py @@ -0,0 +1,9 @@ +import pytest + + +class TestVgchange: + @pytest.mark.complete( + "vgchange -", require_cmd=True, xfail="! vgchange --help &>/dev/null" + ) + def test_1(self, completion): + assert completion diff --git a/test/t/test_vgck.py b/test/t/test_vgck.py new file mode 100644 index 0000000..52ddf88 --- /dev/null +++ b/test/t/test_vgck.py @@ -0,0 +1,9 @@ +import pytest + + +class TestVgck: + @pytest.mark.complete( + "vgck -", require_cmd=True, xfail="! vgck --help &>/dev/null" + ) + def test_1(self, completion): + assert completion diff --git a/test/t/test_vgconvert.py b/test/t/test_vgconvert.py new file mode 100644 index 0000000..029fe48 --- /dev/null +++ b/test/t/test_vgconvert.py @@ -0,0 +1,9 @@ +import pytest + + +class TestVgconvert: + @pytest.mark.complete( + "vgconvert -", require_cmd=True, xfail="! vgconvert --help &>/dev/null" + ) + def test_1(self, completion): + assert completion diff --git a/test/t/test_vgcreate.py b/test/t/test_vgcreate.py new file mode 100644 index 0000000..40c1773 --- /dev/null +++ b/test/t/test_vgcreate.py @@ -0,0 +1,13 @@ +import pytest + + +class TestVgcreate: + @pytest.mark.complete( + "vgcreate -", require_cmd=True, xfail="! vgcreate --help &>/dev/null" + ) + def test_1(self, completion): + assert completion + + @pytest.mark.complete("vgcreate __does_not_exist__", require_cmd=True) + def test_2(self, completion): + assert not completion diff --git a/test/t/test_vgdisplay.py b/test/t/test_vgdisplay.py new file mode 100644 index 0000000..6066729 --- /dev/null +++ b/test/t/test_vgdisplay.py @@ -0,0 +1,9 @@ +import pytest + + +class TestVgdisplay: + @pytest.mark.complete( + "vgdisplay -", require_cmd=True, xfail="! vgdisplay --help &>/dev/null" + ) + def test_1(self, completion): + assert completion diff --git a/test/t/test_vgexport.py b/test/t/test_vgexport.py new file mode 100644 index 0000000..96ecc3c --- /dev/null +++ b/test/t/test_vgexport.py @@ -0,0 +1,9 @@ +import pytest + + +class TestVgexport: + @pytest.mark.complete( + "vgexport -", require_cmd=True, xfail="! vgexport --help &>/dev/null" + ) + def test_1(self, completion): + assert completion diff --git a/test/t/test_vgextend.py b/test/t/test_vgextend.py new file mode 100644 index 0000000..8c41ab6 --- /dev/null +++ b/test/t/test_vgextend.py @@ -0,0 +1,9 @@ +import pytest + + +class TestVgextend: + @pytest.mark.complete( + "vgextend -", require_cmd=True, xfail="! vgextend --help &>/dev/null" + ) + def test_1(self, completion): + assert completion diff --git a/test/t/test_vgimport.py b/test/t/test_vgimport.py new file mode 100644 index 0000000..24017d2 --- /dev/null +++ b/test/t/test_vgimport.py @@ -0,0 +1,9 @@ +import pytest + + +class TestVgimport: + @pytest.mark.complete( + "vgimport -", require_cmd=True, xfail="! vgimport --help &>/dev/null" + ) + def test_1(self, completion): + assert completion diff --git a/test/t/test_vgmerge.py b/test/t/test_vgmerge.py new file mode 100644 index 0000000..7d88932 --- /dev/null +++ b/test/t/test_vgmerge.py @@ -0,0 +1,9 @@ +import pytest + + +class TestVgmerge: + @pytest.mark.complete( + "vgmerge -", require_cmd=True, xfail="! vgmerge --help &>/dev/null" + ) + def test_1(self, completion): + assert completion diff --git a/test/t/test_vgmknodes.py b/test/t/test_vgmknodes.py new file mode 100644 index 0000000..7e046f0 --- /dev/null +++ b/test/t/test_vgmknodes.py @@ -0,0 +1,9 @@ +import pytest + + +class TestVgmknodes: + @pytest.mark.complete( + "vgmknodes -", require_cmd=True, xfail="! vgmknodes --help &>/dev/null" + ) + def test_1(self, completion): + assert completion diff --git a/test/t/test_vgreduce.py b/test/t/test_vgreduce.py new file mode 100644 index 0000000..26174b9 --- /dev/null +++ b/test/t/test_vgreduce.py @@ -0,0 +1,9 @@ +import pytest + + +class TestVgreduce: + @pytest.mark.complete( + "vgreduce -", require_cmd=True, xfail="! vgreduce --help &>/dev/null" + ) + def test_1(self, completion): + assert completion diff --git a/test/t/test_vgremove.py b/test/t/test_vgremove.py new file mode 100644 index 0000000..637d5c3 --- /dev/null +++ b/test/t/test_vgremove.py @@ -0,0 +1,9 @@ +import pytest + + +class TestVgremove: + @pytest.mark.complete( + "vgremove -", require_cmd=True, xfail="! vgremove --help &>/dev/null" + ) + def test_1(self, completion): + assert completion diff --git a/test/t/test_vgrename.py b/test/t/test_vgrename.py new file mode 100644 index 0000000..87a6a72 --- /dev/null +++ b/test/t/test_vgrename.py @@ -0,0 +1,9 @@ +import pytest + + +class TestVgrename: + @pytest.mark.complete( + "vgrename -", require_cmd=True, xfail="! vgrename --help &>/dev/null" + ) + def test_1(self, completion): + assert completion diff --git a/test/t/test_vgs.py b/test/t/test_vgs.py new file mode 100644 index 0000000..e0d8a03 --- /dev/null +++ b/test/t/test_vgs.py @@ -0,0 +1,9 @@ +import pytest + + +class TestVgs: + @pytest.mark.complete( + "vgs -", require_cmd=True, xfail="! vgs --help &>/dev/null" + ) + def test_1(self, completion): + assert completion diff --git a/test/t/test_vgscan.py b/test/t/test_vgscan.py new file mode 100644 index 0000000..95a4026 --- /dev/null +++ b/test/t/test_vgscan.py @@ -0,0 +1,9 @@ +import pytest + + +class TestVgscan: + @pytest.mark.complete( + "vgscan -", require_cmd=True, xfail="! vgscan --help &>/dev/null" + ) + def test_1(self, completion): + assert completion diff --git a/test/t/test_vgsplit.py b/test/t/test_vgsplit.py new file mode 100644 index 0000000..1c3dfa8 --- /dev/null +++ b/test/t/test_vgsplit.py @@ -0,0 +1,9 @@ +import pytest + + +class TestVgsplit: + @pytest.mark.complete( + "vgsplit -", require_cmd=True, xfail="! vgsplit --help &>/dev/null" + ) + def test_1(self, completion): + assert completion diff --git a/test/t/test_vi.py b/test/t/test_vi.py new file mode 100644 index 0000000..4f7f4c2 --- /dev/null +++ b/test/t/test_vi.py @@ -0,0 +1,11 @@ +import pytest + + +class TestVi: + @pytest.mark.complete("vi ") + def test_1(self, completion): + assert completion + + @pytest.mark.complete("vi shared/ld.so.conf.d/") + def test_2(self, completion): + assert completion == "foo.txt libfoo.conf".split() diff --git a/test/t/test_vipw.py b/test/t/test_vipw.py new file mode 100644 index 0000000..07b454b --- /dev/null +++ b/test/t/test_vipw.py @@ -0,0 +1,7 @@ +import pytest + + +class TestVipw: + @pytest.mark.complete("vipw -", require_cmd=True) + def test_1(self, completion): + assert completion diff --git a/test/t/test_vmstat.py b/test/t/test_vmstat.py new file mode 100644 index 0000000..b7145ff --- /dev/null +++ b/test/t/test_vmstat.py @@ -0,0 +1,7 @@ +import pytest + + +class TestVmstat: + @pytest.mark.complete("vmstat -", require_cmd=True) + def test_1(self, completion): + assert completion diff --git a/test/t/test_vncviewer.py b/test/t/test_vncviewer.py new file mode 100644 index 0000000..9e2f148 --- /dev/null +++ b/test/t/test_vncviewer.py @@ -0,0 +1,8 @@ +import pytest + + +@pytest.mark.bashcomp(ignore_env=r"^-declare -f _vncviewer_bootstrap$") +class TestVncviewer: + @pytest.mark.complete("vncviewer ") + def test_1(self, completion): + assert completion diff --git a/test/t/test_vpnc.py b/test/t/test_vpnc.py new file mode 100644 index 0000000..dac5b15 --- /dev/null +++ b/test/t/test_vpnc.py @@ -0,0 +1,13 @@ +import pytest + + +@pytest.mark.bashcomp( + # On CentOS and Fedora, there's something fishy with consolehelper and + # /usr/bin/vpnc going on at least when invoked as root; try to invoke the + # one in /usr/sbin instead. + pre_cmds=("PATH=/usr/sbin:$PATH",) +) +class TestVpnc: + @pytest.mark.complete("vpnc -", require_cmd=True) + def test_1(self, completion): + assert completion diff --git a/test/t/test_watch.py b/test/t/test_watch.py new file mode 100644 index 0000000..b1de7f5 --- /dev/null +++ b/test/t/test_watch.py @@ -0,0 +1,7 @@ +import pytest + + +class TestWatch: + @pytest.mark.complete("watch -", require_cmd=True) + def test_1(self, completion): + assert completion diff --git a/test/t/test_wc.py b/test/t/test_wc.py new file mode 100644 index 0000000..1f83ea7 --- /dev/null +++ b/test/t/test_wc.py @@ -0,0 +1,7 @@ +import pytest + + +class TestWc: + @pytest.mark.complete("wc --", require_longopt=True) + def test_1(self, completion): + assert completion diff --git a/test/t/test_webmitm.py b/test/t/test_webmitm.py new file mode 100644 index 0000000..d631dcf --- /dev/null +++ b/test/t/test_webmitm.py @@ -0,0 +1,7 @@ +import pytest + + +class TestWebmitm: + @pytest.mark.complete("webmitm -", require_cmd=True) + def test_1(self, completion): + assert completion diff --git a/test/t/test_wget.py b/test/t/test_wget.py new file mode 100644 index 0000000..de752c2 --- /dev/null +++ b/test/t/test_wget.py @@ -0,0 +1,11 @@ +import pytest + + +class TestWget: + @pytest.mark.complete("wget ") + def test_1(self, completion): + assert not completion + + @pytest.mark.complete("wget --s", require_cmd=True) + def test_2(self, completion): + assert completion diff --git a/test/t/test_who.py b/test/t/test_who.py new file mode 100644 index 0000000..9131ac7 --- /dev/null +++ b/test/t/test_who.py @@ -0,0 +1,9 @@ +import pytest + + +class TestWho: + @pytest.mark.complete( + "who --", require_cmd=True, xfail="! who --help &>/dev/null" + ) + def test_1(self, completion): + assert completion diff --git a/test/t/test_wine.py b/test/t/test_wine.py new file mode 100644 index 0000000..d0e5698 --- /dev/null +++ b/test/t/test_wine.py @@ -0,0 +1,11 @@ +import pytest + + +class TestWine: + @pytest.mark.complete("wine ", cwd="shared/default") + def test_1(self, completion): + assert completion == ["bar bar.d/", "foo.d/"] + + @pytest.mark.complete("wine notepad ", cwd="shared/default") + def test_2(self, completion): + assert completion == ["bar", "bar bar.d/", "foo", "foo.d/"] diff --git a/test/t/test_withlist.py b/test/t/test_withlist.py new file mode 100644 index 0000000..752c394 --- /dev/null +++ b/test/t/test_withlist.py @@ -0,0 +1,7 @@ +import pytest + + +class TestWithlist: + @pytest.mark.complete("withlist --") + def test_1(self, completion): + assert completion diff --git a/test/t/test_wodim.py b/test/t/test_wodim.py new file mode 100644 index 0000000..4b785b6 --- /dev/null +++ b/test/t/test_wodim.py @@ -0,0 +1,7 @@ +import pytest + + +class TestWodim: + @pytest.mark.complete("wodim ") + def test_1(self, completion): + assert completion diff --git a/test/t/test_wol.py b/test/t/test_wol.py new file mode 100644 index 0000000..bf04f76 --- /dev/null +++ b/test/t/test_wol.py @@ -0,0 +1,20 @@ +import pytest + + +@pytest.mark.bashcomp(pre_cmds=("PATH=$PWD/shared/bin:$PATH",)) +class TestWol: + @pytest.mark.complete("wol ") + def test_1(self, completion): + 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 any(x.endswith("00:00:00:00:00") for x in completion) + + @pytest.mark.complete("wol -", require_cmd=True) + def test_3(self, completion): + assert completion diff --git a/test/t/test_write.py b/test/t/test_write.py new file mode 100644 index 0000000..fc4bfa0 --- /dev/null +++ b/test/t/test_write.py @@ -0,0 +1,7 @@ +import pytest + + +class TestWrite: + @pytest.mark.complete("write roo") + def test_1(self, completion): + assert completion == "t" or "root" in completion diff --git a/test/t/test_wsimport.py b/test/t/test_wsimport.py new file mode 100644 index 0000000..8c27f4b --- /dev/null +++ b/test/t/test_wsimport.py @@ -0,0 +1,18 @@ +import pytest + + +class TestWsimport: + @pytest.mark.complete("wsimport ") + def test_1(self, completion): + assert completion + + @pytest.mark.complete( + "wsimport -", + require_cmd=True, + xfail=( + "! (wsimport -help 2>&1 || :) | " + "command grep -q -- '[[:space:]]-'" + ), + ) + def test_2(self, completion): + assert completion diff --git a/test/t/test_wtf.py b/test/t/test_wtf.py new file mode 100644 index 0000000..45dfcfd --- /dev/null +++ b/test/t/test_wtf.py @@ -0,0 +1,8 @@ +import pytest + + +class TestWtf: + # TODO: actually requires an acronym db, not the cmd + @pytest.mark.complete("wtf A", require_cmd=True) + def test_1(self, completion): + assert completion diff --git a/test/t/test_wvdial.py b/test/t/test_wvdial.py new file mode 100644 index 0000000..bbc520d --- /dev/null +++ b/test/t/test_wvdial.py @@ -0,0 +1,7 @@ +import pytest + + +class TestWvdial: + @pytest.mark.complete("wvdial -", require_cmd=True) + def test_1(self, completion): + assert completion diff --git a/test/t/test_xdg_mime.py b/test/t/test_xdg_mime.py new file mode 100644 index 0000000..432be06 --- /dev/null +++ b/test/t/test_xdg_mime.py @@ -0,0 +1,28 @@ +import pytest + + +@pytest.mark.bashcomp(cmd="xdg-mime") +class TestXdgMime: + @pytest.mark.complete("xdg-mime ") + def test_1(self, completion): + assert completion + + @pytest.mark.complete("xdg-mime -") + def test_2(self, completion): + assert completion + + @pytest.mark.complete("xdg-mime query ") + def test_3(self, completion): + assert completion + + @pytest.mark.complete("xdg-mime query filetype ") + def test_4(self, completion): + assert completion + + @pytest.mark.complete("xdg-mime default foo.desktop ") + def test_5(self, completion): + assert completion + + @pytest.mark.complete("xdg-mime install --mode ") + def test_6(self, completion): + assert completion diff --git a/test/t/test_xdg_settings.py b/test/t/test_xdg_settings.py new file mode 100644 index 0000000..1a19459 --- /dev/null +++ b/test/t/test_xdg_settings.py @@ -0,0 +1,16 @@ +import pytest + + +@pytest.mark.bashcomp(cmd="xdg-settings") +class TestXdgSettings: + @pytest.mark.complete("xdg-settings ") + def test_1(self, completion): + assert completion + + @pytest.mark.complete("xdg-settings --", require_cmd=True) + def test_2(self, completion): + assert completion + + @pytest.mark.complete("xdg-settings get ", require_cmd=True) + def test_3(self, completion): + assert completion diff --git a/test/t/test_xfreerdp.py b/test/t/test_xfreerdp.py new file mode 100644 index 0000000..5616271 --- /dev/null +++ b/test/t/test_xfreerdp.py @@ -0,0 +1,60 @@ +import pytest + +from conftest import assert_bash_exec + + +class TestXfreerdp: + def _help(self, bash): + return assert_bash_exec( + bash, "xfreerdp --help 2>&1 || :", want_output=True + ) + + @pytest.fixture(scope="class") + 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") + + @pytest.fixture(scope="class") + def dash_syntax(self, bash): + if "/help" in self._help(bash): + pytest.skip("Not dash syntax") + + @pytest.mark.complete("xfreerdp /", require_cmd=True) + def test_1(self, bash, completion, help_success, slash_syntax): + assert completion + + @pytest.mark.complete("xfreerdp -", require_cmd=True) + def test_2(self, completion, help_success): + assert completion + + @pytest.mark.complete("xfreerdp +", require_cmd=True) + def test_3(self, bash, completion, help_success, slash_syntax): + assert completion + + @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, help_success): + assert not completion + + @pytest.mark.complete("xfreerdp -k ", require_cmd=True) + def test_6(self, bash, completion, help_success, dash_syntax): + assert completion + + @pytest.mark.complete("xfreerdp --help ", require_cmd=True) + def test_7(self, completion): + assert not completion diff --git a/test/t/test_xgamma.py b/test/t/test_xgamma.py new file mode 100644 index 0000000..151e2d3 --- /dev/null +++ b/test/t/test_xgamma.py @@ -0,0 +1,12 @@ +import pytest + + +class TestXgamma: + @pytest.mark.complete("xgamma -", require_cmd=True) + def test_1(self, completion): + assert completion + + @pytest.mark.complete("xgamma -gam", require_cmd=True) + def test_2(self, completion): + 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 0000000..bb2df82 --- /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/test_xm.py b/test/t/test_xm.py new file mode 100644 index 0000000..42c4c53 --- /dev/null +++ b/test/t/test_xm.py @@ -0,0 +1,7 @@ +import pytest + + +class TestXm: + @pytest.mark.complete("xm ") + def test_1(self, completion): + assert completion diff --git a/test/t/test_xmllint.py b/test/t/test_xmllint.py new file mode 100644 index 0000000..21c52c7 --- /dev/null +++ b/test/t/test_xmllint.py @@ -0,0 +1,11 @@ +import pytest + + +class TestXmllint: + @pytest.mark.complete("xmllint ") + def test_1(self, completion): + assert completion + + @pytest.mark.complete("xmllint -", require_cmd=True) + def test_2(self, completion): + assert completion diff --git a/test/t/test_xmlwf.py b/test/t/test_xmlwf.py new file mode 100644 index 0000000..901f78a --- /dev/null +++ b/test/t/test_xmlwf.py @@ -0,0 +1,11 @@ +import pytest + + +class TestXmlwf: + @pytest.mark.complete("xmlwf ") + def test_1(self, completion): + assert completion + + @pytest.mark.complete("xmlwf -", require_cmd=True) + def test_2(self, completion): + assert completion diff --git a/test/t/test_xmms.py b/test/t/test_xmms.py new file mode 100644 index 0000000..a880b16 --- /dev/null +++ b/test/t/test_xmms.py @@ -0,0 +1,11 @@ +import pytest + + +class TestXmms: + @pytest.mark.complete("xmms --", require_cmd=True) + def test_1(self, completion): + assert completion + + @pytest.mark.complete("xmms --non-existent-option=--") + def test_2(self, completion): + assert not completion diff --git a/test/t/test_xmodmap.py b/test/t/test_xmodmap.py new file mode 100644 index 0000000..cc33d73 --- /dev/null +++ b/test/t/test_xmodmap.py @@ -0,0 +1,11 @@ +import pytest + + +class TestXmodmap: + @pytest.mark.complete("xmodmap ") + def test_1(self, completion): + assert completion + + @pytest.mark.complete("xmodmap -", require_cmd=True) + def test_2(self, completion): + assert completion diff --git a/test/t/test_xpovray.py b/test/t/test_xpovray.py new file mode 100644 index 0000000..4f603a7 --- /dev/null +++ b/test/t/test_xpovray.py @@ -0,0 +1,7 @@ +import pytest + + +class TestXpovray: + @pytest.mark.complete("xpovray ") + def test_1(self, completion): + assert completion diff --git a/test/t/test_xrandr.py b/test/t/test_xrandr.py new file mode 100644 index 0000000..e766922 --- /dev/null +++ b/test/t/test_xrandr.py @@ -0,0 +1,15 @@ +import pytest + + +class TestXrandr: + @pytest.mark.complete("xrandr ", require_cmd=True) + def test_1(self, completion): + assert completion + + @pytest.mark.complete("xrandr --mode ") + def test_2(self, completion): + assert not completion + + @pytest.mark.complete("xrandr -", require_cmd=True) + def test_3(self, completion): + assert completion diff --git a/test/t/test_xrdb.py b/test/t/test_xrdb.py new file mode 100644 index 0000000..3ffce2c --- /dev/null +++ b/test/t/test_xrdb.py @@ -0,0 +1,11 @@ +import pytest + + +class TestXrdb: + @pytest.mark.complete("xrdb ") + def test_1(self, completion): + assert completion + + @pytest.mark.complete("xrdb -", require_cmd=True) + def test_2(self, completion): + assert completion diff --git a/test/t/test_xsltproc.py b/test/t/test_xsltproc.py new file mode 100644 index 0000000..259f9eb --- /dev/null +++ b/test/t/test_xsltproc.py @@ -0,0 +1,11 @@ +import pytest + + +class TestXsltproc: + @pytest.mark.complete("xsltproc ") + def test_1(self, completion): + assert completion + + @pytest.mark.complete("xsltproc -", require_cmd=True) + def test_2(self, completion): + assert completion diff --git a/test/t/test_xvfb_run.py b/test/t/test_xvfb_run.py new file mode 100644 index 0000000..89eb830 --- /dev/null +++ b/test/t/test_xvfb_run.py @@ -0,0 +1,12 @@ +import pytest + + +@pytest.mark.bashcomp(cmd="xvfb-run") +class TestXvfbRun: + @pytest.mark.complete("xvfb-run ") + def test_no_args(self, completion): + assert any(x in completion for x in ("bash", "xvfb-run")) + + @pytest.mark.complete("xvfb-run -", require_cmd=True) + def test_options(self, completion): + assert completion diff --git a/test/t/test_xvnc4viewer.py b/test/t/test_xvnc4viewer.py new file mode 100644 index 0000000..72fe3f9 --- /dev/null +++ b/test/t/test_xvnc4viewer.py @@ -0,0 +1,15 @@ +import pytest + + +class TestXvnc4viewer: + @pytest.mark.complete("xvnc4viewer -") + def test_1(self, completion): + assert completion + + @pytest.mark.complete("xvnc4viewer -PreferredEncoding ") + def test_2(self, completion): + assert completion == "hextile raw zrle".split() + + @pytest.mark.complete("xvnc4viewer --preferredencoding ") + def test_3(self, completion): + assert completion == "hextile raw zrle".split() diff --git a/test/t/test_xxd.py b/test/t/test_xxd.py new file mode 100644 index 0000000..9e84bb7 --- /dev/null +++ b/test/t/test_xxd.py @@ -0,0 +1,11 @@ +import pytest + + +class TestXxd: + @pytest.mark.complete("xxd ") + def test_1(self, completion): + assert completion + + @pytest.mark.complete("xxd -", require_cmd=True) + def test_2(self, completion): + assert completion diff --git a/test/t/test_xz.py b/test/t/test_xz.py new file mode 100644 index 0000000..f226d02 --- /dev/null +++ b/test/t/test_xz.py @@ -0,0 +1,26 @@ +import pytest + + +class TestXz: + @pytest.mark.complete("xz ") + def test_1(self, completion): + assert completion + + @pytest.mark.complete("xz -d xz/") + def test_2(self, completion): + assert ( + completion == "a/ bashcomp.lzma bashcomp.tar.xz " + "bashcomp.tlz bashcomp.xz".split() + ) + + @pytest.mark.complete("xz xz/") + def test_3(self, completion): + assert completion == "a/ bashcomp.tar".split() + + @pytest.mark.complete("xz ~") + def test_4(self, completion): + assert completion + + @pytest.mark.complete("xz -", require_cmd=True) + def test_5(self, completion): + assert completion diff --git a/test/t/test_xzdec.py b/test/t/test_xzdec.py new file mode 100644 index 0000000..a1e9a3b --- /dev/null +++ b/test/t/test_xzdec.py @@ -0,0 +1,11 @@ +import pytest + + +class TestXzdec: + @pytest.mark.complete("xzdec ") + def test_1(self, completion): + assert completion + + @pytest.mark.complete("xzdec -", require_cmd=True) + def test_2(self, completion): + assert completion diff --git a/test/t/test_ypcat.py b/test/t/test_ypcat.py new file mode 100644 index 0000000..0fc4b45 --- /dev/null +++ b/test/t/test_ypcat.py @@ -0,0 +1,7 @@ +import pytest + + +class TestYpcat: + @pytest.mark.complete("ypcat ", require_cmd=True) + def test_1(self, completion): + assert completion diff --git a/test/t/test_ypmatch.py b/test/t/test_ypmatch.py new file mode 100644 index 0000000..18331aa --- /dev/null +++ b/test/t/test_ypmatch.py @@ -0,0 +1,8 @@ +import pytest + + +class TestYpmatch: + # Actually requires ypcat + @pytest.mark.complete("ypmatch foo ", require_cmd=True) + def test_1(self, completion): + assert completion diff --git a/test/t/test_yum.py b/test/t/test_yum.py new file mode 100644 index 0000000..5dd1eba --- /dev/null +++ b/test/t/test_yum.py @@ -0,0 +1,7 @@ +import pytest + + +class TestYum: + @pytest.mark.complete("yum -", require_cmd=True) + def test_1(self, completion): + assert completion diff --git a/test/t/test_yum_arch.py b/test/t/test_yum_arch.py new file mode 100644 index 0000000..9bbc38f --- /dev/null +++ b/test/t/test_yum_arch.py @@ -0,0 +1,8 @@ +import pytest + + +@pytest.mark.bashcomp(cmd="yum-arch") +class TestYumArch: + @pytest.mark.complete("yum-arch -") + def test_1(self, completion): + assert completion diff --git a/test/t/test_zopfli.py b/test/t/test_zopfli.py new file mode 100644 index 0000000..e5a71b3 --- /dev/null +++ b/test/t/test_zopfli.py @@ -0,0 +1,15 @@ +import pytest + + +class TestZopfli: + @pytest.mark.complete("zopfli ") + def test_1(self, completion): + assert completion + + @pytest.mark.complete("zopfli ~") + def test_2(self, completion): + assert completion + + @pytest.mark.complete("zopfli -", require_cmd=True) + def test_3(self, completion): + assert completion diff --git a/test/t/test_zopflipng.py b/test/t/test_zopflipng.py new file mode 100644 index 0000000..3ff120f --- /dev/null +++ b/test/t/test_zopflipng.py @@ -0,0 +1,11 @@ +import pytest + + +class TestZopflipng: + @pytest.mark.complete("zopflipng ") + def test_1(self, completion): + assert completion + + @pytest.mark.complete("zopflipng -", require_cmd=True) + def test_2(self, completion): + assert completion diff --git a/test/t/unit/Makefile.am b/test/t/unit/Makefile.am new file mode 100644 index 0000000..3eb652a --- /dev/null +++ b/test/t/unit/Makefile.am @@ -0,0 +1,24 @@ +EXTRA_DIST = \ + test_unit_count_args.py \ + test_unit_expand.py \ + test_unit_expand_tilde_by_ref.py \ + test_unit_filedir.py \ + test_unit_find_unique_completion_pair.py \ + test_unit_get_comp_words_by_ref.py \ + 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_xinetd_services.py + +all: + +clean-local: + $(RM) -R __pycache__ diff --git a/test/t/unit/test_unit_count_args.py b/test/t/unit/test_unit_count_args.py new file mode 100644 index 0000000..56bce2c --- /dev/null +++ b/test/t/unit/test_unit_count_args.py @@ -0,0 +1,66 @@ +import pytest + +from conftest import TestUnitBase, assert_bash_exec + + +@pytest.mark.bashcomp( + cmd=None, ignore_env=r"^[+-](args|COMP_(WORDS|CWORD|LINE|POINT))=" +) +class TestUnitCountArgs(TestUnitBase): + def _test(self, *args, **kwargs): + return self._test_unit("_count_args %s; echo $args", *args, **kwargs) + + def test_1(self, bash): + assert_bash_exec(bash, "COMP_CWORD= _count_args >/dev/null") + + def test_2(self, bash): + """a b| should set args to 1""" + output = self._test(bash, "(a b)", 1, "a b", 3) + assert output == "1" + + def test_3(self, bash): + """a b|c should set args to 1""" + output = self._test(bash, "(a bc)", 1, "a bc", 3) + assert output == "1" + + def test_4(self, bash): + """a b c| should set args to 2""" + output = self._test(bash, "(a b c)", 2, "a b c", 4) + assert output == "2" + + def test_5(self, bash): + """a b| c should set args to 1""" + output = self._test(bash, "(a b c)", 1, "a b c", 3) + assert output == "1" + + def test_6(self, bash): + """a b -c| d should set args to 2""" + output = self._test(bash, "(a b -c d)", 2, "a b -c d", 6) + assert output == "2" + + def test_7(self, bash): + """a b -c d e| with -c arg excluded should set args to 2""" + output = self._test( + bash, "(a b -c d e)", 4, "a b -c d e", 10, arg='"" "@(-c|--foo)"' + ) + assert output == "2" + + def test_8(self, bash): + """a -b -c d e| with -c arg excluded + and -b included should set args to 1""" + output = self._test( + bash, + "(a -b -c d e)", + 4, + "a -b -c d e", + 11, + arg='"" "@(-c|--foo)" "-[b]"', + ) + assert output == "2" + + def test_9(self, bash): + """a -b -c d e| with -b included should set args to 3""" + output = self._test( + bash, "(a -b -c d e)", 4, "a -b -c d e", 11, arg='"" "" "-b"' + ) + assert output == "3" diff --git a/test/t/unit/test_unit_expand.py b/test/t/unit/test_unit_expand.py new file mode 100644 index 0000000..d2a3ebc --- /dev/null +++ b/test/t/unit/test_unit_expand.py @@ -0,0 +1,31 @@ +import pytest + +from conftest import assert_bash_exec + + +@pytest.mark.bashcomp(cmd=None, ignore_env=r"^[+-](cur|COMPREPLY)=") +class TestUnitExpand: + def test_1(self, bash): + assert_bash_exec(bash, "_expand >/dev/null") + + 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 new file mode 100644 index 0000000..17bdedf --- /dev/null +++ b/test/t/unit/test_unit_expand_tilde_by_ref.py @@ -0,0 +1,46 @@ +import pytest + +from conftest import assert_bash_exec + + +@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") + + def test_2(self, bash): + """Test environment non-pollution, detected at teardown.""" + assert_bash_exec( + 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 new file mode 100644 index 0000000..b847efc --- /dev/null +++ b/test/t/unit/test_unit_filedir.py @@ -0,0 +1,235 @@ +import os +import shutil +import sys +import tempfile +from pathlib import Path + +import pytest + +from conftest import assert_bash_exec, assert_complete + + +@pytest.mark.bashcomp(cmd=None, ignore_env=r"^\+COMPREPLY=") +class TestUnitFiledir: + @pytest.fixture(scope="class") + def functions(self, request, bash): + assert_bash_exec( + bash, + "_f() { local cur=$(_get_cword); unset COMPREPLY; _filedir; }; " + "complete -F _f f; " + "complete -F _f -o filenames f2", + ) + assert_bash_exec( + bash, + "_g() { local cur=$(_get_cword); unset COMPREPLY; _filedir e1; }; " + "complete -F _g g", + ) + assert_bash_exec( + bash, + "_fd() { local cur=$(_get_cword); unset COMPREPLY; _filedir -d; };" + "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 == "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 == "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 == "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 == "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 == "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 == "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 == "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 == "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 == "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 == '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 == '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 == '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 == 'f"' + + @pytest.mark.complete(r"fd a\ ", cwd="_filedir") + def test_15(self, functions, completion): + 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_find_unique_completion_pair.py b/test/t/unit/test_unit_find_unique_completion_pair.py new file mode 100644 index 0000000..25cf9d3 --- /dev/null +++ b/test/t/unit/test_unit_find_unique_completion_pair.py @@ -0,0 +1,55 @@ +import pytest + +from conftest import find_unique_completion_pair + + +@pytest.mark.bashcomp(cmd=None) +class TestUnitFindUniqueCompletionPair: + def _test(self, inp: str, exp: str) -> None: + res = find_unique_completion_pair(inp.split()) + if exp: + part, cont = exp.split() + assert res == (part, part + cont) + else: + assert not exp + + def test_1(self): + self._test("a", "") + + def test_2(self): + self._test("ab", "a b") + + def test_3(self): + self._test("ab ab ab", "a b") + + def test_4(self): + self._test("a ab abcd abc", "") + + def test_5(self): + self._test("user1 user2", "") + + def test_6(self): + self._test("root username1 username2", "ro ot") + + def test_7(self): + self._test("root username21 username2", "ro ot") + + def test_8(self): + self._test( + "long_user_name lang_user_name long_usor_name", "lang_us er_name" + ) + + def test_9(self): + self._test( + "lang_user_name1 long_user_name lang_user_name long_usor_name", + "long_use r_name", + ) + + def test_10(self): + self._test("root username", "user name") + + def test_11(self): + self._test("a aladin", "ala din") + + def test_12(self): + self._test("ala aladin", "alad in") 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 new file mode 100644 index 0000000..b6498fa --- /dev/null +++ b/test/t/unit/test_unit_get_comp_words_by_ref.py @@ -0,0 +1,260 @@ +import pytest + +from conftest import TestUnitBase, assert_bash_exec + + +@pytest.mark.bashcomp( + 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-}", + bash, + *args, + **kwargs + ) + return output.strip() + + def test_1(self, bash): + 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|""" + output = self._test(bash, "(a b)", 1, "a b", 3) + assert output == "b,a" + + def test_3(self, bash): + """a |""" + output = self._test(bash, "(a)", 1, "a ", 2) + assert output == ",a" + + def test_4(self, bash): + """|a""" + output = self._test(bash, "(a)", 0, "a", 0) + assert output == "," + + def test_5(self, bash): + """|a """ + output = self._test(bash, "(a)", 0, "a ", 0) + assert output == "," + + def test_6(self, bash): + """ | a """ + output = self._test(bash, "(a)", 0, " a ", 1) + assert output.strip() == "," + + def test_7(self, bash): + """a b |""" + output = self._test(bash, "(a b '')", 2, "a b ", 4) + assert output == ",b" + + def test_8(self, bash): + """a b | with WORDBREAKS -= :""" + output = self._test(bash, "(a b '')", 2, "a b ", 4, arg="-n :") + assert output == ",b" + + def test_9(self, bash): + """a b|c""" + output = self._test(bash, "(a bc)", 1, "a bc", 3) + assert output == "b,a" + + def test_10(self, bash): + """a | b""" + output = self._test(bash, "(a b)", 1, "a b", 2) + assert output == ",a" + + def test_11(self, bash): + r"""a b\ c|""" + output = self._test(bash, r"(a 'b\ c')", 1, r"a b\ c", 6) + assert output == r"b\ c,a" + + def test_12(self, bash): + r"""a\ b a\ b|""" + output = self._test(bash, r"('a\ b' 'a\ b')", 1, r"a\ b a\ b", 9) + assert output == r"a\ b,a\ b" + + def test_13(self, bash): + r"""a b\| c""" + output = self._test(bash, r"(a 'b\ c')", 1, r"a b\ c", 4) + assert output == r"b\,a" + + def test_14(self, bash): + r"""a "b\|""" + output = self._test(bash, "(a '\"b')", 1, 'a "b\\', 5) + assert output == r'"b\,a' + + def test_15(self, bash): + """a 'b c|""" + output = self._test(bash, '(a "\'b c")', 1, "a 'b c", 6) + assert output == "'b c,a" + + def test_16(self, bash): + """a "b c|""" + output = self._test(bash, r'(a "\"b c")', 1, 'a "b c', 6) + assert output == '"b c,a' + + def test_17(self, bash): + """a b:c| with WORDBREAKS += :""" + assert_bash_exec(bash, "add_comp_wordbreak_char :") + output = self._test(bash, "(a b : c)", 3, "a b:c", 5) + assert output == "c,:" + + def test_18(self, bash): + """a b:c| with WORDBREAKS -= :""" + output = self._test(bash, "(a b : c)", 3, "a b:c", 5, arg="-n :") + assert output == "b:c,a" + + def test_19(self, bash): + """a b c:| with WORDBREAKS -= :""" + output = self._test(bash, "(a b c :)", 3, "a b c:", 6, arg="-n :") + assert output == "c:,b" + + def test_20(self, bash): + r"""a b:c | with WORDBREAKS -= :""" + output = self._test(bash, "(a b : c '')", 4, "a b:c ", 6, arg="-n :") + assert output == ",b:c" + + def test_21(self, bash): + """a :| with WORDBREAKS -= :""" + output = self._test(bash, "(a :)", 1, "a :", 3, arg="-n :") + assert output == ":,a" + + def test_22(self, bash): + """a b::| with WORDBREAKS -= :""" + output = self._test(bash, "(a b ::)", 2, "a b::", 5, arg="-n :") + assert output == "b::,a" + + def test_23(self, bash): + """a -n| + + This test makes sure `_get_cword' doesn't use `echo' to return its + value, because -n might be interpreted by `echo' and thus woud not + be returned. + """ + output = self._test(bash, "(a -n)", 1, "a -n", 4) + assert output == "-n,a" + + def test_24(self, bash): + """a b>c|""" + output = self._test(bash, r"(a b \> c)", 3, "a b>c", 5) + assert output.startswith("c,") + + def test_25(self, bash): + """a b=c|""" + output = self._test(bash, "(a b = c)", 3, "a b=c", 5) + assert output.startswith("c,") + + def test_26(self, bash): + """a *|""" + output = self._test(bash, r"(a \*)", 1, "a *", 4) + assert output == "*,a" + + def test_27(self, bash): + """a $(b c|""" + output = self._test(bash, "(a '$(b c')", 1, "a $(b c", 7) + assert output == "$(b c,a" + + def test_28(self, bash): + r"""a $(b c\ d|""" + output = self._test(bash, r"(a '$(b c\ d')", 1, r"a $(b c\ d", 10) + assert output == r"$(b c\ d,a" + + def test_29(self, bash): + """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 new file mode 100644 index 0000000..0b56d16 --- /dev/null +++ b/test/t/unit/test_unit_get_cword.py @@ -0,0 +1,154 @@ +import pexpect +import pytest + +from conftest import PS1, TestUnitBase, assert_bash_exec + + +@pytest.mark.bashcomp( + 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, + "COMP_WORDS=() COMP_CWORD= COMP_LINE= COMP_POINT= " + "_get_cword >/dev/null", + ) + + def test_2(self, bash): + """a b| should return b""" + output = self._test(bash, "(a b)", 1, "a b", 3) + assert output == "b" + + def test_3(self, bash): + """a | should return nothing""" + output = self._test(bash, "(a)", 1, "a ", 2) + assert not output + + def test_4(self, bash): + """a b | should return nothing""" + output = self._test(bash, "(a b '')", 2, "a b ", 4) + assert not output + + def test_5(self, bash): + """a b | with WORDBREAKS -= : should return nothing""" + output = self._test(bash, "(a b '')", 2, "a b ", 4, arg=":") + assert not output + + def test_6(self, bash): + """a b|c should return b""" + output = self._test(bash, "(a bc)", 1, "a bc", 3) + assert output == "b" + + def test_7(self, bash): + r"""a b\ c| should return b\ c""" + output = self._test(bash, r"(a 'b\ c')", 1, r"a b\ c", 6) + assert output == r"b\ c" + + def test_8(self, bash): + r"""a b\| c should return b\ """ + output = self._test(bash, r"(a 'b\ c')", 1, r"a b\ c", 4) + assert output == "b\\" + + def test_9(self, bash): + r"""a "b\| should return "b\ """ + output = self._test(bash, "(a '\"b\\')", 1, r"a \"b\\", 5) + assert output == '"b\\' + + def test_10(self, bash): + r"""a 'b c| should return 'b c""" + output = self._test(bash, '(a "\'b c")', 1, "a 'b c", 6) + assert output == "'b c" + + def test_11(self, bash): + r"""a "b c| should return "b c""" + output = self._test(bash, "(a '\"b c')", 1, 'a "b c', 6) + assert output == '"b c' + + def test_12(self, bash): + """a b:c| with WORDBREAKS += : should return c""" + assert_bash_exec(bash, "add_comp_wordbreak_char :") + output = self._test(bash, "(a b : c)", 3, "a b:c", 5) + assert output == "c" + + def test_13(self, bash): + """a b:c| with WORDBREAKS -= : should return b:c""" + assert_bash_exec(bash, "add_comp_wordbreak_char :") + output = self._test(bash, "(a b : c)", 3, "a b:c", 5, arg=":") + assert output == "b:c" + + def test_14(self, bash): + """a b c:| with WORDBREAKS -= : should return c:""" + assert_bash_exec(bash, "add_comp_wordbreak_char :") + output = self._test(bash, "(a b c :)", 3, "a b c:", 6, arg=":") + assert output == "c:" + + def test_15(self, bash): + """a :| with WORDBREAKS -= : should return :""" + assert_bash_exec(bash, "add_comp_wordbreak_char :") + output = self._test(bash, "(a :)", 1, "a :", 3, arg=":") + assert output == ":" + + def test_16(self, bash): + """a b::| with WORDBREAKS -= : should return b::""" + assert_bash_exec(bash, "add_comp_wordbreak_char :") + output = self._test(bash, "(a b::)", 1, "a b::", 5, arg=":") + assert output == "b::" + + def test_17(self, bash): + """ + a -n| should return -n + + This test makes sure `_get_cword' doesn't use `echo' to return its + value, because -n might be interpreted by `echo' and thus woud not + be returned. + """ + output = self._test(bash, "(a -n)", 1, "a -n", 4) + assert output == "-n" + + def test_18(self, bash): + """a b>c| should return c""" + output = self._test(bash, r"(a b \> c)", 3, "a b>c", 5) + assert output == "c" + + def test_19(self, bash): + """a b=c| should return c""" + output = self._test(bash, "(a b = c)", 3, "a b=c", 5) + assert output == "c" + + def test_20(self, bash): + """a *| should return *""" + output = self._test(bash, r"(a \*)", 1, "a *", 4) + assert output == "*" + + def test_21(self, bash): + """a $(b c| should return $(b c""" + output = self._test(bash, r"(a '$(b c')", 1, "a $(b c", 7) + assert output == "$(b c" + + def test_22(self, bash): + r"""a $(b c\ d| should return $(b c\ d""" + output = self._test(bash, r"(a '$(b c\ d')", 1, r"a $(b c\ d", 10) + assert output == r"$(b c\ d" + + def test_23(self, bash): + """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 new file mode 100644 index 0000000..64a5a79 --- /dev/null +++ b/test/t/unit/test_unit_init_completion.py @@ -0,0 +1,34 @@ +import pytest + +from conftest import TestUnitBase, assert_bash_exec, assert_complete + + +@pytest.mark.bashcomp( + cmd=None, + ignore_env=r"^[+-](COMP(_(WORDS|CWORD|LINE|POINT)|REPLY)|" + r"cur|cword|words)=", +) +class TestUnitInitCompletion(TestUnitBase): + def test_1(self, bash): + """Test environment non-pollution, detected at teardown.""" + assert_bash_exec( + bash, + "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 + ) + 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_ip_addresses.py b/test/t/unit/test_unit_ip_addresses.py new file mode 100644 index 0000000..8120c88 --- /dev/null +++ b/test/t/unit/test_unit_ip_addresses.py @@ -0,0 +1,49 @@ +import pytest + +from conftest import assert_bash_exec, in_container + + +@pytest.mark.bashcomp(cmd=None, ignore_env=r"^\+COMPREPLY=") +class TestUnitIpAddresses: + @pytest.fixture(scope="class") + def functions(self, request, bash): + assert_bash_exec( + bash, + "_ia() { local cur=$(_get_cword);unset COMPREPLY;" + "_ip_addresses; }", + ) + assert_bash_exec(bash, "complete -F _ia ia") + assert_bash_exec( + bash, + "_iaa() { local cur=$(_get_cword);unset COMPREPLY;" + "_ip_addresses -a; }", + ) + assert_bash_exec(bash, "complete -F _iaa iaa") + assert_bash_exec( + bash, + " _ia6() { local cur=$(_get_cword);unset COMPREPLY;" + "_ip_addresses -6; }", + ) + assert_bash_exec(bash, "complete -F _ia6 ia6") + + def test_1(self, bash): + assert_bash_exec(bash, "_ip_addresses") + + @pytest.mark.complete("iaa ") + def test_2(self, functions, completion): + """_ip_addresses -a should complete ip addresses.""" + assert completion + assert all("." in x or ":" in x for x in completion) + + @pytest.mark.complete("ia ") + def test_3(self, functions, completion): + """_ip_addresses should complete ipv4 addresses.""" + assert completion + assert all("." in x for x in completion) + + @pytest.mark.xfail(in_container(), reason="Probably fails in a container") + @pytest.mark.complete("ia6 ") + def test_4(self, functions, completion): + """_ip_addresses -6 should complete ipv6 addresses.""" + assert completion + assert all(":" in x for x in completion) 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 0000000..ac5205e --- /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 new file mode 100644 index 0000000..c5488e3 --- /dev/null +++ b/test/t/unit/test_unit_longopt.py @@ -0,0 +1,52 @@ +# Based on work by Stephen Gildea, October 2010. + +import pytest + +from conftest import assert_bash_exec + + +@pytest.mark.bashcomp(cmd=None, ignore_env=r"^\+COMPREPLY=") +class TestUnitLongopt: + @pytest.fixture(scope="class") + 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): + """First long option should be included""" + assert completion + assert all( + x in completion for x in "--quiet --recursive --text".split() + ) + + @pytest.mark.complete("_grephelp -") + def test_2(self, functions, completion): + """Only long options should be included""" + assert completion + assert all(x.startswith("--") for x in completion) + + @pytest.mark.complete("_grephelp --") + def test_3(self, functions, completion): + """Should have both ones ending with a = and ones not""" + 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_parse_help.py b/test/t/unit/test_unit_parse_help.py new file mode 100644 index 0000000..4a02155 --- /dev/null +++ b/test/t/unit/test_unit_parse_help.py @@ -0,0 +1,183 @@ +# Based on work by Stephen Gildea, October 2010. + +import pytest + +from conftest import assert_bash_exec + + +@pytest.mark.bashcomp(cmd=None, ignore_env=r"^\+declare -f fn$") +class TestUnitParseHelp: + def test_1(self, bash): + assert_bash_exec(bash, "fn() { echo; }") + output = assert_bash_exec(bash, "_parse_help fn") + assert not output + + def test_2(self, bash): + assert_bash_exec(bash, "fn() { echo 'no dashes here'; }") + output = assert_bash_exec(bash, "_parse_help fn") + assert not output + + def test_3(self, bash): + assert_bash_exec(bash, "fn() { echo 'internal-dash'; }") + output = assert_bash_exec(bash, "_parse_help fn") + assert not output + + def test_4(self, bash): + assert_bash_exec(bash, "fn() { echo 'no -leading-dashes'; }") + output = assert_bash_exec(bash, "_parse_help fn") + assert not output + + def test_5(self, bash): + assert_bash_exec(bash, "fn() { echo '-one dash'; }") + output = assert_bash_exec(bash, "_parse_help fn", want_output=True) + assert output.split() == "-one".split() + + def test_6(self, bash): + assert_bash_exec(bash, "fn() { echo ' -space dash'; }") + output = assert_bash_exec(bash, "_parse_help fn", want_output=True) + assert output.split() == "-space".split() + + def test_7(self, bash): + assert_bash_exec(bash, "fn() { echo '-one -two dashes'; }") + output = assert_bash_exec(bash, "_parse_help fn", want_output=True) + assert output.split() == "-one".split() + + def test_8(self, bash): + assert_bash_exec(bash, "fn() { echo '-one,-t dashes'; }") + output = assert_bash_exec(bash, "_parse_help fn", want_output=True) + assert output.split() == "-one".split() + + def test_9(self, bash): + assert_bash_exec(bash, "fn() { echo '-one dash-inside'; }") + output = assert_bash_exec(bash, "_parse_help fn", want_output=True) + assert output.split() == "-one".split() + + def test_10(self, bash): + """Test value not included in completion.""" + assert_bash_exec(bash, "fn() { echo '--long-arg=value'; }") + output = assert_bash_exec(bash, "_parse_help fn", want_output=True) + assert output.split() == "--long-arg=".split() + + def test_11(self, bash): + """Test -value not seen as option.""" + assert_bash_exec(bash, "fn() { echo '--long-arg=-value'; }") + output = assert_bash_exec(bash, "_parse_help fn", want_output=True) + assert output.split() == "--long-arg=".split() + + def test_12(self, bash): + assert_bash_exec(bash, "fn() { echo '--long-arg=-value,--opt2=val'; }") + output = assert_bash_exec(bash, "_parse_help fn", want_output=True) + assert output.split() == "--long-arg=".split() + + def test_13(self, bash): + assert_bash_exec(bash, "fn() { echo '-m,--mirror'; }") + output = assert_bash_exec(bash, "_parse_help fn", want_output=True) + assert output.split() == "--mirror".split() + + def test_14(self, bash): + assert_bash_exec(bash, "fn() { echo '-T/--upload-file'; }") + output = assert_bash_exec(bash, "_parse_help fn", want_output=True) + assert output.split() == "--upload-file".split() + + def test_15(self, bash): + assert_bash_exec(bash, "fn() { echo '-T|--upload-file'; }") + output = assert_bash_exec(bash, "_parse_help fn", want_output=True) + assert output.split() == "--upload-file".split() + + def test_16(self, bash): + assert_bash_exec(bash, "fn() { echo '-f, -F, --foo'; }") + output = assert_bash_exec(bash, "_parse_help fn", want_output=True) + assert output.split() == "--foo".split() + + def test_17(self, bash): + assert_bash_exec(bash, "fn() { echo '--foo[=bar]'; }") + output = assert_bash_exec(bash, "_parse_help fn", want_output=True) + assert output.split() == "--foo".split() + + def test_18(self, bash): + assert_bash_exec(bash, "fn() { echo '--foo=<bar>'; }") + output = assert_bash_exec(bash, "_parse_help fn", want_output=True) + assert output.split() == "--foo=".split() + + def test_19(self, bash): + assert_bash_exec(bash, "fn() { echo '--foo={bar,quux}'; }") + output = assert_bash_exec(bash, "_parse_help fn", want_output=True) + assert output.split() == "--foo=".split() + + def test_20(self, bash): + assert_bash_exec(bash, "fn() { echo '--[no]foo'; }") + output = assert_bash_exec(bash, "_parse_help fn", want_output=True) + assert output.split() == "--foo --nofoo".split() + + def test_21(self, bash): + assert_bash_exec(bash, "fn() { echo '--[no-]bar[=quux]'; }") + output = assert_bash_exec(bash, "_parse_help fn", want_output=True) + assert output.split() == "--bar --no-bar".split() + + def test_22(self, bash): + assert_bash_exec(bash, "fn() { echo '--[no-]bar=quux'; }") + output = assert_bash_exec(bash, "_parse_help fn", want_output=True) + assert output.split() == "--bar= --no-bar=".split() + + def test_23(self, bash): + assert_bash_exec(bash, "fn() { echo '--[dont-]foo'; }") + output = assert_bash_exec(bash, "_parse_help fn", want_output=True) + assert output.split() == "--foo --dont-foo".split() + + def test_24(self, bash): + assert_bash_exec(bash, "fn() { echo '-[dont]x --[dont]yy'; }") + output = assert_bash_exec(bash, "_parse_help fn", want_output=True) + assert output.split() == "--yy --dontyy".split() + + def test_25(self, bash): + assert_bash_exec(bash, "fn() { echo '-f FOO, --foo=FOO'; }") + output = assert_bash_exec(bash, "_parse_help fn", want_output=True) + assert output.split() == "--foo=".split() + + def test_26(self, bash): + assert_bash_exec(bash, "fn() { echo '-f [FOO], --foo[=FOO]'; }") + output = assert_bash_exec(bash, "_parse_help fn", want_output=True) + assert output.split() == "--foo".split() + + def test_27(self, bash): + assert_bash_exec(bash, "fn() { echo '--foo.'; }") + output = assert_bash_exec(bash, "_parse_help fn", want_output=True) + assert output.split() == "--foo".split() + + def test_28(self, bash): + assert_bash_exec(bash, "fn() { echo '-f or --foo'; }") + output = assert_bash_exec(bash, "_parse_help fn", want_output=True) + assert output.split() == "--foo".split() + + def test_29(self, bash): + """Test parsing from stdin.""" + output = assert_bash_exec( + bash, "echo '-f or --foo' | _parse_help -", want_output=True + ) + assert output.split() == "--foo".split() + + def test_30(self, bash): + """More than two dashes should not be treated as options.""" + assert_bash_exec( + bash, r"fn() { printf '%s\n' $'----\n---foo\n----- bar'; }" + ) + output = assert_bash_exec(bash, "_parse_help fn") + assert not output + + def test_31(self, bash): + assert_bash_exec( + bash, + r"fn() { printf '%s\n' " + r"'-F ERROR_FORMAT, --error-format ERROR_FORMAT'; }", + ) + output = assert_bash_exec(bash, "_parse_help fn", want_output=True) + assert output.split() == "--error-format".split() + + def test_32(self, bash): + assert_bash_exec( + bash, + r"fn() { printf '%s\n' " + r"'-e CODE1,CODE2.. --exclude=CODE1,CODE2..'; }", + ) + output = assert_bash_exec(bash, "_parse_help fn", want_output=True) + assert output.split() == "--exclude=".split() diff --git a/test/t/unit/test_unit_parse_usage.py b/test/t/unit/test_unit_parse_usage.py new file mode 100644 index 0000000..f0cb711 --- /dev/null +++ b/test/t/unit/test_unit_parse_usage.py @@ -0,0 +1,69 @@ +import pytest + +from conftest import assert_bash_exec + + +@pytest.mark.bashcomp(cmd=None, ignore_env=r"^\+declare -f fn$") +class TestUnitParseUsage: + def test_1(self, bash): + assert_bash_exec(bash, "fn() { echo; }") + output = assert_bash_exec(bash, "_parse_usage fn") + assert not output + + def test_2(self, bash): + assert_bash_exec(bash, "fn() { echo 'no dashes here'; }") + output = assert_bash_exec(bash, "_parse_usage fn") + assert not output + + def test_3(self, bash): + assert_bash_exec(bash, "fn() { echo 'foo [-f]'; }") + output = assert_bash_exec(bash, "_parse_usage fn", want_output=True) + assert output.split() == "-f".split() + + def test_4(self, bash): + assert_bash_exec(bash, "fn() { echo 'bar [-aBcD] [-e X]'; }") + output = assert_bash_exec(bash, "_parse_usage fn", want_output=True) + assert output.split() == "-a -B -c -D -e".split() + + def test_5(self, bash): + assert_bash_exec(bash, "fn() { echo '[-[XyZ]] [--long=arg]'; }") + output = assert_bash_exec(bash, "_parse_usage fn", want_output=True) + assert output.split() == "-X -y -Z --long=".split() + + def test_6(self, bash): + assert_bash_exec(bash, "fn() { echo '[-s|--long]'; }") + output = assert_bash_exec(bash, "_parse_usage fn", want_output=True) + assert output.split() == "--long".split() + + def test_7(self, bash): + assert_bash_exec(bash, "fn() { echo '[-s, --long=arg]'; }") + output = assert_bash_exec(bash, "_parse_usage fn", want_output=True) + assert output.split() == "--long=".split() + + def test_8(self, bash): + assert_bash_exec(bash, "fn() { echo '[--long/-s] [-S/--longer]'; }") + output = assert_bash_exec(bash, "_parse_usage fn", want_output=True) + assert output.split() == "--long --longer".split() + + def test_9(self, bash): + assert_bash_exec(bash, "fn() { echo '[ -a ] [ -b foo ]'; }") + output = assert_bash_exec(bash, "_parse_usage fn", want_output=True) + assert output.split() == "-a -b".split() + + def test_10(self, bash): + assert_bash_exec(bash, "fn() { echo '[ -a | --aa ]'; }") + output = assert_bash_exec(bash, "_parse_usage fn", want_output=True) + assert output.split() == "--aa".split() + + def test_11(self, bash): + assert_bash_exec( + bash, "fn() { echo ----; echo ---foo; echo '----- bar'; }" + ) + output = assert_bash_exec(bash, "_parse_usage fn") + assert not output + + def test_12(self, bash): + output = assert_bash_exec( + bash, "echo '[-duh]' | _parse_usage -", want_output=True + ) + assert output.split() == "-d -u -h".split() diff --git a/test/t/unit/test_unit_quote.py b/test/t/unit/test_unit_quote.py new file mode 100644 index 0000000..b280bd6 --- /dev/null +++ b/test/t/unit/test_unit_quote.py @@ -0,0 +1,36 @@ +import pytest + +from conftest import TestUnitBase, assert_bash_exec + + +@pytest.mark.bashcomp(cmd=None) +class TestUnitQuote(TestUnitBase): + def test_1(self, bash): + output = assert_bash_exec( + bash, 'quote "a b"', want_output=True, want_newline=False + ) + assert output.strip() == "'a b'" + + def test_2(self, bash): + output = assert_bash_exec( + bash, 'quote "a b"', want_output=True, want_newline=False + ) + assert output.strip() == "'a b'" + + def test_3(self, bash): + output = assert_bash_exec( + bash, 'quote " a "', want_output=True, want_newline=False + ) + assert output.strip() == "' a '" + + def test_4(self, bash): + output = assert_bash_exec( + bash, "quote \"a'b'c\"", want_output=True, want_newline=False + ) + assert output.strip() == r"'a'\''b'\''c'" + + def test_5(self, bash): + output = assert_bash_exec( + bash, 'quote "a\'"', want_output=True, want_newline=False + ) + assert output.strip() == r"'a'\'''" 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 0000000..e2b437e --- /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_tilde.py b/test/t/unit/test_unit_tilde.py new file mode 100644 index 0000000..35a4e4c --- /dev/null +++ b/test/t/unit/test_unit_tilde.py @@ -0,0 +1,42 @@ +import pytest + +from conftest import assert_bash_exec + + +@pytest.mark.bashcomp(cmd=None, ignore_env=r"^\+COMPREPLY=") +class TestUnitTilde: + def test_1(self, bash): + assert_bash_exec(bash, "_tilde >/dev/null") + + def test_2(self, bash): + """Test environment non-pollution, detected at teardown.""" + assert_bash_exec( + bash, 'foo() { local aa="~"; _tilde "$aa"; }; foo; unset foo' + ) + + def test_3(self, bash): + """Test for https://bugs.debian.org/766163""" + assert_bash_exec(bash, "_tilde ~-o") + + def _test_part_full(self, bash, part, full): + res = ( + assert_bash_exec( + bash, + '_tilde "~%s"; echo "${COMPREPLY[@]}"' % part, + want_output=True, + ) + .strip() + .split() + ) + assert res + assert res[0] == "~%s" % full + + def test_4(self, bash, part_full_user): + """~full should complete to ~full unmodified.""" + _, full = part_full_user + self._test_part_full(bash, full, full) + + def test_5(self, bash, part_full_user): + """~part should complete to ~full.""" + part, full = part_full_user + self._test_part_full(bash, part, full) diff --git a/test/t/unit/test_unit_variables.py b/test/t/unit/test_unit_variables.py new file mode 100644 index 0000000..d62bc4a --- /dev/null +++ b/test/t/unit/test_unit_variables.py @@ -0,0 +1,41 @@ +import pytest + +from conftest import assert_bash_exec + + +@pytest.mark.bashcomp(cmd=None, ignore_env=r"^[+-](___var|assoc[12])=") +class TestUnitVariables: + @pytest.fixture(scope="class") + def functions(self, request, bash): + assert_bash_exec(bash, "unset assoc1 && declare -A assoc1=([idx]=1)") + assert_bash_exec( + bash, "unset assoc2 && declare -A assoc2=([idx1]=1 [idx2]=2)" + ) + assert_bash_exec(bash, "unset ${!___v*} && declare ___var=''") + request.addfinalizer( + lambda: assert_bash_exec(bash, "unset ___var assoc1 assoc2") + ) + + @pytest.mark.complete(": $___v") + def test_simple_variable_name(self, functions, completion): + assert completion == "ar" + + @pytest.mark.complete(": ${assoc1[") + def test_single_array_index(self, functions, completion): + assert completion == "idx]}" + + @pytest.mark.complete(": ${assoc2[") + def test_multiple_array_indexes(self, functions, completion): + assert completion == "${assoc2[idx1]} ${assoc2[idx2]}".split() + + @pytest.mark.complete(": ${assoc1[bogus]") + def test_closing_curly_after_square(self, functions, completion): + assert completion == "}" + + @pytest.mark.complete(": ${assoc1[@") + def test_closing_brackets_after_at(self, functions, completion): + assert completion == "]}" + + @pytest.mark.complete(": ${#___v") + def test_hash_prefix(self, functions, completion): + 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 0000000..7a90cb7 --- /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 0000000..eb8398e --- /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 |