cmd_misc.py 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216
  1. #!/usr/bin/env python3
  2. """Test miscellaneous commands."""
  3. import time
  4. import typing as T
  5. from testlib import check, cmd, util
  6. from testlib.log import log
  7. from testlib.proc import Tinc, Script
  8. from testlib.test import Test
  9. SUBNETS_BAR = ("10.20.30.40", "fe80::")
  10. def init(ctx: Test) -> Tinc:
  11. """Initialize a node."""
  12. node = ctx.node()
  13. stdin = f"""
  14. init {node}
  15. set Port 0
  16. set Address localhost
  17. set DeviceType dummy
  18. """
  19. node.cmd(stdin=stdin)
  20. return node
  21. def configure_nodes(ctx: Test) -> T.Tuple[Tinc, Tinc]:
  22. """Create and configure nodes."""
  23. log.info("initialize nodes")
  24. foo, bar = init(ctx), init(ctx)
  25. log.info("configure and start nodes")
  26. foo.cmd("add", "Subnet", "1.2.3.4")
  27. foo.add_script(Script.TINC_UP)
  28. foo.add_script(bar.script_up)
  29. foo.start()
  30. for sub in SUBNETS_BAR:
  31. bar.cmd("add", "Subnet", sub)
  32. bar.start()
  33. log.info("connect nodes")
  34. cmd.exchange(foo, bar)
  35. foo.cmd("add", "ConnectTo", bar.name)
  36. foo.cmd("retry")
  37. foo[bar.script_up].wait()
  38. return foo, bar
  39. def test_version(foo: Tinc) -> None:
  40. """Test command 'version'."""
  41. log.info("test command 'version' with redundant arguments")
  42. _, err = foo.cmd("version", "foo", code=1)
  43. check.is_in("Too many arguments", err)
  44. log.info("test command 'version'")
  45. out, _ = foo.cmd("version")
  46. check.has_prefix(out, "tinc version ")
  47. def test_help(foo: Tinc) -> None:
  48. """Test command 'help'."""
  49. log.info("test command 'help'")
  50. out, _ = foo.cmd("help")
  51. check.is_in("Valid options are", out)
  52. out, _ = foo.cmd("help", "foobar")
  53. check.is_in("Valid options are", out)
  54. def test_info(foo: Tinc, bar: Tinc) -> None:
  55. """Test command 'info'."""
  56. log.info("info invalid arguments")
  57. _, err = foo.cmd("info", code=1)
  58. check.is_in("Invalid number of arguments", err)
  59. log.info("info unknown node")
  60. _, err = foo.cmd("info", "foobar", code=1)
  61. check.is_in("Unknown node foobar", err)
  62. log.info("info own node")
  63. out, _ = foo.cmd("info", foo.name)
  64. check.is_in("can reach itself", out)
  65. log.info("info peer node")
  66. out, _ = foo.cmd("info", bar.name)
  67. check.is_in(bar.name, out)
  68. for sub in SUBNETS_BAR:
  69. check.is_in(sub, out)
  70. log.info("info unknown subnet")
  71. for sub in "1.1.1.1", "fe82:42::":
  72. _, err = foo.cmd("info", sub, code=1)
  73. check.is_in("Unknown address", err)
  74. log.info("info own valid subnet")
  75. out, _ = foo.cmd("info", "1.2.3.4")
  76. check.is_in("Subnet: 1.2.3.4", out)
  77. check.is_in(f"Owner: {foo}", out)
  78. for sub in SUBNETS_BAR:
  79. log.info("info peer's valid subnet %s", sub)
  80. out, _ = foo.cmd("info", sub)
  81. check.is_in(f"Subnet: {sub}", out)
  82. check.is_in(f"Owner: {bar}", out)
  83. def test_pid(foo: Tinc) -> None:
  84. """Test command 'pid'."""
  85. log.info("test pid with too many arguments")
  86. _, err = foo.cmd("pid", "foo", code=1)
  87. check.is_in("Too many arguments", err)
  88. log.info("test pid without arguments")
  89. pidfile = util.read_text(foo.sub("pid"))
  90. pid, _ = pidfile.split(maxsplit=1)
  91. out, _ = foo.cmd("pid")
  92. check.equals(pid, out.strip())
  93. def test_debug(foo: Tinc) -> None:
  94. """Test command 'debug'."""
  95. for args in ("debug",), ("debug", "1", "2"):
  96. _, err = foo.cmd(*args, code=1)
  97. check.is_in("Invalid number of arguments", err)
  98. _, err = foo.cmd("debug", "5")
  99. check.is_in("new level 5", err)
  100. def test_log(foo: Tinc) -> None:
  101. """Test command 'log'."""
  102. log.info("test with too many arguments")
  103. _, err = foo.cmd("log", "foo", "bar", code=1)
  104. check.is_in("Too many arguments", err)
  105. log.info("test correct call")
  106. log_client = foo.tinc("log")
  107. foo.cmd("reload")
  108. time.sleep(1)
  109. foo.cmd("stop")
  110. out, _ = log_client.communicate()
  111. check.true(out)
  112. def test_restart(foo: Tinc) -> None:
  113. """Test command 'restart'."""
  114. log.info("restart without arguments")
  115. foo.cmd("restart")
  116. foo[Script.TINC_UP].wait()
  117. log.info("restart with an argument")
  118. foo.cmd("restart", "-d3")
  119. foo[Script.TINC_UP].wait()
  120. # Checking the error message is unreliable since
  121. # it's provided by getopt() and differs from OS to OS.
  122. log.info("restart with invalid options")
  123. foo.cmd("restart", "--fake-invalid-option", code=1)
  124. log.info("restart with invalid arguments")
  125. _, err = foo.cmd("restart", "bad-incorrect-argument", code=1)
  126. check.is_in("unrecognized argument", err)
  127. def test_shell(foo: Tinc) -> None:
  128. """Test shell."""
  129. log.info("indented comments are not ignored")
  130. _, err = foo.cmd(stdin=" # ", code=1)
  131. check.is_in("Unknown command", err)
  132. log.info("comments are ignored")
  133. _, err = foo.cmd(stdin="# this_will_fail unless comments are ignored")
  134. assert "this_will_fail" not in err
  135. log.info("inline comments are treated as arguments")
  136. _, err = foo.cmd(stdin="version # inline comments are not ignored", code=1)
  137. check.is_in("Too many arguments", err)
  138. log.info("check exit commands")
  139. for command in "exit", "quit":
  140. out, _ = foo.cmd(stdin=command)
  141. check.blank(out)
  142. def run_tests(ctx: Test) -> None:
  143. """Run tests."""
  144. foo, bar = configure_nodes(ctx)
  145. test_shell(foo)
  146. test_version(foo)
  147. test_help(foo)
  148. test_info(foo, bar)
  149. test_pid(foo)
  150. test_debug(foo)
  151. test_log(foo)
  152. test_restart(foo)
  153. with Test("run tests") as context:
  154. run_tests(context)