forked from curl/trurl
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathtest.py
145 lines (110 loc) · 3.87 KB
/
test.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
#!/usr/bin/python3
from typing import Any
import json
import subprocess
import sys
import shlex
from dataclasses import dataclass, asdict
IGNORESTDERR = True
TESTFILE = "./tests.json"
if sys.platform == "win32" or sys.platform == "cygwin":
BASECMD = "./trurl.exe" # windows
else:
BASECMD = "./trurl" # linux
RED = "\033[91m" # used to mark unsuccessful tests
NOCOLOR = "\033[0m"
TAB = "\x09"
@dataclass
class CommandOutput:
stdout: Any
returncode: int
stderr: str
def stripDict(d):
new = {}
for key in d:
if type(d[key]) == str:
new[key] = d[key].strip()
else:
new[key] = d[key]
return new
class TestCase:
def __init__(self, testIndex, **testCase):
self.testIndex = testIndex
self.cmdline = testCase["cmdline"]
self.expected = stripDict(testCase["expected"])
self.commandOutput: CommandOutput = None
self.testPassed: bool = False
def runCommand(self, stdinkeyword: str):
# returns false if the command does not contain keyword
if self.cmdline.find(stdinkeyword) == -1:
return False
output = subprocess.run(
shlex.split(f"{BASECMD} {self.cmdline}"),
capture_output=True,
)
# testresult is bytes by default, change to string and remove line endings with strip if we expect a string
if type(self.expected["stdout"]) == str:
stdout = output.stdout.decode().strip()
else:
# if we dont expect string, parse to json
stdout = json.loads(output.stdout)
# assume stderr is always going to be string
stderr = output.stderr.decode().strip()
if (IGNORESTDERR):
self.expected.pop("stderr")
self.commandOutput = CommandOutput(stdout, output.returncode, stderr)
return True
def test(self):
# return true only if stdout, stderr and errorcode is equal to the ones found in testfile
tests = []
for item in self.expected:
passed = self.expected[item] == asdict(self.commandOutput)[item]
tests.append(passed)
self.testPassed = all(tests)
return self.testPassed
def printVerbose(self):
print(RED, end="")
self.printConcise()
print(NOCOLOR, end="")
for item in self.expected:
itemFail = self.expected[item] != asdict(self.commandOutput)[item]
print(f"--- {item} --- ")
print("expected: ")
print(f"'{self.expected[item]}'")
print("got:")
print(RED if itemFail else "", end="")
print(f"'{asdict(self.commandOutput)[item]}'")
print(NOCOLOR, end="")
print()
def printConcise(self):
o = f"{self.testIndex}: {'passed' if self.testPassed else 'failed'}{TAB}'{self.cmdline}'"
print(o)
def main():
with open(TESTFILE, "r") as file:
allTests = json.load(file)
testIndexesToRun = []
# if argv[1] exists and starts with int
stdinfilter = ""
testIndexesToRun = list(range(len(allTests)))
if len(sys.argv) > 1:
if sys.argv[1][0].isnumeric():
# run only test cases sepereated by ","
testIndexesToRun = []
for caseIndex in sys.argv[1].split(","):
testIndexesToRun.append(int(caseIndex))
else:
stdinfilter = sys.argv[1]
numTestsPassed = 0
for testIndex in testIndexesToRun:
test = TestCase(testIndex, **allTests[testIndex])
if test.runCommand(stdinfilter):
if test.test(): # passed
test.printConcise()
numTestsPassed += 1
else:
test.printVerbose()
# finally print the results to terminal
print("finished:")
print(f"{numTestsPassed}/{len(testIndexesToRun)} tests passed")
if __name__ == "__main__":
main()