1 """Simple assertions which print the expected and received values on failure."""
8 Num = T.TypeVar("Num", int, float)
11 def false(value: T.Any) -> None:
12 """Check that value is falsy."""
14 raise ValueError(f'expected "{value}" to be falsy')
17 def true(value: T.Any) -> None:
18 """Check that value is truthy."""
20 raise ValueError(f'expected "{value}" to be truthy', value)
23 def equals(expected: Val, actual: Val) -> None:
24 """Check that the two values are equal."""
25 if expected != actual:
26 raise ValueError(f'expected "{expected}", got "{actual}"')
29 def has_prefix(text: T.AnyStr, prefix: T.AnyStr) -> None:
30 """Check that text has prefix."""
31 if not text.startswith(prefix):
32 raise ValueError(f"expected {text!r} to start with {prefix!r}")
35 def in_range(value: Num, gte: Num, lte: Num) -> None:
36 """Check that value lies in the range [min, max]."""
37 if not gte >= value >= lte:
38 raise ValueError(f"value {value} must be between {gte} and {lte}")
41 def is_in(needle: Val, *haystacks: T.Container[Val]) -> None:
42 """Check that at least one haystack includes needle."""
43 for haystack in haystacks:
44 if needle in haystack:
46 raise ValueError(f'expected any of "{haystacks}" to include "{needle}"')
49 def not_in(needle: Val, *haystacks: T.Container[Val]) -> None:
50 """Check that all haystacks do not include needle."""
51 for haystack in haystacks:
52 if needle in haystack:
53 raise ValueError(f'expected all "{haystacks}" NOT to include "{needle}"')
56 def nodes(node, want_nodes: int) -> None:
57 """Check that node can reach exactly N nodes (including itself)."""
58 log.debug("want %d reachable nodes from tinc %s", want_nodes, node)
59 stdout, _ = node.cmd("dump", "reachable", "nodes")
60 equals(want_nodes, len(stdout.splitlines()))
63 def files_eq(path0: str, path1: str) -> None:
64 """Compare file contents, ignoring whitespace at both ends."""
65 log.debug("comparing files %s and %s", path0, path1)
67 def read(path: str) -> str:
68 log.debug("reading file %s", path)
69 with open(path, "r", encoding="utf-8") as f:
70 return f.read().strip()
72 content0 = read(path0)
73 content1 = read(path1)
75 if content0 != content1:
76 raise ValueError(f"expected files {path0} and {path1} to match")