From c45a3fd7319d03bd147448a017f5aaed3b46fdfe Mon Sep 17 00:00:00 2001 From: Kirill Isakov Date: Fri, 27 May 2022 00:51:42 +0600 Subject: [PATCH] Add tests for import/export errors --- src/tincctl.c | 2 +- test/integration/cmd_import.py | 176 +++++++++++++++++++++++++++++++++ test/integration/meson.build | 1 + 3 files changed, 178 insertions(+), 1 deletion(-) create mode 100755 test/integration/cmd_import.py diff --git a/src/tincctl.c b/src/tincctl.c index 5144b793..b8155cbd 100644 --- a/src/tincctl.c +++ b/src/tincctl.c @@ -2545,7 +2545,7 @@ static int cmd_export_all(int argc, char *argv[]) { if(first) { first = false; } else { - printf("#---------------------------------------------------------------#\n"); + printf("\n#---------------------------------------------------------------#\n"); } result |= export(ent->d_name, stdout); diff --git a/test/integration/cmd_import.py b/test/integration/cmd_import.py new file mode 100755 index 00000000..769cf795 --- /dev/null +++ b/test/integration/cmd_import.py @@ -0,0 +1,176 @@ +#!/usr/bin/env python3 + +"""Test import/export error conditions.""" + +import os + +from testlib import check, cmd, util +from testlib.log import log +from testlib.proc import Tinc +from testlib.test import Test + +SEPARATOR = f"#{'-' * 63}#" + +MULTI_HOST = f""" +Name = node0 +Address = sun +{SEPARATOR} +Name = node1 +Address = moon +{SEPARATOR} +""".strip() + +MAX_PATH = 255 if os.name == "nt" else os.pathconf("/", "PC_PATH_MAX") +LONG_NAME = MAX_PATH * "x" + + +def init(ctx: Test) -> Tinc: + """Initialize a node.""" + + node = ctx.node() + stdin = f""" + init {node} + set Port 0 + set Address localhost + set DeviceType dummy + set AutoConnect no + """ + node.cmd(stdin=stdin) + return node + + +def test_import(foo: Tinc) -> None: + """Run tests for command 'import'.""" + + _, err = foo.cmd("import", "foo", code=1) + check.is_in("Too many arguments", err) + + _, err = foo.cmd("import", code=1) + check.is_in("No host configuration files imported", err) + + for prefix in "fred", "Name fred", "name = fred", "name=fred": + log.info("testing prefix '%s'", prefix) + _, err = foo.cmd("import", stdin=prefix, code=1) + check.is_in("Junk at the beginning", err) + + _, err = foo.cmd("import", stdin="Name = !@#", code=1) + check.is_in("Invalid Name in input", err) + + _, err = foo.cmd("import", stdin=f"Name = {LONG_NAME}", code=1) + check.is_in("Filename too long", err) + + log.info("make sure no address for imported nodes is present") + for node in "node0", "node1": + foo.cmd("get", f"{node}.Address", code=1) + + _, err = foo.cmd("import", stdin=MULTI_HOST) + check.is_in("Imported 2 host configuration files", err) + + log.info("check imported nodes addresses") + check.equals("sun", cmd.get(foo, "node0.Address")) + check.equals("moon", cmd.get(foo, "node1.Address")) + + _, err = foo.cmd("import", stdin="Name = node0", code=1) + check.is_in("node0 already exists", err) + + if os.name != "nt": + log.info("import to inaccessible hosts subdirectory") + os.chmod(foo.sub("hosts"), 0) + _, err = foo.cmd("import", stdin="Name = vinny", code=1) + check.is_in("Error creating configuration", err) + + +def test_export(foo: Tinc) -> None: + """Run tests for command 'export'.""" + + _, err = foo.cmd("export", "foo", code=1) + check.is_in("Too many arguments", err) + + os.remove(foo.sub(f"hosts/{foo}")) + _, err = foo.cmd("export", code=1) + check.is_in("Could not open configuration", err) + + util.write_text(foo.sub("tinc.conf"), "") + _, err = foo.cmd("export", code=1) + check.is_in("Could not find Name", err) + + os.remove(foo.sub("tinc.conf")) + _, err = foo.cmd("export", code=1) + check.is_in("Could not open", err) + + +def test_exchange(foo: Tinc) -> None: + """Run tests for command 'exchange'.""" + + log.info("make sure exchange does not import if export fails") + util.write_text(foo.sub("tinc.conf"), "") + host_foo = "Name = foo\nAddress = 1.1.1.1" + _, err = foo.cmd("exchange", stdin=host_foo, code=1) + assert "Imported" not in err + + +def test_exchange_all(foo: Tinc) -> None: + """Run tests for command 'exchange'.""" + + log.info("make sure exchange-all does not import if export fails") + host_bar = foo.sub("hosts/bar") + util.write_text(host_bar, "") + os.chmod(host_bar, 0) + host_foo = "Name = foo\nAddress = 1.1.1.1" + _, err = foo.cmd("exchange-all", stdin=host_foo, code=1) + assert "Imported" not in err + + +def test_export_all(foo: Tinc) -> None: + """Run tests for command 'export-all'.""" + + _, err = foo.cmd("export-all", "foo", code=1) + check.is_in("Too many arguments", err) + + host_foo = foo.sub("hosts/foo") + util.write_text(host_foo, "Name = foo") + os.chmod(host_foo, 0) + + host_bar = foo.sub("hosts/bar") + util.write_text(host_bar, "Host = bar\nAddress = 1.1.1.1") + + host_invalid = foo.sub("hosts/xi-Eb-Vx-k3") + util.write_text(host_invalid, "Host = invalid") + + out, err = foo.cmd("export-all", code=1) + check.is_in("Could not open configuration", err) + + log.info("checking bad node name in export") + assert "xi-Eb-Vx-k3" not in out + + for want in "Host = bar", "Address = 1.1.1.1", SEPARATOR: + check.is_in(want, out) + + log.info("verify that separators are used on separate lines") + lines = out.splitlines() + separators = list(filter(lambda line: line == SEPARATOR, lines)) + if len(separators) != 2: + log.info("unexpected number of separators: %s", lines) + assert False + + if os.name != "nt": + os.chmod(foo.sub("hosts"), 0) + _, err = foo.cmd("export-all", code=1) + check.is_in("Could not open host configuration", err) + + +with Test("test 'import' command") as context: + test_import(init(context)) + +with Test("test 'export' command") as context: + test_export(init(context)) + +with Test("test 'exchange' command") as context: + test_exchange(init(context)) + +if os.name != "nt": + with Test("test 'exchange-all' command") as context: + test_exchange_all(init(context)) + + with Test("test 'export-all' command") as context: + test_export_all(init(context)) diff --git a/test/integration/meson.build b/test/integration/meson.build index 0fd03dd6..3414ddb5 100644 --- a/test/integration/meson.build +++ b/test/integration/meson.build @@ -2,6 +2,7 @@ tests = [ 'basic.py', 'cmd_dump.py', 'cmd_fsck.py', + 'cmd_import.py', 'cmd_join.py', 'cmd_keys.py', 'cmd_misc.py', -- 2.20.1