1from itertools import chain
2
3import pytest
4
5from conftest import assert_bash_exec
6
7
8@pytest.mark.bashcomp(
9    cmd=None,
10    ignore_env="^[+-](COMP(REPLY|_KNOWN_HOSTS_WITH_HOSTFILE)|OLDHOME)=",
11)
12class TestUnitKnownHostsReal:
13    @pytest.mark.parametrize(
14        "prefix,colon_flag,hostfile",
15        [("", "", True), ("", "", False), ("user@", "c", True)],
16    )
17    def test_basic(
18        self, bash, hosts, avahi_hosts, prefix, colon_flag, hostfile
19    ):
20        expected = (
21            "%s%s%s" % (prefix, x, ":" if colon_flag else "")
22            for x in chain(
23                hosts if hostfile else avahi_hosts,
24                # fixtures/_known_hosts_real/config
25                "gee hus jar #not-a-comment".split(),
26                # fixtures/_known_hosts_real/known_hosts
27                (
28                    "doo",
29                    "ike",
30                    "jub",
31                    "10.0.0.1",
32                    "kyl",
33                    "100.0.0.2",
34                    "10.10.0.3",
35                    "blah",
36                    "fd00:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:5555",
37                    "fe80::123:0xff:dead:beef%eth0",
38                    "1111:2222:3333:4444:5555:6666:xxxx:abab",
39                    "11xx:2222:3333:4444:5555:6666:xxxx:abab",
40                    "::42",
41                ),
42            )
43        )
44        assert_bash_exec(
45            bash,
46            "unset -v COMP_KNOWN_HOSTS_WITH_HOSTFILE"
47            if hostfile
48            else "COMP_KNOWN_HOSTS_WITH_HOSTFILE=",
49        )
50        output = assert_bash_exec(
51            bash,
52            "_known_hosts_real -a%sF _known_hosts_real/config '%s'; "
53            r'printf "%%s\n" "${COMPREPLY[@]}"; unset COMPREPLY'
54            % (colon_flag, prefix),
55            want_output=True,
56        )
57        assert sorted(set(output.split())) == sorted(expected)
58
59    @pytest.mark.parametrize(
60        "family,result",
61        (
62            ("4", "127.0.0.1 localhost"),
63            ("6", "::1 localhost"),
64            ("46", "localhost"),
65        ),
66    )
67    def test_ip_filtering(self, bash, family, result):
68        assert_bash_exec(
69            bash, "unset -v COMPREPLY COMP_KNOWN_HOSTS_WITH_HOSTFILE"
70        )
71        output = assert_bash_exec(
72            bash,
73            "COMP_KNOWN_HOSTS_WITH_HOSTFILE= "
74            "_known_hosts_real -%sF _known_hosts_real/localhost_config ''; "
75            r'printf "%%s\n" "${COMPREPLY[@]}"' % family,
76            want_output=True,
77        )
78        assert sorted(set(output.strip().split())) == sorted(result.split())
79
80    def test_consecutive_spaces(self, bash, hosts):
81        expected = hosts.copy()
82        # fixtures/_known_hosts_real/spaced  conf
83        expected.extend("gee hus #not-a-comment".split())
84        # fixtures/_known_hosts_real/known_hosts2
85        expected.extend("two two2 two3 two4".split())
86        # fixtures/_known_hosts_/spaced  known_hosts
87        expected.extend("doo ike".split())
88
89        output = assert_bash_exec(
90            bash,
91            "unset -v COMPREPLY COMP_KNOWN_HOSTS_WITH_HOSTFILE; "
92            "_known_hosts_real -aF '_known_hosts_real/spaced  conf' ''; "
93            r'printf "%s\n" "${COMPREPLY[@]}"',
94            want_output=True,
95        )
96        assert sorted(set(output.strip().split())) == sorted(expected)
97
98    def test_files_starting_with_tilde(self, bash, hosts):
99        expected = hosts.copy()
100        # fixtures/_known_hosts_real/known_hosts2
101        expected.extend("two two2 two3 two4".split())
102        # fixtures/_known_hosts_real/known_hosts3
103        expected.append("three")
104        # fixtures/_known_hosts_real/known_hosts4
105        expected.append("four")
106
107        assert_bash_exec(bash, 'OLDHOME="$HOME"; HOME="%s"' % bash.cwd)
108        output = assert_bash_exec(
109            bash,
110            "unset -v COMPREPLY COMP_KNOWN_HOSTS_WITH_HOSTFILE; "
111            "_known_hosts_real -aF _known_hosts_real/config_tilde ''; "
112            r'printf "%s\n" "${COMPREPLY[@]}"',
113            want_output=True,
114        )
115        assert_bash_exec(bash, 'HOME="$OLDHOME"')
116        assert sorted(set(output.strip().split())) == sorted(expected)
117
118    def test_included_configs(self, bash, hosts):
119        expected = hosts.copy()
120        # fixtures/_known_hosts_real/config_include_recursion
121        expected.append("recursion")
122        # fixtures/_known_hosts_real/.ssh/config_relative_path
123        expected.append("relative_path")
124        # fixtures/_known_hosts_real/.ssh/config_asterisk_*
125        expected.extend("asterisk_1 asterisk_2".split())
126        # fixtures/_known_hosts_real/.ssh/config_question_mark
127        expected.append("question_mark")
128
129        assert_bash_exec(
130            bash, 'OLDHOME="$HOME"; HOME="%s/_known_hosts_real"' % bash.cwd
131        )
132        output = assert_bash_exec(
133            bash,
134            "unset -v COMPREPLY COMP_KNOWN_HOSTS_WITH_HOSTFILE; "
135            "_known_hosts_real -aF _known_hosts_real/config_include ''; "
136            r'printf "%s\n" "${COMPREPLY[@]}"',
137            want_output=True,
138        )
139        assert_bash_exec(bash, 'HOME="$OLDHOME"')
140        assert sorted(set(output.strip().split())) == sorted(expected)
141
142    def test_no_globbing(self, bash):
143        assert_bash_exec(
144            bash, 'OLDHOME="$HOME"; HOME="%s/_known_hosts_real"' % bash.cwd
145        )
146        output = assert_bash_exec(
147            bash,
148            "cd _known_hosts_real; "
149            "unset -v COMPREPLY COMP_KNOWN_HOSTS_WITH_HOSTFILE; "
150            "_known_hosts_real -aF config ''; "
151            r'printf "%s\n" "${COMPREPLY[@]}"; '
152            "cd - &>/dev/null",
153            want_output=True,
154        )
155        assert_bash_exec(bash, 'HOME="$OLDHOME"')
156        completion = sorted(set(output.strip().split()))
157        assert "gee" in completion
158        assert "gee-filename-canary" not in completion
159