3 """Test miscellaneous commands."""
7 from testlib import check, cmd
8 from testlib.log import log
9 from testlib.proc import Tinc, Script
10 from testlib.test import Test
12 SUBNETS_BAR = ("10.20.30.40", "fe80::")
15 def configure_nodes(ctx: Test) -> T.Tuple[Tinc, Tinc]:
16 """Create and configure nodes."""
18 log.info("initialize nodes")
19 foo, bar = ctx.node(init=True), ctx.node(init=True)
21 log.info("configure and start nodes")
22 foo.cmd("add", "Subnet", "1.2.3.4")
23 foo.add_script(Script.TINC_UP)
24 foo.add_script(bar.script_up)
27 for sub in SUBNETS_BAR:
28 bar.cmd("add", "Subnet", sub)
31 log.info("connect nodes")
32 cmd.exchange(foo, bar)
33 foo.cmd("add", "ConnectTo", bar.name)
35 foo[bar.script_up].wait()
40 def test_version(foo: Tinc) -> None:
41 """Test command 'version'."""
43 log.info("test command 'version' with redundant arguments")
44 _, err = foo.cmd("version", "foo", code=1)
45 check.is_in("Too many arguments", err)
47 log.info("test command 'version'")
48 out, _ = foo.cmd("version")
49 check.has_prefix(out, "tinc version ")
52 def test_help(foo: Tinc) -> None:
53 """Test command 'help'."""
55 log.info("test command 'help'")
56 out, _ = foo.cmd("help")
57 check.is_in("Valid options are", out)
59 out, _ = foo.cmd("help", "foobar")
60 check.is_in("Valid options are", out)
63 def test_info(foo: Tinc, bar: Tinc) -> None:
64 """Test command 'info'."""
66 log.info("info invalid arguments")
67 _, err = foo.cmd("info", code=1)
68 check.is_in("Invalid number of arguments", err)
70 log.info("info unknown node")
71 _, err = foo.cmd("info", "foobar", code=1)
72 check.is_in("Unknown node foobar", err)
74 log.info("info own node")
75 out, _ = foo.cmd("info", foo.name)
76 check.is_in("can reach itself", out)
78 log.info("info peer node")
79 out, _ = foo.cmd("info", bar.name)
80 check.is_in(bar.name, out)
81 for sub in SUBNETS_BAR:
84 log.info("info unknown subnet")
85 for sub in "1.1.1.1", "fe82:42::":
86 _, err = foo.cmd("info", sub, code=1)
87 check.is_in("Unknown address", err)
89 log.info("info own valid subnet")
90 out, _ = foo.cmd("info", "1.2.3.4")
91 check.is_in("Subnet: 1.2.3.4", out)
92 check.is_in(f"Owner: {foo}", out)
94 for sub in SUBNETS_BAR:
95 log.info("info peer's valid subnet %s", sub)
96 out, _ = foo.cmd("info", sub)
97 check.is_in(f"Subnet: {sub}", out)
98 check.is_in(f"Owner: {bar}", out)
101 def test_pid(foo: Tinc) -> None:
102 """Test command 'pid'."""
104 log.info("test pid with too many arguments")
105 _, err = foo.cmd("pid", "foo", code=1)
106 check.is_in("Too many arguments", err)
108 log.info("test pid without arguments")
109 out, _ = foo.cmd("pid")
110 check.equals(foo.pid, int(out.strip()))
113 def test_debug(foo: Tinc) -> None:
114 """Test command 'debug'."""
116 for args in ("debug",), ("debug", "1", "2"):
117 _, err = foo.cmd(*args, code=1)
118 check.is_in("Invalid number of arguments", err)
120 _, err = foo.cmd("debug", "5")
121 check.is_in("new level 5", err)
124 def test_log(foo: Tinc) -> None:
125 """Test command 'log'."""
127 log.info("test with too many arguments")
128 _, err = foo.cmd("log", "foo", "bar", code=1)
129 check.is_in("Too many arguments", err)
131 log.info("test correct call")
132 log_client = foo.tinc("log")
133 foo.cmd("set", "LogLevel", "10")
136 foo.add_script(Script.TINC_DOWN)
138 foo[Script.TINC_DOWN].wait()
140 out, _ = log_client.communicate()
144 def test_restart(foo: Tinc) -> None:
145 """Test command 'restart'."""
147 log.info("restart without arguments")
149 foo[Script.TINC_UP].wait()
151 log.info("restart with an argument")
152 foo.cmd("restart", "-d3")
153 foo[Script.TINC_UP].wait()
155 # Checking the error message is unreliable since
156 # it's provided by getopt() and differs from OS to OS.
157 log.info("restart with invalid options")
158 foo.cmd("restart", "--fake-invalid-option", code=1)
160 log.info("restart with invalid arguments")
161 _, err = foo.cmd("restart", "bad-incorrect-argument", code=1)
162 check.is_in("unrecognized argument", err)
165 def test_shell(foo: Tinc) -> None:
168 log.info("indented comments are not ignored")
169 _, err = foo.cmd(stdin=" # ", code=1)
170 check.is_in("Unknown command", err)
172 log.info("comments are ignored")
173 _, err = foo.cmd(stdin="# this_will_fail unless comments are ignored")
174 assert "this_will_fail" not in err
176 log.info("inline comments are treated as arguments")
177 _, err = foo.cmd(stdin="version # inline comments are not ignored", code=1)
178 check.is_in("Too many arguments", err)
180 log.info("check exit commands")
181 for command in "exit", "quit":
182 out, _ = foo.cmd(stdin=command)
186 def run_tests(ctx: Test) -> None:
189 foo, bar = configure_nodes(ctx)
198 # Too unstable on Windows because of how it works with services (impossible to
199 # start the service if it has been marked for deletion, but not yet deleted).
200 # Since lots of things can prevent service removal (like opened task manager or
201 # services.msc) the `restart` command is inherently unreliable.
206 with Test("run tests") as context: