Skip to content

Commit f35a86f

Browse files
committed
IS-1426 update tests to run in self contained catch process to avoid static state leaking across tests
1 parent 545ef73 commit f35a86f

2 files changed

Lines changed: 109 additions & 41 deletions

File tree

Consensust.h

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -53,9 +53,7 @@ class Consensust {
5353
class StartFromScratch {
5454
public:
5555
StartFromScratch() {
56-
int i = system( "rm -rf /tmp/*.db.*" );
57-
i = system( "rm -rf /tmp/*.db" );
58-
i++; // make compiler happy
56+
system( "rm -rf /tmp/*.db" );
5957
Consensust::setConfigDirPath( boost::filesystem::system_complete( "." ) );
6058

6159
#ifdef GOOGLE_PROFILE

scripts/tests.py

Lines changed: 108 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -26,63 +26,133 @@
2626
import subprocess
2727

2828

29-
def run_without_check(_command):
29+
SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__))
30+
REPO_ROOT = os.path.abspath(os.path.join(SCRIPT_DIR, ".."))
31+
32+
33+
def print_separator(_label, _char="="):
34+
line = _char * 80
35+
print("\n" + line)
36+
print(_label)
37+
print(line)
38+
39+
40+
def normalize_catch_expression(_testType):
41+
if len(_testType) >= 2 and _testType[0] == _testType[-1] and _testType[0] in ("'", '"'):
42+
return _testType[1:-1]
43+
return _testType
44+
45+
46+
def list_catch_test_names(_consensustExecutive, _testType):
47+
result = subprocess.run(
48+
[_consensustExecutive, normalize_catch_expression(_testType), "--list-test-names-only"],
49+
check=False,
50+
stdout=subprocess.PIPE,
51+
stderr=subprocess.PIPE,
52+
universal_newlines=True,
53+
)
54+
test_names = [line.strip() for line in result.stdout.splitlines() if line.strip()]
55+
if len(test_names) == 0:
56+
error_output = result.stderr.strip()
57+
raise RuntimeError(
58+
"Could not list Catch tests for {} (exit code {}): {}".format(
59+
_testType,
60+
result.returncode,
61+
error_output or "no tests matched",
62+
)
63+
)
64+
return test_names
65+
66+
67+
def run(_command, _label=None):
68+
if _label:
69+
print_separator(_label)
3070
print(">" + _command)
31-
subprocess.call(_command, shell=True)
71+
subprocess.check_call(_command, shell=True)
3272

3373

34-
def run(_command):
35-
print(">" + _command)
36-
subprocess.check_call(_command, shell=True)
74+
def run_args(_command, _label=None):
75+
if _label:
76+
print_separator(_label)
77+
print(">" + " ".join(_command))
78+
subprocess.check_call(_command)
79+
3780

81+
def run_catch_tests(_consensustExecutive, _testType, _label):
82+
# By default, split catch tests into separate runs
83+
# There are currently static variables that bleed state between tests
84+
# if we try running all under the same catch session, causing tests to fail
3885

39-
def unitTest(_consensustExecutive, _testType):
40-
run("rm -f ./core")
41-
run(_consensustExecutive + " " + _testType)
86+
test_names = list_catch_test_names(_consensustExecutive, _testType)
87+
if len(test_names) == 0:
88+
raise RuntimeError("No Catch tests matched: " + _testType)
89+
print_separator(_label + " (" + str(len(test_names)) + " cases)")
90+
91+
for index, test_name in enumerate(test_names, 1):
92+
run_args(
93+
# use '"' delimiters to ensure test names with commas are treated as a single argument
94+
[_consensustExecutive, '"' + test_name + '"'],
95+
"[{}/{}] {}".format(index, len(test_names), test_name),
96+
)
97+
98+
99+
def unitTest(_consensustExecutive, _testType, _label=None):
100+
label = _label or _testType
101+
run("rm -f ./core", "Cleanup for " + label)
102+
run_catch_tests(_consensustExecutive, _testType, "Catch tests: " + label)
42103

43104

44105
def fullConsensusTest(_test, _consensustExecutive, _testType):
45-
testDir = "test/" + _test
106+
testDir = os.path.join(REPO_ROOT, "test", _test)
46107
os.chdir(testDir)
47-
run("pwd")
48-
run("rm -rf " + testDir + "/core")
49-
run("rm -rf /tmp/*.db*")
50-
run(_consensustExecutive + " " + _testType)
51-
os.chdir("../..")
108+
run("pwd", "Entering " + testDir)
109+
run("rm -rf ./core", "Cleanup core files for " + _test)
110+
run("rm -rf /tmp/*.db*", "Cleanup db files for " + _test)
111+
run_catch_tests(
112+
_consensustExecutive,
113+
_testType,
114+
"Consensus test: " + _test + " " + _testType,
115+
)
116+
os.chdir(REPO_ROOT)
52117

53118

54119
def getConsensustExecutive():
55-
run_without_check("cp -f cmake-build-debug/consensust /tmp/consensust")
56-
run_without_check("cp -f build/consensust /tmp/consensust")
57-
consensustExecutive = "/tmp/consensust"
58-
return consensustExecutive
120+
candidates = [
121+
os.path.join(REPO_ROOT, "cmake-build-debug", "consensust"),
122+
os.path.join(REPO_ROOT, "build", "consensust"),
123+
]
124+
125+
for candidate in candidates:
126+
if os.path.isfile(candidate):
127+
return candidate
128+
129+
raise RuntimeError(
130+
"Could not find consensust binary. Looked in: {}".format(", ".join(candidates))
131+
)
59132

60133

61134
print("Starting tests.")
62135

63-
os.chdir("..")
136+
os.chdir(REPO_ROOT)
64137

65138
run("ccache -M 20G")
66139

67140
consensustExecutive = getConsensustExecutive()
68141

69142
# Run all non-end-to-end and non-performance unit tests
70-
unitTest(consensustExecutive, "~[end-to-end]~[performance]")
71-
unitTest(consensustExecutive, "'[end-to-end][db]'")
72-
73-
74-
# fullConsensusTest("sixteennodes", consensustExecutive, "[consensus-finalization-download]")
75-
76-
# try:
77-
# fullConsensusTest("two_out_of_four", consensustExecutive, "[consensus-stuck]")
78-
# except:
79-
# print("Success")
80-
81-
82-
fullConsensusTest("onenode", consensustExecutive, "[consensus-basic]")
83-
fullConsensusTest("twonodes", consensustExecutive, "[consensus-basic]")
84-
fullConsensusTest("fournodes", consensustExecutive, "[consensus-basic]")
85-
#fullConsensusTest("sixteennodes", consensustExecutive, "[consensus-basic]")
86-
#fullConsensusTest("fournodes_catchup", consensustExecutive, "[consensus-basic]")
87-
#fullConsensusTest("three_out_of_four", consensustExecutive, "[consensus-basic]")
88-
143+
unitTest(
144+
consensustExecutive,
145+
"~[end-to-end]~[performance]",
146+
"Non-end-to-end non-performance",
147+
)
148+
149+
unitTest(
150+
consensustExecutive,
151+
"'[end-to-end][db]'",
152+
"End-to-end db tests",
153+
)
154+
155+
156+
# fullConsensusTest("onenode", consensustExecutive, "[consensus-basic]")
157+
# fullConsensusTest("twonodes", consensustExecutive, "[consensus-basic]")
158+
# fullConsensusTest("fournodes", consensustExecutive, "[consensus-basic]")

0 commit comments

Comments
 (0)