Skip to content

Commit 487c5fc

Browse files
authored
Merge pull request bitcoin-dev-project#384 from mplsgrant/2024-06-test-base-log-file
Allow asserting againt TestBase log file
2 parents e01a422 + 4098f6e commit 487c5fc

File tree

2 files changed

+59
-30
lines changed

2 files changed

+59
-30
lines changed

test/dag_connection_test.py

Lines changed: 14 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
#!/usr/bin/env python3
22

33
import os
4-
import time
54
from pathlib import Path
65

76
from test_base import TestBase
@@ -13,13 +12,13 @@ def __init__(self):
1312
self.graph_file_path = (
1413
Path(os.path.dirname(__file__)) / "data" / "ten_semi_unconnected.graphml"
1514
)
16-
self.scenario_timeout = 180 # seconds
1715

1816
def run_test(self):
1917
self.start_server()
2018
try:
2119
self.setup_network()
2220
self.run_connect_dag_scenario()
21+
self.run_connect_dag_scenario_post_connection()
2322
finally:
2423
self.stop_server()
2524

@@ -31,31 +30,21 @@ def setup_network(self):
3130

3231
def run_connect_dag_scenario(self):
3332
self.log.info("Running connect_dag scenario")
33+
self.log_expected_msgs = [
34+
"Successfully ran the connect_dag.py scenario using a temporary file"
35+
]
36+
self.log_unexpected_msgs = ["Test failed."]
3437
self.warcli("scenarios run-file test/framework_tests/connect_dag.py")
38+
self.wait_for_all_scenarios()
39+
self.assert_log_msgs()
3540

36-
start_time = time.time()
37-
while time.time() - start_time < self.scenario_timeout:
38-
running_scenarios = self.rpc("scenarios_list_running")
39-
if not running_scenarios:
40-
self.log.info("Scenario completed successfully")
41-
return
42-
43-
if len(running_scenarios) == 1 and not running_scenarios[0]["active"]:
44-
self.log.info("Scenario completed successfully")
45-
return
46-
47-
time.sleep(1)
48-
49-
self.log.error(f"Scenario did not complete within {self.scenario_timeout} seconds")
50-
self.stop_running_scenario()
51-
raise AssertionError(f"Scenario timed out after {self.scenario_timeout} seconds")
52-
53-
def stop_running_scenario(self):
54-
running_scenarios = self.rpc("scenarios_list_running")
55-
if running_scenarios:
56-
pid = running_scenarios[0]["pid"]
57-
self.log.warning(f"Stopping scenario with PID {pid}")
58-
self.warcli(f"scenarios stop {pid}", False)
41+
def run_connect_dag_scenario_post_connection(self):
42+
self.log.info("Running connect_dag scenario")
43+
self.log_expected_msgs = ["Successfully ran the connect_dag.py scenario"]
44+
self.log_unexpected_msgs = ["Test failed"]
45+
self.warcli("scenarios run-file test/framework_tests/connect_dag.py")
46+
self.wait_for_all_scenarios()
47+
self.assert_log_msgs()
5948

6049

6150
if __name__ == "__main__":

test/test_base.py

Lines changed: 45 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,10 @@
33
import logging
44
import logging.config
55
import os
6+
import re
67
import threading
78
from pathlib import Path
8-
from subprocess import PIPE, STDOUT, Popen, run
9+
from subprocess import PIPE, Popen, run
910
from tempfile import mkdtemp
1011
from time import sleep
1112

@@ -20,6 +21,9 @@ def __init__(self):
2021
self.setup_environment()
2122
self.setup_logging()
2223
atexit.register(self.cleanup)
24+
self.log_expected_msgs: None | [str] = None
25+
self.log_unexpected_msgs: None | [str] = None
26+
self.log_msg_assertions_passed = False
2327
self.log.info("Warnet test base initialized")
2428

2529
def setup_environment(self):
@@ -59,6 +63,19 @@ def cleanup(self, signum=None, frame=None):
5963
self.server_thread.join()
6064
self.server = None
6165

66+
def _print_and_assert_msgs(self, message):
67+
print(message)
68+
if (self.log_expected_msgs or self.log_unexpected_msgs) and assert_log(
69+
message, self.log_expected_msgs, self.log_unexpected_msgs
70+
):
71+
self.log_msg_assertions_passed = True
72+
73+
def assert_log_msgs(self):
74+
assert (
75+
self.log_msg_assertions_passed
76+
), f"Log assertion failed. Expected message not found: {self.log_expected_msgs}"
77+
self.log_msg_assertions_passed = False
78+
6279
def warcli(self, cmd, network=True):
6380
self.log.debug(f"Executing warcli command: {cmd}")
6481
command = ["warcli"] + cmd.split()
@@ -94,19 +111,19 @@ def start_server(self):
94111
# TODO: check for conflicting warnet process
95112
# maybe also ensure that no conflicting docker networks exist
96113

97-
# For kubernetes we assume the server is started outside test base
114+
# For kubernetes we assume the server is started outside test base,
98115
# but we can still read its log output
99116
self.log.info("Starting Warnet server")
100117
self.server = Popen(
101-
["kubectl", "logs", "-f", "rpc-0"],
118+
["kubectl", "logs", "-f", "rpc-0", "--since=1s"],
102119
stdout=PIPE,
103-
stderr=STDOUT,
120+
stderr=PIPE,
104121
bufsize=1,
105122
universal_newlines=True,
106123
)
107124

108125
self.server_thread = threading.Thread(
109-
target=self.output_reader, args=(self.server.stdout, print)
126+
target=self.output_reader, args=(self.server.stdout, self._print_and_assert_msgs)
110127
)
111128
self.server_thread.daemon = True
112129
self.server_thread.start()
@@ -176,3 +193,26 @@ def get_scenario_return_code(self, scenario_name):
176193
if len(scns) == 0:
177194
raise Exception(f"Scenario {scenario_name} not found in running scenarios")
178195
return scns[0]["return_code"]
196+
197+
198+
def assert_equal(thing1, thing2, *args):
199+
if thing1 != thing2 or any(thing1 != arg for arg in args):
200+
raise AssertionError(
201+
"not({})".format(" == ".join(str(arg) for arg in (thing1, thing2) + args))
202+
)
203+
204+
205+
def assert_log(log_message, expected_msgs, unexpected_msgs=None) -> bool:
206+
if unexpected_msgs is None:
207+
unexpected_msgs = []
208+
assert_equal(type(expected_msgs), list)
209+
assert_equal(type(unexpected_msgs), list)
210+
211+
found = True
212+
for unexpected_msg in unexpected_msgs:
213+
if re.search(re.escape(unexpected_msg), log_message, flags=re.MULTILINE):
214+
raise AssertionError(f"Unexpected message found in log: {unexpected_msg}")
215+
for expected_msg in expected_msgs:
216+
if re.search(re.escape(expected_msg), log_message, flags=re.MULTILINE) is None:
217+
found = False
218+
return found

0 commit comments

Comments
 (0)