summaryrefslogtreecommitdiffstats
path: root/test/t
diff options
context:
space:
mode:
Diffstat (limited to 'test/t')
-rw-r--r--test/t/Makefile.am698
-rw-r--r--test/t/conftest.py637
-rw-r--r--test/t/test_2to3.py11
-rw-r--r--test/t/test_7z.py33
-rw-r--r--test/t/test_a2ps.py11
-rw-r--r--test/t/test_a2x.py11
-rw-r--r--test/t/test_abook.py7
-rw-r--r--test/t/test_aclocal.py11
-rw-r--r--test/t/test_acpi.py7
-rw-r--r--test/t/test_acroread.py7
-rw-r--r--test/t/test_adb.py11
-rw-r--r--test/t/test_add_members.py7
-rw-r--r--test/t/test_alias.py21
-rw-r--r--test/t/test_alpine.py7
-rw-r--r--test/t/test_animate.py7
-rw-r--r--test/t/test_ant.py35
-rw-r--r--test/t/test_apache2ctl.py7
-rw-r--r--test/t/test_appdata_validate.py12
-rw-r--r--test/t/test_apt_build.py8
-rw-r--r--test/t/test_apt_cache.py17
-rw-r--r--test/t/test_apt_get.py16
-rw-r--r--test/t/test_aptitude.py23
-rw-r--r--test/t/test_arch.py8
-rw-r--r--test/t/test_arp.py13
-rw-r--r--test/t/test_arping.py11
-rw-r--r--test/t/test_arpspoof.py12
-rw-r--r--test/t/test_asciidoc.py11
-rw-r--r--test/t/test_aspell.py7
-rw-r--r--test/t/test_autoconf.py7
-rw-r--r--test/t/test_autoheader.py7
-rw-r--r--test/t/test_automake.py11
-rw-r--r--test/t/test_autoreconf.py7
-rw-r--r--test/t/test_autorpm.py7
-rw-r--r--test/t/test_autoscan.py11
-rw-r--r--test/t/test_autossh.py7
-rw-r--r--test/t/test_autoupdate.py7
-rw-r--r--test/t/test_avctrl.py7
-rw-r--r--test/t/test_awk.py11
-rw-r--r--test/t/test_badblocks.py12
-rw-r--r--test/t/test_base64.py11
-rw-r--r--test/t/test_bash.py7
-rw-r--r--test/t/test_bc.py7
-rw-r--r--test/t/test_bind.py11
-rw-r--r--test/t/test_bison.py7
-rw-r--r--test/t/test_bk.py7
-rw-r--r--test/t/test_bmake.py7
-rw-r--r--test/t/test_brctl.py7
-rw-r--r--test/t/test_btdownloadcurses_py.py8
-rw-r--r--test/t/test_btdownloadgui_py.py8
-rw-r--r--test/t/test_btdownloadheadless_py.py8
-rw-r--r--test/t/test_bts.py11
-rw-r--r--test/t/test_bzip2.py15
-rw-r--r--test/t/test_cal.py11
-rw-r--r--test/t/test_cancel.py34
-rw-r--r--test/t/test_cardctl.py7
-rw-r--r--test/t/test_carton.py11
-rw-r--r--test/t/test_cat.py11
-rw-r--r--test/t/test_cc.py7
-rw-r--r--test/t/test_ccache.py27
-rw-r--r--test/t/test_ccze.py19
-rw-r--r--test/t/test_cd.py26
-rw-r--r--test/t/test_cdrecord.py7
-rw-r--r--test/t/test_cfagent.py7
-rw-r--r--test/t/test_cfrun.py7
-rw-r--r--test/t/test_chage.py11
-rw-r--r--test/t/test_change_pw.py8
-rw-r--r--test/t/test_check_db.py7
-rw-r--r--test/t/test_check_perms.py7
-rw-r--r--test/t/test_checksec.py7
-rw-r--r--test/t/test_chfn.py7
-rw-r--r--test/t/test_chgrp.py7
-rw-r--r--test/t/test_chkconfig.py15
-rw-r--r--test/t/test_chmod.py25
-rw-r--r--test/t/test_chown.py82
-rw-r--r--test/t/test_chpasswd.py7
-rw-r--r--test/t/test_chromium_browser.py25
-rw-r--r--test/t/test_chronyc.py11
-rw-r--r--test/t/test_chroot.py16
-rw-r--r--test/t/test_chrpath.py11
-rw-r--r--test/t/test_chsh.py15
-rw-r--r--test/t/test_ci.py7
-rw-r--r--test/t/test_ciptool.py7
-rw-r--r--test/t/test_civclient.py7
-rw-r--r--test/t/test_civserver.py7
-rw-r--r--test/t/test_cksfv.py7
-rw-r--r--test/t/test_cleanarch.py8
-rw-r--r--test/t/test_clisp.py7
-rw-r--r--test/t/test_clone_member.py7
-rw-r--r--test/t/test_co.py7
-rw-r--r--test/t/test_colordiff.py11
-rw-r--r--test/t/test_compare.py7
-rw-r--r--test/t/test_compgen.py7
-rw-r--r--test/t/test_complete.py11
-rw-r--r--test/t/test_composite.py7
-rw-r--r--test/t/test_config_list.py7
-rw-r--r--test/t/test_configure.py17
-rw-r--r--test/t/test_conjure.py7
-rw-r--r--test/t/test_convert.py15
-rw-r--r--test/t/test_cowsay.py7
-rw-r--r--test/t/test_cp.py11
-rw-r--r--test/t/test_cpan2dist.py9
-rw-r--r--test/t/test_cpio.py12
-rw-r--r--test/t/test_cplusplus.py8
-rw-r--r--test/t/test_cppcheck.py31
-rw-r--r--test/t/test_createdb.py11
-rw-r--r--test/t/test_createuser.py11
-rw-r--r--test/t/test_crontab.py16
-rw-r--r--test/t/test_cryptsetup.py11
-rw-r--r--test/t/test_csplit.py11
-rw-r--r--test/t/test_curl.py28
-rw-r--r--test/t/test_cut.py11
-rw-r--r--test/t/test_cvs.py20
-rw-r--r--test/t/test_cvsps.py12
-rw-r--r--test/t/test_date.py11
-rw-r--r--test/t/test_dcop.py7
-rw-r--r--test/t/test_dd.py17
-rw-r--r--test/t/test_declare.py20
-rw-r--r--test/t/test_deja_dup.py12
-rw-r--r--test/t/test_desktop_file_validate.py12
-rw-r--r--test/t/test_df.py11
-rw-r--r--test/t/test_dfutool.py7
-rw-r--r--test/t/test_dhclient.py7
-rw-r--r--test/t/test_dict.py7
-rw-r--r--test/t/test_diff.py7
-rw-r--r--test/t/test_dir.py11
-rw-r--r--test/t/test_display.py11
-rw-r--r--test/t/test_dmesg.py7
-rw-r--r--test/t/test_dmypy.py14
-rw-r--r--test/t/test_dnssec_keygen.py80
-rw-r--r--test/t/test_dnsspoof.py7
-rw-r--r--test/t/test_dot.py7
-rw-r--r--test/t/test_dpkg.py15
-rw-r--r--test/t/test_dpkg_deb.py12
-rw-r--r--test/t/test_dpkg_query.py18
-rw-r--r--test/t/test_dpkg_reconfigure.py8
-rw-r--r--test/t/test_dpkg_source.py8
-rw-r--r--test/t/test_dropdb.py11
-rw-r--r--test/t/test_dropuser.py7
-rw-r--r--test/t/test_dselect.py11
-rw-r--r--test/t/test_dsniff.py7
-rw-r--r--test/t/test_du.py11
-rw-r--r--test/t/test_dumpdb.py8
-rw-r--r--test/t/test_dumpe2fs.py11
-rw-r--r--test/t/test_e2freefrag.py11
-rw-r--r--test/t/test_e2label.py7
-rw-r--r--test/t/test_ebtables.py7
-rw-r--r--test/t/test_ecryptfs_migrate_home.py12
-rw-r--r--test/t/test_eject.py7
-rw-r--r--test/t/test_enscript.py7
-rw-r--r--test/t/test_env.py7
-rw-r--r--test/t/test_eog.py11
-rw-r--r--test/t/test_ether_wake.py18
-rw-r--r--test/t/test_etherwake.py7
-rw-r--r--test/t/test_evince.py22
-rw-r--r--test/t/test_expand.py7
-rw-r--r--test/t/test_explodepkg.py23
-rw-r--r--test/t/test_export.py36
-rw-r--r--test/t/test_faillog.py7
-rw-r--r--test/t/test_fbgs.py7
-rw-r--r--test/t/test_fbi.py7
-rw-r--r--test/t/test_feh.py31
-rw-r--r--test/t/test_file.py11
-rw-r--r--test/t/test_file_roller.py8
-rw-r--r--test/t/test_filefrag.py11
-rw-r--r--test/t/test_filesnarf.py7
-rw-r--r--test/t/test_find.py37
-rw-r--r--test/t/test_find_member.py7
-rw-r--r--test/t/test_finger.py33
-rw-r--r--test/t/test_fio.py15
-rw-r--r--test/t/test_firefox.py12
-rw-r--r--test/t/test_flake8.py17
-rw-r--r--test/t/test_fmt.py9
-rw-r--r--test/t/test_fold.py7
-rw-r--r--test/t/test_freebsd_update.py8
-rw-r--r--test/t/test_freeciv.py7
-rw-r--r--test/t/test_freeciv_server.py8
-rw-r--r--test/t/test_function.py7
-rw-r--r--test/t/test_fusermount.py11
-rw-r--r--test/t/test_g4.py7
-rw-r--r--test/t/test_g77.py7
-rw-r--r--test/t/test_gcc.py64
-rw-r--r--test/t/test_gcj.py7
-rw-r--r--test/t/test_gcl.py7
-rw-r--r--test/t/test_gdb.py14
-rw-r--r--test/t/test_genaliases.py8
-rw-r--r--test/t/test_gendiff.py7
-rw-r--r--test/t/test_genisoimage.py11
-rw-r--r--test/t/test_geoiplookup.py7
-rw-r--r--test/t/test_getconf.py25
-rw-r--r--test/t/test_getent.py18
-rw-r--r--test/t/test_gkrellm.py10
-rw-r--r--test/t/test_gm.py19
-rw-r--r--test/t/test_gmplayer.py7
-rw-r--r--test/t/test_gnatmake.py7
-rw-r--r--test/t/test_gnokii.py11
-rw-r--r--test/t/test_gnome_mplayer.py17
-rw-r--r--test/t/test_gnome_screenshot.py8
-rw-r--r--test/t/test_gpasswd.py11
-rw-r--r--test/t/test_gpc.py7
-rw-r--r--test/t/test_gperf.py7
-rw-r--r--test/t/test_gpg.py7
-rw-r--r--test/t/test_gpg2.py7
-rw-r--r--test/t/test_gpgv.py15
-rw-r--r--test/t/test_gphoto2.py7
-rw-r--r--test/t/test_gplusplus.py8
-rw-r--r--test/t/test_gprof.py7
-rw-r--r--test/t/test_grep.py16
-rw-r--r--test/t/test_groupadd.py11
-rw-r--r--test/t/test_groupdel.py11
-rw-r--r--test/t/test_groupmems.py7
-rw-r--r--test/t/test_groupmod.py11
-rw-r--r--test/t/test_growisofs.py7
-rw-r--r--test/t/test_grpck.py11
-rw-r--r--test/t/test_grub.py7
-rw-r--r--test/t/test_gssdp_discover.py22
-rw-r--r--test/t/test_gzip.py15
-rw-r--r--test/t/test_hciattach.py7
-rw-r--r--test/t/test_hciconfig.py7
-rw-r--r--test/t/test_hcitool.py11
-rw-r--r--test/t/test_hddtemp.py7
-rw-r--r--test/t/test_head.py7
-rw-r--r--test/t/test_hexdump.py7
-rw-r--r--test/t/test_hid2hci.py8
-rw-r--r--test/t/test_host.py7
-rw-r--r--test/t/test_hostname.py7
-rw-r--r--test/t/test_hping2.py11
-rw-r--r--test/t/test_hping3.py7
-rw-r--r--test/t/test_htop.py7
-rw-r--r--test/t/test_htpasswd.py23
-rw-r--r--test/t/test_hunspell.py11
-rw-r--r--test/t/test_hwclock.py7
-rw-r--r--test/t/test_iconv.py21
-rw-r--r--test/t/test_id.py7
-rw-r--r--test/t/test_identify.py7
-rw-r--r--test/t/test_idn.py7
-rw-r--r--test/t/test_ifdown.py14
-rw-r--r--test/t/test_ifstat.py21
-rw-r--r--test/t/test_iftop.py11
-rw-r--r--test/t/test_ifup.py20
-rw-r--r--test/t/test_import.py7
-rw-r--r--test/t/test_influx.py15
-rw-r--r--test/t/test_info.py12
-rw-r--r--test/t/test_inject.py8
-rw-r--r--test/t/test_inotifywait.py15
-rw-r--r--test/t/test_inotifywatch.py15
-rw-r--r--test/t/test_insmod.py7
-rw-r--r--test/t/test_installpkg.py39
-rw-r--r--test/t/test_interdiff.py11
-rw-r--r--test/t/test_invoke_rc_d.py14
-rw-r--r--test/t/test_ionice.py7
-rw-r--r--test/t/test_ip.py15
-rw-r--r--test/t/test_ipcalc.py23
-rw-r--r--test/t/test_iperf.py24
-rw-r--r--test/t/test_iperf3.py20
-rw-r--r--test/t/test_ipmitool.py11
-rw-r--r--test/t/test_ipsec.py7
-rw-r--r--test/t/test_iptables.py7
-rw-r--r--test/t/test_ipv6calc.py11
-rw-r--r--test/t/test_irb.py11
-rw-r--r--test/t/test_iscsiadm.py7
-rw-r--r--test/t/test_isort.py11
-rw-r--r--test/t/test_isql.py8
-rw-r--r--test/t/test_iwconfig.py7
-rw-r--r--test/t/test_iwlist.py7
-rw-r--r--test/t/test_iwpriv.py7
-rw-r--r--test/t/test_iwspy.py7
-rw-r--r--test/t/test_jar.py7
-rw-r--r--test/t/test_jarsigner.py7
-rw-r--r--test/t/test_java.py49
-rw-r--r--test/t/test_javac.py11
-rw-r--r--test/t/test_javadoc.py17
-rw-r--r--test/t/test_javaws.py11
-rw-r--r--test/t/test_jpegoptim.py11
-rw-r--r--test/t/test_jps.py7
-rw-r--r--test/t/test_jq.py30
-rw-r--r--test/t/test_jshint.py11
-rw-r--r--test/t/test_json_xs.py11
-rw-r--r--test/t/test_jsonschema.py13
-rw-r--r--test/t/test_k3b.py11
-rw-r--r--test/t/test_kcov.py16
-rw-r--r--test/t/test_kdvi.py10
-rw-r--r--test/t/test_kill.py15
-rw-r--r--test/t/test_killall.py21
-rw-r--r--test/t/test_kldload.py7
-rw-r--r--test/t/test_kldunload.py16
-rw-r--r--test/t/test_koji.py11
-rw-r--r--test/t/test_kpdf.py7
-rw-r--r--test/t/test_kplayer.py7
-rw-r--r--test/t/test_ktutil.py11
-rw-r--r--test/t/test_l2ping.py7
-rw-r--r--test/t/test_larch.py7
-rw-r--r--test/t/test_lastlog.py7
-rw-r--r--test/t/test_ld.py11
-rw-r--r--test/t/test_ldapadd.py7
-rw-r--r--test/t/test_ldapcompare.py7
-rw-r--r--test/t/test_ldapdelete.py7
-rw-r--r--test/t/test_ldapmodrdn.py7
-rw-r--r--test/t/test_ldappasswd.py7
-rw-r--r--test/t/test_ldapsearch.py7
-rw-r--r--test/t/test_ldapvi.py7
-rw-r--r--test/t/test_ldapwhoami.py7
-rw-r--r--test/t/test_ldd.py13
-rw-r--r--test/t/test_less.py11
-rw-r--r--test/t/test_lftp.py16
-rw-r--r--test/t/test_lftpget.py7
-rw-r--r--test/t/test_lilo.py16
-rw-r--r--test/t/test_links.py11
-rw-r--r--test/t/test_lintian.py7
-rw-r--r--test/t/test_lintian_info.py12
-rw-r--r--test/t/test_lisp.py7
-rw-r--r--test/t/test_list_admins.py7
-rw-r--r--test/t/test_list_lists.py7
-rw-r--r--test/t/test_list_members.py7
-rw-r--r--test/t/test_list_owners.py8
-rw-r--r--test/t/test_ln.py11
-rw-r--r--test/t/test_locale_gen.py13
-rw-r--r--test/t/test_look.py16
-rw-r--r--test/t/test_lpq.py7
-rw-r--r--test/t/test_lpr.py7
-rw-r--r--test/t/test_lrzip.py15
-rw-r--r--test/t/test_ls.py40
-rw-r--r--test/t/test_lsof.py11
-rw-r--r--test/t/test_lspci.py13
-rw-r--r--test/t/test_lsscsi.py11
-rw-r--r--test/t/test_lsusb.py10
-rw-r--r--test/t/test_lua.py11
-rw-r--r--test/t/test_luac.py11
-rw-r--r--test/t/test_luseradd.py7
-rw-r--r--test/t/test_luserdel.py11
-rw-r--r--test/t/test_lusermod.py7
-rw-r--r--test/t/test_lvchange.py9
-rw-r--r--test/t/test_lvcreate.py9
-rw-r--r--test/t/test_lvdisplay.py11
-rw-r--r--test/t/test_lvextend.py9
-rw-r--r--test/t/test_lvm.py7
-rw-r--r--test/t/test_lvmdiskscan.py11
-rw-r--r--test/t/test_lvreduce.py9
-rw-r--r--test/t/test_lvremove.py9
-rw-r--r--test/t/test_lvrename.py9
-rw-r--r--test/t/test_lvresize.py9
-rw-r--r--test/t/test_lvs.py9
-rw-r--r--test/t/test_lvscan.py9
-rw-r--r--test/t/test_lz4.py15
-rw-r--r--test/t/test_lzip.py11
-rw-r--r--test/t/test_lzma.py19
-rw-r--r--test/t/test_lzop.py11
-rw-r--r--test/t/test_m4.py9
-rw-r--r--test/t/test_macof.py7
-rw-r--r--test/t/test_mailmanctl.py8
-rw-r--r--test/t/test_mailsnarf.py7
-rw-r--r--test/t/test_make.py47
-rw-r--r--test/t/test_makepkg.py17
-rw-r--r--test/t/test_man.py115
-rw-r--r--test/t/test_mc.py7
-rw-r--r--test/t/test_mcrypt.py19
-rw-r--r--test/t/test_md5sum.py11
-rw-r--r--test/t/test_mdadm.py7
-rw-r--r--test/t/test_mdecrypt.py7
-rw-r--r--test/t/test_mdtool.py7
-rw-r--r--test/t/test_medusa.py7
-rw-r--r--test/t/test_mencoder.py12
-rw-r--r--test/t/test_mii_diag.py12
-rw-r--r--test/t/test_mii_tool.py12
-rw-r--r--test/t/test_minicom.py7
-rw-r--r--test/t/test_mkdir.py21
-rw-r--r--test/t/test_mkfifo.py11
-rw-r--r--test/t/test_mkinitrd.py7
-rw-r--r--test/t/test_mkisofs.py15
-rw-r--r--test/t/test_mknod.py11
-rw-r--r--test/t/test_mktemp.py7
-rw-r--r--test/t/test_mmsitepass.py7
-rw-r--r--test/t/test_mock.py13
-rw-r--r--test/t/test_modinfo.py32
-rw-r--r--test/t/test_modprobe.py36
-rw-r--r--test/t/test_module.py7
-rw-r--r--test/t/test_mogrify.py7
-rw-r--r--test/t/test_monodevelop.py11
-rw-r--r--test/t/test_montage.py7
-rw-r--r--test/t/test_mount.py22
-rw-r--r--test/t/test_mplayer.py12
-rw-r--r--test/t/test_mr.py58
-rw-r--r--test/t/test_msgsnarf.py7
-rw-r--r--test/t/test_msynctool.py7
-rw-r--r--test/t/test_mtx.py7
-rw-r--r--test/t/test_munin_node_configure.py19
-rw-r--r--test/t/test_munin_run.py8
-rw-r--r--test/t/test_munindoc.py10
-rw-r--r--test/t/test_mussh.py7
-rw-r--r--test/t/test_mutt.py33
-rw-r--r--test/t/test_muttng.py7
-rw-r--r--test/t/test_mv.py11
-rw-r--r--test/t/test_mypy.py15
-rw-r--r--test/t/test_mysql.py15
-rw-r--r--test/t/test_mysqladmin.py7
-rw-r--r--test/t/test_nc.py7
-rw-r--r--test/t/test_ncftp.py11
-rw-r--r--test/t/test_nethogs.py11
-rw-r--r--test/t/test_netstat.py11
-rw-r--r--test/t/test_newgrp.py7
-rw-r--r--test/t/test_newlist.py7
-rw-r--r--test/t/test_newusers.py11
-rw-r--r--test/t/test_ngrep.py11
-rw-r--r--test/t/test_nl.py11
-rw-r--r--test/t/test_nm.py11
-rw-r--r--test/t/test_nmap.py47
-rw-r--r--test/t/test_nmcli.py7
-rw-r--r--test/t/test_nproc.py17
-rw-r--r--test/t/test_nslookup.py7
-rw-r--r--test/t/test_nsupdate.py11
-rw-r--r--test/t/test_ntpdate.py7
-rw-r--r--test/t/test_objcopy.py11
-rw-r--r--test/t/test_objdump.py7
-rw-r--r--test/t/test_od.py11
-rw-r--r--test/t/test_oggdec.py11
-rw-r--r--test/t/test_op.py11
-rw-r--r--test/t/test_openssl.py16
-rw-r--r--test/t/test_opera.py11
-rw-r--r--test/t/test_optipng.py11
-rw-r--r--test/t/test_p4.py7
-rw-r--r--test/t/test_pack200.py7
-rw-r--r--test/t/test_passwd.py11
-rw-r--r--test/t/test_paste.py11
-rw-r--r--test/t/test_patch.py11
-rw-r--r--test/t/test_pdftotext.py11
-rw-r--r--test/t/test_perl.py91
-rw-r--r--test/t/test_perlcritic.py15
-rw-r--r--test/t/test_perldoc.py18
-rw-r--r--test/t/test_perltidy.py19
-rw-r--r--test/t/test_pgrep.py35
-rw-r--r--test/t/test_phing.py11
-rw-r--r--test/t/test_pidof.py15
-rw-r--r--test/t/test_pine.py7
-rw-r--r--test/t/test_pinfo.py12
-rw-r--r--test/t/test_ping.py11
-rw-r--r--test/t/test_pkg_config.py12
-rw-r--r--test/t/test_pkg_deinstall.py15
-rw-r--r--test/t/test_pkg_delete.py7
-rw-r--r--test/t/test_pkg_get.py8
-rw-r--r--test/t/test_pkg_info.py7
-rw-r--r--test/t/test_pkgadd.py8
-rw-r--r--test/t/test_pkgrm.py8
-rw-r--r--test/t/test_pkgtool.py7
-rw-r--r--test/t/test_pkgutil.py7
-rw-r--r--test/t/test_pkill.py11
-rw-r--r--test/t/test_plague_client.py8
-rw-r--r--test/t/test_pm_hibernate.py8
-rw-r--r--test/t/test_pm_is_supported.py8
-rw-r--r--test/t/test_pm_powersave.py8
-rw-r--r--test/t/test_pngfix.py11
-rw-r--r--test/t/test_portinstall.py27
-rw-r--r--test/t/test_portsnap.py7
-rw-r--r--test/t/test_portupgrade.py8
-rw-r--r--test/t/test_postcat.py11
-rw-r--r--test/t/test_postconf.py20
-rw-r--r--test/t/test_postfix.py22
-rw-r--r--test/t/test_postmap.py11
-rw-r--r--test/t/test_postsuper.py7
-rw-r--r--test/t/test_povray.py7
-rw-r--r--test/t/test_pr.py11
-rw-r--r--test/t/test_prelink.py11
-rw-r--r--test/t/test_printenv.py19
-rw-r--r--test/t/test_protoc.py20
-rw-r--r--test/t/test_psql.py11
-rw-r--r--test/t/test_ptx.py11
-rw-r--r--test/t/test_puppet.py11
-rw-r--r--test/t/test_pushd.py7
-rw-r--r--test/t/test_pv.py15
-rw-r--r--test/t/test_pvchange.py9
-rw-r--r--test/t/test_pvcreate.py9
-rw-r--r--test/t/test_pvdisplay.py11
-rw-r--r--test/t/test_pvmove.py9
-rw-r--r--test/t/test_pvremove.py9
-rw-r--r--test/t/test_pvs.py9
-rw-r--r--test/t/test_pvscan.py9
-rw-r--r--test/t/test_pwck.py11
-rw-r--r--test/t/test_pwd.py7
-rw-r--r--test/t/test_pwdx.py19
-rw-r--r--test/t/test_pwgen.py7
-rw-r--r--test/t/test_pycodestyle.py15
-rw-r--r--test/t/test_pydoc.py11
-rw-r--r--test/t/test_pydocstyle.py13
-rw-r--r--test/t/test_pyflakes.py11
-rw-r--r--test/t/test_pylint.py11
-rw-r--r--test/t/test_pylint_3.py12
-rw-r--r--test/t/test_pytest.py50
-rw-r--r--test/t/test_python.py39
-rw-r--r--test/t/test_python3.py39
-rw-r--r--test/t/test_pyvenv.py7
-rw-r--r--test/t/test_qemu.py11
-rw-r--r--test/t/test_qrunner.py7
-rw-r--r--test/t/test_querybts.py7
-rw-r--r--test/t/test_quota.py11
-rw-r--r--test/t/test_quotacheck.py7
-rw-r--r--test/t/test_quotaon.py7
-rw-r--r--test/t/test_radvdump.py11
-rw-r--r--test/t/test_rcs.py7
-rw-r--r--test/t/test_rcsdiff.py7
-rw-r--r--test/t/test_rdesktop.py7
-rw-r--r--test/t/test_rdict.py7
-rw-r--r--test/t/test_readelf.py7
-rw-r--r--test/t/test_readonly.py7
-rw-r--r--test/t/test_remove_members.py7
-rw-r--r--test/t/test_removepkg.py15
-rw-r--r--test/t/test_renice.py11
-rw-r--r--test/t/test_repomanage.py11
-rw-r--r--test/t/test_reportbug.py7
-rw-r--r--test/t/test_reptyr.py11
-rw-r--r--test/t/test_resolvconf.py7
-rw-r--r--test/t/test_rfcomm.py7
-rw-r--r--test/t/test_rfkill.py11
-rw-r--r--test/t/test_ri.py16
-rw-r--r--test/t/test_rlog.py7
-rw-r--r--test/t/test_rm.py11
-rw-r--r--test/t/test_rmdir.py16
-rw-r--r--test/t/test_rmlist.py7
-rw-r--r--test/t/test_rmmod.py7
-rw-r--r--test/t/test_route.py7
-rw-r--r--test/t/test_rpcdebug.py7
-rw-r--r--test/t/test_rpm.py15
-rw-r--r--test/t/test_rpm2tgz.py26
-rw-r--r--test/t/test_rpmbuild.py7
-rw-r--r--test/t/test_rrdtool.py7
-rw-r--r--test/t/test_rsync.py16
-rw-r--r--test/t/test_rtcwake.py11
-rw-r--r--test/t/test_runuser.py7
-rw-r--r--test/t/test_sbcl.py7
-rw-r--r--test/t/test_sbcl_mt.py8
-rw-r--r--test/t/test_sbopkg.py7
-rw-r--r--test/t/test_scp.py79
-rw-r--r--test/t/test_screen.py48
-rw-r--r--test/t/test_scrub.py19
-rw-r--r--test/t/test_sdptool.py7
-rw-r--r--test/t/test_secret_tool.py12
-rw-r--r--test/t/test_sed.py7
-rw-r--r--test/t/test_seq.py7
-rw-r--r--test/t/test_service.py7
-rw-r--r--test/t/test_set.py7
-rw-r--r--test/t/test_setquota.py11
-rw-r--r--test/t/test_sftp.py46
-rw-r--r--test/t/test_sh.py19
-rw-r--r--test/t/test_sha1sum.py7
-rw-r--r--test/t/test_shar.py7
-rw-r--r--test/t/test_shellcheck.py19
-rw-r--r--test/t/test_sitecopy.py7
-rw-r--r--test/t/test_slackpkg.py7
-rw-r--r--test/t/test_slapt_get.py44
-rw-r--r--test/t/test_slapt_src.py43
-rw-r--r--test/t/test_smartctl.py7
-rw-r--r--test/t/test_smbcacls.py7
-rw-r--r--test/t/test_smbclient.py7
-rw-r--r--test/t/test_smbcquotas.py7
-rw-r--r--test/t/test_smbget.py7
-rw-r--r--test/t/test_smbpasswd.py7
-rw-r--r--test/t/test_smbtar.py7
-rw-r--r--test/t/test_smbtree.py7
-rw-r--r--test/t/test_snownews.py7
-rw-r--r--test/t/test_sort.py7
-rw-r--r--test/t/test_split.py7
-rw-r--r--test/t/test_spovray.py7
-rw-r--r--test/t/test_sqlite3.py15
-rw-r--r--test/t/test_ss.py15
-rw-r--r--test/t/test_ssh.py60
-rw-r--r--test/t/test_ssh_add.py17
-rw-r--r--test/t/test_ssh_copy_id.py16
-rw-r--r--test/t/test_ssh_keygen.py59
-rw-r--r--test/t/test_sshfs.py8
-rw-r--r--test/t/test_sshmitm.py7
-rw-r--r--test/t/test_sshow.py7
-rw-r--r--test/t/test_strace.py7
-rw-r--r--test/t/test_stream.py7
-rw-r--r--test/t/test_strings.py11
-rw-r--r--test/t/test_strip.py7
-rw-r--r--test/t/test_su.py11
-rw-r--r--test/t/test_sudo.py83
-rw-r--r--test/t/test_sum.py11
-rw-r--r--test/t/test_svcadm.py7
-rw-r--r--test/t/test_svk.py7
-rw-r--r--test/t/test_svn.py7
-rw-r--r--test/t/test_svnadmin.py7
-rw-r--r--test/t/test_svnlook.py7
-rw-r--r--test/t/test_sync_members.py7
-rw-r--r--test/t/test_synclient.py16
-rw-r--r--test/t/test_sysbench.py11
-rw-r--r--test/t/test_sysctl.py15
-rw-r--r--test/t/test_tac.py7
-rw-r--r--test/t/test_tail.py7
-rw-r--r--test/t/test_tar.py120
-rw-r--r--test/t/test_tcpdump.py7
-rw-r--r--test/t/test_tcpkill.py7
-rw-r--r--test/t/test_tcpnice.py7
-rw-r--r--test/t/test_tee.py11
-rw-r--r--test/t/test_texindex.py7
-rw-r--r--test/t/test_tightvncviewer.py7
-rw-r--r--test/t/test_time.py23
-rw-r--r--test/t/test_timeout.py11
-rw-r--r--test/t/test_tipc.py7
-rw-r--r--test/t/test_totem.py7
-rw-r--r--test/t/test_touch.py7
-rw-r--r--test/t/test_tox.py19
-rw-r--r--test/t/test_tr.py7
-rw-r--r--test/t/test_tracepath.py11
-rw-r--r--test/t/test_tshark.py34
-rw-r--r--test/t/test_tsig_keygen.py12
-rw-r--r--test/t/test_tune2fs.py11
-rw-r--r--test/t/test_udevadm.py11
-rw-r--r--test/t/test_ulimit.py35
-rw-r--r--test/t/test_umount.py85
-rw-r--r--test/t/test_unace.py7
-rw-r--r--test/t/test_uname.py7
-rw-r--r--test/t/test_unexpand.py7
-rw-r--r--test/t/test_uniq.py7
-rw-r--r--test/t/test_units.py9
-rw-r--r--test/t/test_unpack200.py7
-rw-r--r--test/t/test_unrar.py7
-rw-r--r--test/t/test_unset.py7
-rw-r--r--test/t/test_unshunt.py7
-rw-r--r--test/t/test_update_alternatives.py8
-rw-r--r--test/t/test_update_rc_d.py8
-rw-r--r--test/t/test_upgradepkg.py51
-rw-r--r--test/t/test_urlsnarf.py7
-rw-r--r--test/t/test_uscan.py7
-rw-r--r--test/t/test_useradd.py11
-rw-r--r--test/t/test_userdel.py11
-rw-r--r--test/t/test_usermod.py11
-rw-r--r--test/t/test_valgrind.py42
-rw-r--r--test/t/test_vdir.py11
-rw-r--r--test/t/test_vgcfgbackup.py11
-rw-r--r--test/t/test_vgcfgrestore.py11
-rw-r--r--test/t/test_vgchange.py9
-rw-r--r--test/t/test_vgck.py9
-rw-r--r--test/t/test_vgconvert.py9
-rw-r--r--test/t/test_vgcreate.py13
-rw-r--r--test/t/test_vgdisplay.py9
-rw-r--r--test/t/test_vgexport.py9
-rw-r--r--test/t/test_vgextend.py9
-rw-r--r--test/t/test_vgimport.py9
-rw-r--r--test/t/test_vgmerge.py9
-rw-r--r--test/t/test_vgmknodes.py9
-rw-r--r--test/t/test_vgreduce.py9
-rw-r--r--test/t/test_vgremove.py9
-rw-r--r--test/t/test_vgrename.py9
-rw-r--r--test/t/test_vgs.py9
-rw-r--r--test/t/test_vgscan.py9
-rw-r--r--test/t/test_vgsplit.py9
-rw-r--r--test/t/test_vi.py11
-rw-r--r--test/t/test_vipw.py7
-rw-r--r--test/t/test_vmstat.py7
-rw-r--r--test/t/test_vncviewer.py8
-rw-r--r--test/t/test_vpnc.py13
-rw-r--r--test/t/test_watch.py7
-rw-r--r--test/t/test_wc.py7
-rw-r--r--test/t/test_webmitm.py7
-rw-r--r--test/t/test_wget.py11
-rw-r--r--test/t/test_who.py9
-rw-r--r--test/t/test_wine.py11
-rw-r--r--test/t/test_withlist.py7
-rw-r--r--test/t/test_wodim.py7
-rw-r--r--test/t/test_wol.py20
-rw-r--r--test/t/test_write.py7
-rw-r--r--test/t/test_wsimport.py18
-rw-r--r--test/t/test_wtf.py8
-rw-r--r--test/t/test_wvdial.py7
-rw-r--r--test/t/test_xdg_mime.py28
-rw-r--r--test/t/test_xdg_settings.py16
-rw-r--r--test/t/test_xfreerdp.py60
-rw-r--r--test/t/test_xgamma.py12
-rw-r--r--test/t/test_xhost.py22
-rw-r--r--test/t/test_xm.py7
-rw-r--r--test/t/test_xmllint.py11
-rw-r--r--test/t/test_xmlwf.py11
-rw-r--r--test/t/test_xmms.py11
-rw-r--r--test/t/test_xmodmap.py11
-rw-r--r--test/t/test_xpovray.py7
-rw-r--r--test/t/test_xrandr.py15
-rw-r--r--test/t/test_xrdb.py11
-rw-r--r--test/t/test_xsltproc.py11
-rw-r--r--test/t/test_xvfb_run.py12
-rw-r--r--test/t/test_xvnc4viewer.py15
-rw-r--r--test/t/test_xxd.py11
-rw-r--r--test/t/test_xz.py26
-rw-r--r--test/t/test_xzdec.py11
-rw-r--r--test/t/test_ypcat.py7
-rw-r--r--test/t/test_ypmatch.py8
-rw-r--r--test/t/test_yum.py7
-rw-r--r--test/t/test_yum_arch.py8
-rw-r--r--test/t/test_zopfli.py15
-rw-r--r--test/t/test_zopflipng.py11
-rw-r--r--test/t/unit/Makefile.am24
-rw-r--r--test/t/unit/test_unit_count_args.py66
-rw-r--r--test/t/unit/test_unit_expand.py31
-rw-r--r--test/t/unit/test_unit_expand_tilde_by_ref.py46
-rw-r--r--test/t/unit/test_unit_filedir.py235
-rw-r--r--test/t/unit/test_unit_find_unique_completion_pair.py55
-rw-r--r--test/t/unit/test_unit_get_comp_words_by_ref.py260
-rw-r--r--test/t/unit/test_unit_get_cword.py154
-rw-r--r--test/t/unit/test_unit_init_completion.py34
-rw-r--r--test/t/unit/test_unit_ip_addresses.py49
-rw-r--r--test/t/unit/test_unit_known_hosts_real.py158
-rw-r--r--test/t/unit/test_unit_longopt.py52
-rw-r--r--test/t/unit/test_unit_parse_help.py183
-rw-r--r--test/t/unit/test_unit_parse_usage.py69
-rw-r--r--test/t/unit/test_unit_quote.py36
-rw-r--r--test/t/unit/test_unit_quote_readline.py15
-rw-r--r--test/t/unit/test_unit_tilde.py42
-rw-r--r--test/t/unit/test_unit_variables.py41
-rw-r--r--test/t/unit/test_unit_xinetd_services.py22
706 files changed, 11710 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"]