Extends the test framework to prepare for compilation tests
Fix: it2 would have different working for emit eof
This commit is contained in:
parent
1b8333fcfa
commit
7672da6ad3
@ -2,14 +2,14 @@ import os
|
||||
import sys
|
||||
|
||||
def emit(string):
|
||||
sys.stdout.write(string)
|
||||
sys.stdout.buffer.write(string.encode('latin_1'))
|
||||
sys.stdout.flush()
|
||||
|
||||
def trace(header, value):
|
||||
if os.environ.get('TRACE'):
|
||||
sys.stderr.write(f'{header}={value!r}\n')
|
||||
|
||||
eof = chr(0)
|
||||
eof = chr(0xFF)
|
||||
eol = chr(10)
|
||||
quote = chr(34)
|
||||
PEEK = None
|
||||
@ -354,14 +354,14 @@ def emitheader():
|
||||
emitln(" return a + b[0]")
|
||||
emitln("")
|
||||
emitln("def emit(string):")
|
||||
emitln(" sys.stdout.write(string)")
|
||||
emitln(" sys.stdout.buffer.write(string.encode('latin_1'))")
|
||||
emitln(" sys.stdout.flush()")
|
||||
emitln("")
|
||||
emitln("def trace(header, value):")
|
||||
emitln(" if os.environ.get('TRACE'):")
|
||||
emitln(" sys.stderr.write(f'{header}={value!r}\\n')")
|
||||
emitln("")
|
||||
emitln("eof = chr(0)")
|
||||
emitln("eof = chr(0xFF)")
|
||||
emitln("eol = chr(10)")
|
||||
emitln("quote = chr(34)")
|
||||
emitln("")
|
||||
|
||||
@ -431,14 +431,14 @@ emitheader:
|
||||
emitln " return a + b[0]"
|
||||
emitln ""
|
||||
emitln "def emit(string):"
|
||||
emitln " sys.stdout.write(string)"
|
||||
emitln " sys.stdout.buffer.write(string.encode('latin_1'))"
|
||||
emitln " sys.stdout.flush()"
|
||||
emitln ""
|
||||
emitln "def trace(header, value):"
|
||||
emitln " if os.environ.get('TRACE'):"
|
||||
emitln " sys.stderr.write(f'{header}={value!r}\\n')"
|
||||
emitln ""
|
||||
emitln "eof = chr(0)"
|
||||
emitln "eof = chr(0xFF)"
|
||||
emitln "eol = chr(10)"
|
||||
emitln "quote = chr(34)"
|
||||
emitln ""
|
||||
|
||||
@ -532,7 +532,7 @@ emitheader:
|
||||
emitln "#include <string.h>"
|
||||
emitln ""
|
||||
emitln ""
|
||||
emitln "char var_eof[2] = {-1, 0};"
|
||||
emitln "char var_eof[2] = {0xFF, 0};"
|
||||
emitln "char var_eol[2] = {10, 0};"
|
||||
emitln "char var_quote[2] = {34, 0};"
|
||||
emitln "char var_false[1] = {0};"
|
||||
|
||||
14
README.md
14
README.md
@ -121,6 +121,20 @@ Calls the given function with the given arguments. If the function's return valu
|
||||
|
||||
Writes the name and value of the variable passed to stderr if the TRACE environment variable is set.
|
||||
|
||||
### Standard library constants
|
||||
|
||||
#### eof
|
||||
|
||||
End of file character, zero byte.
|
||||
|
||||
#### eol
|
||||
|
||||
End of line character.
|
||||
|
||||
#### quote
|
||||
|
||||
Double quote character.
|
||||
|
||||
### Standard library functions
|
||||
|
||||
#### addstringchar a b
|
||||
|
||||
3
tests/.gitignore
vendored
3
tests/.gitignore
vendored
@ -1 +1,2 @@
|
||||
/*.results
|
||||
/*/*.act.*
|
||||
/Makefile.mk
|
||||
|
||||
@ -1,6 +1,5 @@
|
||||
.SUFFIXES:
|
||||
.PHONY: all clean
|
||||
.PRECIOUS: build/%.it0.py build/%.it0.c
|
||||
.DELETE_ON_ERROR:
|
||||
|
||||
PYVERSION=3.12
|
||||
@ -8,31 +7,23 @@ PYPREFIX=/usr
|
||||
CYTHON=cython3
|
||||
CC=gcc
|
||||
|
||||
# builtincheckfalse is separate since it's supposed to crash. It's a test for the test 'framework', if you will.
|
||||
TESTLIST=$(shell ls *.lang0 | grep -v 'builtincheckfalse' | sed 's/.lang0//')
|
||||
all: verify-results
|
||||
|
||||
all: check
|
||||
Makefile.mk: generate-recipes.py $(wildcard test_stdlib_constants/*.exp.*) $(wildcard test_stdlib_functions/*.exp.*)
|
||||
python3 generate-recipes.py Makefile.mk it0 it1 it2
|
||||
|
||||
check: all-it0.results all-it1.results all-it2.results
|
||||
! grep -v 'Success' $^
|
||||
|
||||
all-it0.results: $(addprefix build/,$(addsuffix .it0, $(TESTLIST))) build/builtincheckfalse.it0
|
||||
-rm -f $@
|
||||
cat test-input.txt | build/builtincheckfalse.it0 2> /dev/null 2>&1 | grep 'Success'
|
||||
$(foreach test,$(TESTLIST), echo -n "$(test) " >> $@; cat test-input.txt | ./build/$(test).it0 >> $@ ; echo "" >> $@ ;)
|
||||
|
||||
all-it1.results: $(addprefix build/,$(addsuffix .it1, $(TESTLIST))) build/builtincheckfalse.it1
|
||||
-rm -f $@
|
||||
cat test-input.txt | build/builtincheckfalse.it1 2> /dev/null 2>&1 | grep 'Success'
|
||||
$(foreach test,$(TESTLIST), echo -n "$(test) " >> $@; cat test-input.txt | ./build/$(test).it1 >> $@ ; echo "" >> $@ ;)
|
||||
|
||||
all-it2.results: $(addprefix build/,$(addsuffix .it2, $(TESTLIST))) build/builtincheckfalse.it2
|
||||
-rm -f $@
|
||||
cat test-input.txt | build/builtincheckfalse.it2 2> /dev/null 2>&1 | grep 'Success'
|
||||
$(foreach test,$(TESTLIST), echo -n "$(test) " >> $@; cat test-input.txt | ./build/$(test).it2 >> $@ ; echo "" >> $@ ;)
|
||||
include Makefile.mk
|
||||
|
||||
clean:
|
||||
-rm -f *.results build/*.it0* build/*.it1* build/*.it2*
|
||||
find build -name '*.c' -delete
|
||||
find build -name '*.it0' -delete
|
||||
find build -name '*.it1' -delete
|
||||
find build -name '*.it2' -delete
|
||||
find build -name '*.py' -delete
|
||||
find build -name '*.tmp' -delete
|
||||
find . -name '*.act.*.result' -delete
|
||||
find . -name '*.act.*.stdout' -delete
|
||||
find . -name '*.act.*.stderr' -delete
|
||||
|
||||
###
|
||||
# it0
|
||||
|
||||
14
tests/build/test_stdlib_functions/.gitignore
vendored
Normal file
14
tests/build/test_stdlib_functions/.gitignore
vendored
Normal file
@ -0,0 +1,14 @@
|
||||
/*.it0
|
||||
/*.it0.c
|
||||
/*.it0.o
|
||||
/*.it0.py
|
||||
/*.it0.py.tmp
|
||||
/*.it1
|
||||
/*.it1.c
|
||||
/*.it1.o
|
||||
/*.it1.py
|
||||
/*.it1.py.tmp
|
||||
/*.it2
|
||||
/*.it2.c
|
||||
/*.it2.c.tmp
|
||||
/*.it2.o
|
||||
103
tests/generate-recipes.py
Normal file
103
tests/generate-recipes.py
Normal file
@ -0,0 +1,103 @@
|
||||
import glob
|
||||
import os
|
||||
import sys
|
||||
|
||||
class Rule:
|
||||
def __init__(self, target: str, prerequisites: list[str], recipe: list[str]) -> None:
|
||||
self.target = target
|
||||
self.prerequisites = prerequisites
|
||||
self.recipe = recipe
|
||||
|
||||
def make_lines(self):
|
||||
return [
|
||||
self.target + ': ' + ' '.join(self.prerequisites),
|
||||
] + [
|
||||
'\t' + line
|
||||
for line in self.recipe
|
||||
] + ['']
|
||||
|
||||
def get_file_list():
|
||||
return glob.glob('test_*/*.lang0')
|
||||
|
||||
def make_rules(file_path, lang0it):
|
||||
result: list[Rule] = []
|
||||
|
||||
act_result = file_path.replace('.lang0', f'.act.{lang0it}.result')
|
||||
act_stdout = file_path.replace('.lang0', f'.act.{lang0it}.stdout')
|
||||
act_stderr = file_path.replace('.lang0', f'.act.{lang0it}.stderr')
|
||||
stdin = file_path.replace('.lang0', '.stdin')
|
||||
exp_stdout = file_path.replace('.lang0', '.exp.stdout')
|
||||
exp_stderr = file_path.replace('.lang0', '.exp.stderr')
|
||||
|
||||
program = file_path.replace('.lang0', f'.{lang0it}')
|
||||
|
||||
if os.path.isfile(exp_stdout) or os.path.isfile(exp_stderr):
|
||||
result.append(Rule(
|
||||
act_stdout,
|
||||
['build/' + program],
|
||||
[
|
||||
(f'cat {stdin} | ' if os.path.isfile(stdin) else 'echo x | ')
|
||||
+ f'build/{program} 1> {act_stdout} 2> {act_stderr}',
|
||||
]
|
||||
))
|
||||
|
||||
exp_list = [exp_stdout, exp_stderr]
|
||||
act_list = [act_stdout, act_stderr]
|
||||
|
||||
result.append(Rule(
|
||||
act_result,
|
||||
[
|
||||
fil
|
||||
for exp_file, act_file in zip(exp_list, act_list, strict=True)
|
||||
if os.path.isfile(exp_file)
|
||||
for fil in [exp_file, act_file]
|
||||
],
|
||||
[
|
||||
'rm -f $@',
|
||||
] + [
|
||||
f'-diff {exp_file} {act_file} >> $@'
|
||||
for exp_file, act_file in zip(exp_list, act_list, strict=True)
|
||||
if os.path.isfile(exp_file)
|
||||
]
|
||||
))
|
||||
|
||||
assert result[-1].prerequisites, f'Missing expectations for {file_path}'
|
||||
|
||||
return result
|
||||
|
||||
def main(program, write_to, *lang0it):
|
||||
rule_list_list = [
|
||||
make_rules(file_path, it)
|
||||
for file_path in get_file_list()
|
||||
for it in lang0it
|
||||
]
|
||||
|
||||
result_targets = [
|
||||
rule.target
|
||||
for rule_list in rule_list_list
|
||||
for rule in rule_list
|
||||
if rule.target.endswith('.result')
|
||||
]
|
||||
|
||||
rule_list_list.append([Rule(
|
||||
'verify-results',
|
||||
result_targets,
|
||||
[
|
||||
'@echo Finding failed test results...',
|
||||
'@find $^ -not -empty -print -exec false {} +',
|
||||
'@echo All tests passed.'
|
||||
]
|
||||
)])
|
||||
|
||||
data = '\n'.join(
|
||||
line
|
||||
for rule_list in rule_list_list
|
||||
for rule in rule_list
|
||||
for line in rule.make_lines()
|
||||
)
|
||||
|
||||
with open(write_to, 'wt', encoding='ASCII') as fil:
|
||||
fil.write(data)
|
||||
|
||||
if __name__ == '__main__':
|
||||
main(*sys.argv)
|
||||
@ -1,3 +0,0 @@
|
||||
main:
|
||||
emit "Success"
|
||||
/
|
||||
1
tests/test_stdlib_constants/test_eof.exp.stdout
Normal file
1
tests/test_stdlib_constants/test_eof.exp.stdout
Normal file
@ -0,0 +1 @@
|
||||
<EFBFBD>
|
||||
3
tests/test_stdlib_constants/test_eof.lang0
Normal file
3
tests/test_stdlib_constants/test_eof.lang0
Normal file
@ -0,0 +1,3 @@
|
||||
main:
|
||||
emit eof
|
||||
/
|
||||
1
tests/test_stdlib_constants/test_eol.exp.stdout
Normal file
1
tests/test_stdlib_constants/test_eol.exp.stdout
Normal file
@ -0,0 +1 @@
|
||||
|
||||
3
tests/test_stdlib_constants/test_eol.lang0
Normal file
3
tests/test_stdlib_constants/test_eol.lang0
Normal file
@ -0,0 +1,3 @@
|
||||
main:
|
||||
emit eol
|
||||
/
|
||||
1
tests/test_stdlib_constants/test_quote.exp.stdout
Normal file
1
tests/test_stdlib_constants/test_quote.exp.stdout
Normal file
@ -0,0 +1 @@
|
||||
"
|
||||
3
tests/test_stdlib_constants/test_quote.lang0
Normal file
3
tests/test_stdlib_constants/test_quote.lang0
Normal file
@ -0,0 +1,3 @@
|
||||
main:
|
||||
emit quote
|
||||
/
|
||||
1
tests/test_stdlib_functions/test_emit.exp.stdout
Normal file
1
tests/test_stdlib_functions/test_emit.exp.stdout
Normal file
@ -0,0 +1 @@
|
||||
Hello, world!
|
||||
4
tests/test_stdlib_functions/test_emit.lang0
Normal file
4
tests/test_stdlib_functions/test_emit.lang0
Normal file
@ -0,0 +1,4 @@
|
||||
main:
|
||||
emit "Hello"
|
||||
emit ", world!"
|
||||
/
|
||||
Loading…
x
Reference in New Issue
Block a user