summaryrefslogtreecommitdiff
path: root/test/t/unit
diff options
context:
space:
mode:
Diffstat (limited to 'test/t/unit')
-rw-r--r--test/t/unit/Makefile.am19
-rw-r--r--test/t/unit/test_unit_count_args.py66
-rw-r--r--test/t/unit/test_unit_expand.py13
-rw-r--r--test/t/unit/test_unit_expand_tilde_by_ref.py16
-rw-r--r--test/t/unit/test_unit_filedir.py9
-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.py167
-rw-r--r--test/t/unit/test_unit_get_cword.py135
-rw-r--r--test/t/unit/test_unit_init_completion.py24
-rw-r--r--test/t/unit/test_unit_ip_addresses.py49
-rw-r--r--test/t/unit/test_unit_longopt.py34
-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_tilde.py42
14 files changed, 881 insertions, 0 deletions
diff --git a/test/t/unit/Makefile.am b/test/t/unit/Makefile.am
new file mode 100644
index 00000000..a0ab7502
--- /dev/null
+++ b/test/t/unit/Makefile.am
@@ -0,0 +1,19 @@
+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_longopt.py \
+ test_unit_parse_help.py \
+ test_unit_parse_usage.py \
+ test_unit_tilde.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 00000000..c0afe736
--- /dev/null
+++ b/test/t/unit/test_unit_count_args.py
@@ -0,0 +1,66 @@
+import pytest
+
+from conftest import assert_bash_exec, TestUnitBase
+
+
+@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, "_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 00000000..7c0a9836
--- /dev/null
+++ b/test/t/unit/test_unit_expand.py
@@ -0,0 +1,13 @@
+import pytest
+
+from conftest import assert_bash_exec
+
+
+@pytest.mark.bashcomp(cmd=None)
+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")
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 00000000..fbc172df
--- /dev/null
+++ b/test/t/unit/test_unit_expand_tilde_by_ref.py
@@ -0,0 +1,16 @@
+import pytest
+
+from conftest import assert_bash_exec
+
+
+@pytest.mark.bashcomp(cmd=None)
+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',
+ )
diff --git a/test/t/unit/test_unit_filedir.py b/test/t/unit/test_unit_filedir.py
new file mode 100644
index 00000000..dcd52403
--- /dev/null
+++ b/test/t/unit/test_unit_filedir.py
@@ -0,0 +1,9 @@
+import pytest
+
+from conftest import assert_bash_exec
+
+
+@pytest.mark.bashcomp(cmd=None, ignore_env=r"^\+COMPREPLY=")
+class TestUnitFiledir:
+ def test_1(self, bash):
+ assert_bash_exec(bash, "_filedir >/dev/null")
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 00000000..25cf9d3b
--- /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 00000000..1603bad6
--- /dev/null
+++ b/test/t/unit/test_unit_get_comp_words_by_ref.py
@@ -0,0 +1,167 @@
+import pytest
+
+from conftest import assert_bash_exec, TestUnitBase
+
+
+@pytest.mark.bashcomp(
+ cmd=None, ignore_env=r"^(\+(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, "_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"
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 00000000..3042dd29
--- /dev/null
+++ b/test/t/unit/test_unit_get_cword.py
@@ -0,0 +1,135 @@
+import pytest
+
+from conftest import assert_bash_exec, TestUnitBase
+
+
+@pytest.mark.bashcomp(
+ cmd=None, ignore_env=r"^[+-]COMP_(WORDS|CWORD|LINE|POINT)="
+)
+class TestUnitGetCword(TestUnitBase):
+ def _test(self, *args, **kwargs):
+ return self._test_unit("_get_cword %s; echo", *args, **kwargs)
+
+ def test_1(self, bash):
+ assert_bash_exec(bash, "_get_cword >/dev/null")
+
+ 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"
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 00000000..64f3b511
--- /dev/null
+++ b/test/t/unit/test_unit_init_completion.py
@@ -0,0 +1,24 @@
+import pytest
+
+from conftest import assert_bash_exec, TestUnitBase
+
+
+@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; _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 == ","
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 00000000..cd7a38ab
--- /dev/null
+++ b/test/t/unit/test_unit_ip_addresses.py
@@ -0,0 +1,49 @@
+import pytest
+
+from conftest import assert_bash_exec, in_docker
+
+
+@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_docker(), reason="Probably fails in docker")
+ @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_longopt.py b/test/t/unit/test_unit_longopt.py
new file mode 100644
index 00000000..ac0ac836
--- /dev/null
+++ b/test/t/unit/test_unit_longopt.py
@@ -0,0 +1,34 @@
+# 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")
+
+ @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)
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 00000000..4a02155b
--- /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 00000000..f0cb7114
--- /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_tilde.py b/test/t/unit/test_unit_tilde.py
new file mode 100644
index 00000000..35a4e4c6
--- /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)