Skip to content

Commit 296c26d

Browse files
committed
Resolved .nvimrc merge conflicts
2 parents d76d176 + 6f4845a commit 296c26d

File tree

2 files changed

+171
-48
lines changed

2 files changed

+171
-48
lines changed

.nvimrc

+2
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
11
" Allow us to build our application(s) with a keystroke.
22
set makeprg=build
3+
34
" Create errorformat strings for detecting clang error messages.
45
" (We consume ../ from the beginning of the filename due to how build.bat
56
" works.)
67
set errorformat+=%f(%l\\,%c):\ %trror:\ %m
78
set errorformat+=%f(%l\\,%c):\ %tarning:\ %m
89

910
noremap <F4> :make!<cr>:cwindow<cr>
11+
1012
" Allow us to run the tests with a keystroke.
1113
noremap <F5> :!test<cr>

scripts/tester.py

+169-48
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
"""
99

1010

11-
import os, subprocess, struct, enum, sys
11+
import os, subprocess, struct, enum, sys, functools, inspect
1212

1313

1414
BUILD_DIR = "build"
@@ -21,6 +21,16 @@
2121
TESTS_ERRORED = 0
2222

2323

24+
def infile(name):
25+
global DATA_DIR
26+
return DATA_DIR + "/" + name + ".sq"
27+
28+
29+
def outfile(name):
30+
global BUILD_DIR
31+
return BUILD_DIR + "/" + name + ".x"
32+
33+
2434
def build(input_file, output_file):
2535
""" Takes in a SUBLEQ filename as input and invokes the assembler on it,
2636
producing an output binary of similar name in the build directory. The
@@ -29,6 +39,8 @@ def build(input_file, output_file):
2939
binary. If an error occurred, then the output value is the message output
3040
by the assembler.
3141
"""
42+
global ASSEMBLER
43+
3244
result = subprocess.run([ ASSEMBLER,
3345
input_file,
3446
output_file
@@ -39,73 +51,182 @@ def build(input_file, output_file):
3951
return result.stdout, result.returncode
4052

4153

42-
##
54+
def unpack(file):
55+
data = None
56+
57+
with open(file, "rb") as f:
58+
data = [ i[0] for i in struct.iter_unpack("i", f.read()) ]
59+
60+
return data
61+
62+
63+
class TestResult():
64+
65+
def __init__(self, name, success, messages = []):
66+
self.test = name
67+
self.success = success
68+
self.messages = messages
69+
70+
def report(self):
71+
status = "PASSED" if self.success else "FAILED"
72+
73+
message = f"==> Test \"{self.test}\" {status}"
74+
75+
if self.success is not True:
76+
def prepend_tab(string):
77+
return "\t"+string
78+
79+
message = message+"\n" + "\n".join(map(prepend_tab, self.messages))
80+
81+
print(message)
82+
83+
84+
class TestAssertion():
85+
86+
def __init__(self, expected, actual, success, message):
87+
self.expected = expected
88+
self.actual = actual
89+
self.success = success
90+
self.message = message
91+
92+
def report(self):
93+
status = "Failed to assert" if not self.success else "Asserted"
94+
return f"{status} that {self.message}"
95+
96+
97+
class Test():
98+
99+
def __init__(self, name, test):
100+
self.name = name
101+
self._test = test
102+
self._asserts = []
103+
self._errored = False
104+
105+
def run(self):
106+
self._test(self)
107+
108+
# Get all the messages from the assertions that failed.
109+
messages = [ a.report() for a in self._asserts if not a.success ]
110+
111+
passing = len(messages) == 0
112+
113+
return TestResult(self.name, passing and not self._errored, messages)
114+
115+
def error(self, message):
116+
print(f"==> TEST ERROR: \t{message}")
117+
118+
def is_equal(self, expected, actual):
119+
self._asserts.append(TestAssertion(
120+
expected,
121+
actual,
122+
expected == actual,
123+
f"{expected} == {actual}"
124+
))
125+
126+
127+
class Tester():
128+
129+
def __init__(self):
130+
self._tests = []
131+
132+
def add_test(self, test):
133+
self._tests.append(Test(test.__name__, test))
134+
135+
def run(self):
136+
results = []
137+
138+
for test in self._tests:
139+
result = test.run()
140+
result.report()
141+
142+
results.append(result)
143+
144+
failing_tests = len([ r for r in results if r.success is False ])
145+
146+
if failing_tests > 0:
147+
passing_tests = len(self._tests) - failing_tests
148+
print(f"\n\t{passing_tests} / {len(self._tests)} tests passing.")
149+
150+
else:
151+
print("\n\tAll tests passing.")
152+
153+
154+
155+
tester = Tester()
156+
157+
43158
## ASSEMBLER TESTS
44-
##
45159

46-
# TODO[joe] Create tests that confirm assembler error messages?
47-
# These would include usage errors and syntax errors. This functionality would
48-
# be desirable at some point, when we get around to implementing syntax error
49-
# checking. However, this is sufficient for now.
50-
assembler_tests = {
51-
'basic': [ 0, 0, -1 ],
52-
'next_address': [ 1, 2, 3 ],
53-
'complex': [ 0, 1, 3, 0, 1, 6, 0, 0, -1 ],
54-
'two_address': [ 0, 1, 3 ],
55-
'one_address': [ 1, 1, 3 ],
56-
}
160+
@tester.add_test
161+
def basic(test):
162+
_, returncode = build(infile(test.name), outfile(test.name))
57163

164+
if returncode:
165+
test.error(f"Build for {outfile(self)} exited with code {returncode}")
58166

59-
for test, expected_result in assembler_tests.items():
60-
test_file = DATA_DIR+"\\"+test+".sq"
61-
output_file = test_file.replace(".sq", ".x").replace(DATA_DIR, BUILD_DIR)
167+
test.is_equal([ 0, 0, -1 ], unpack(outfile(test.name)))
62168

63-
output, returncode = build(test_file, output_file)
169+
@tester.add_test
170+
def next_address(test):
171+
_, returncode = build(infile(test.name), outfile(test.name))
64172

65173
if returncode:
66-
if output:
67-
print(output.decode("utf-8"))
174+
test.error(f"Build for {outfile(self)} exited with code {returncode}")
68175

69-
print("==> ERROR: Build for \"{}\" exited with code {}".format(test_file,
70-
returncode))
176+
test.is_equal([ 1, 2, 3 ], unpack(outfile(test.name)))
71177

72-
TESTS_ERRORED = TESTS_ERRORED + 1
73-
74-
continue
178+
@tester.add_test
179+
def two_address(test):
180+
_, returncode = build(infile(test.name), outfile(test.name))
75181

76-
program = []
182+
if returncode:
183+
test.error(f"Build for {outfile(self)} exited with code {returncode}")
77184

78-
with open(output_file, "rb") as program_file:
79-
program = [ i[0] for i in struct.iter_unpack("i", program_file.read()) ]
185+
test.is_equal([ 0, 1, 3 ], unpack(outfile(test.name)))
80186

81-
if not program == expected_result:
82-
print("\nExpected {}, got {}\n".format(expected_result, program))
83-
print("==> FAILED: \"{}\" ".format(test_file))
187+
@tester.add_test
188+
def one_address(test):
189+
_, returncode = build(infile(test.name), outfile(test.name))
84190

85-
else:
86-
print("==> PASSED: \"{}\" ".format(test_file))
191+
if returncode:
192+
test.error(f"Build for {outfile(self)} exited with code {returncode}")
87193

88-
TESTS_PASSED = TESTS_PASSED + 1
194+
test.is_equal([ 1, 1, 3 ], unpack(outfile(test.name)))
89195

196+
@tester.add_test
197+
def label(test):
198+
_, returncode = build(infile(test.name), outfile(test.name))
90199

91-
##
92-
## EMULATOR TESTS
93-
##
200+
if returncode:
201+
test.error(f"Build for {outfile(self)} exited with code {returncode}")
202+
203+
test.is_equal([ 0, 0, -1], unpack(outfile(test.name)))
94204

95-
emulator_tests = {}
205+
@tester.add_test
206+
def identifier(test):
207+
_, returncode = build(infile(test.name), outfile(test.name))
96208

209+
if returncode:
210+
test.error(f"Build for {outfile(self)} exited with code {returncode}")
211+
212+
test.is_equal([ 0, 0, -1 ], unpack(outfile(test.name)))
97213

98-
##
99-
## Test Statistics
100-
##
214+
@tester.add_test
215+
def complex(test):
216+
_, returncode = build(infile(test.name), outfile(test.name))
217+
218+
if returncode:
219+
test.error(f"Build for {outfile(self)} exited with code {returncode}")
101220

102-
TOTAL_TESTS = len(assembler_tests) + len(emulator_tests)
221+
test.is_equal([ 0, 1, 3, 0, 1, 6, 0, 0, -1 ], unpack(outfile(test.name)))
222+
223+
224+
## EMULATOR TESTS
225+
# todo(jrm): Write the emulator tests
103226

104-
# Total tests passed vs total tests run.
105-
print("\n {} / {} tests passed".format(TESTS_PASSED,
106-
len(assembler_tests)+len(emulator_tests)))
107227

108-
# Total tests that errored.
109-
print(" {} tests errored".format(TESTS_ERRORED))
228+
# Run the tests
229+
tester.run()
110230

111-
sys.exit(TOTAL_TESTS - TESTS_PASSED)
231+
# todo(jrm) have tester.run() return the number of tests failed.
232+
# sys.exit(TOTAL_TESTS - TESTS_PASSED)

0 commit comments

Comments
 (0)