nxu/tester.py

79 lines
2.3 KiB
Python

#!/usr/bin/python
from os import environ
from subprocess import Popen, PIPE
from random import randint
u5 = {'sz': 1 << 5, 'fmt': b'%02x'}
u8 = {'sz': 1 << 8, 'fmt': b'%02x'}
u16 = {'sz': 1 << 16, 'fmt': b'%04x'}
u32 = {'sz': 1 << 32, 'fmt': b'%08x'}
def fmt(gx, x):
return gx['fmt'].decode('utf-8') % (x % gx['sz'])
def testcase(p, sym, args, out, f):
xs = [randint(0, a[1]['sz'] - 1) for a in args]
p.stdin.write(sym)
for i in range(0, len(args)):
x = xs[i]
g = args[i][1]
p.stdin.write(b' ')
p.stdin.write(g['fmt'] % x)
p.stdin.write(b'\n')
p.stdin.flush()
got = p.stdout.readline().strip().decode('utf-8')
z = f(*xs)
expected = fmt(out, z)
if got == expected:
return None
else:
res = {'got': got, 'expected': expected}
for (name, x) in args: res[name] = x
return res
def test(p, runs, sym, args, out, f):
fails = 0
cases = []
maximum = (1 << 32) - 1
for i in range(0, runs):
case = testcase(p, sym, args, out, f)
if case is not None:
fails += 1
cases.append(case)
name = sym.decode('utf-8')
if fails == 0:
print('%s passed %d runs' % (name, runs))
else:
print('%s failed %d/%d runs (%r)' % (name, fails, runs, cases))
def pipe():
cli = environ['HOME'] + '/w/uxn/bin/uxncli'
return Popen([cli, 'run.rom'], stdin=PIPE, stdout=PIPE)
def bitcount(x):
n = 0
while x > 0:
n += 1
x = x >> 1
return n
def main():
runs = 100
p = pipe()
test(p, runs, b'+', [('x', u32), ('y', u32)], u32, lambda x, y: x + y)
test(p, runs, b'-', [('x', u32), ('y', u32)], u32, lambda x, y: x - y)
test(p, runs, b'*', [('x', u32), ('y', u32)], u32, lambda x, y: x * y)
test(p, runs, b'L', [('x', u32), ('y', u5)], u32, lambda x, y: x << y)
test(p, runs, b'B', [('x', u32)], u8, bitcount)
test(p, runs, b'&', [('x', u32), ('y', u32)], u32, lambda x, y: x & y)
test(p, runs, b'|', [('x', u32), ('y', u32)], u32, lambda x, y: x | y)
test(p, runs, b'^', [('x', u32), ('y', u32)], u32, lambda x, y: x ^ y)
test(p, runs, b'~', [('x', u32)], u32, lambda x: ~x)
test(p, runs, b'N', [('x', u32)], u32, lambda x: -x)
p.stdin.close()
p.stdout.close()
if __name__ == "__main__":
main()