Ophis/tests/test_ophis.py

222 lines
7.3 KiB
Python
Executable File

#!/usr/bin/python
import sys
import subprocess
import os
import os.path
pythonpath = sys.executable
homepath = os.path.realpath(os.path.dirname(sys.argv[0]))
ophispath = os.path.join(homepath, "..", "bin", "ophis")
failed = 0
# These are some simple routines for forwarding to Ophis. It relies
# on the standard input/output capabilities; we'll only go around it
# when explicitly testing the input/output file capabilities.
def assemble_raw(asm="", options=[]):
p = subprocess.Popen([pythonpath, ophispath] + options,
stdin=subprocess.PIPE, stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
return p.communicate(asm)
def assemble_string(asm, options=[]):
return assemble_raw(asm, ["-o", "-", "-"] + options)
def test_string(test_name, asm, expected, options=[]):
(out, err) = assemble_string(asm, options)
if out == expected:
print "%s: SUCCESS" % test_name
else:
global failed
failed += 1
print "%s: FAILED\nError output:\n%s" % (test_name, err)
def test_file(test_name, fname, ename, options=[]):
f = open(os.path.join(homepath, fname), 'rt')
asm = f.read()
f.close()
if ename is not None:
f = open(os.path.join(homepath, ename), 'rb')
expected = f.read()
f.close()
else: # a test where we expect failure
expected = ''
test_string(test_name, asm, expected, options)
# And now, the actual test suites. First, the most basic techniques
# are tested - these are the ones the test harness *itself* depends
# on, then we start running through the features.
def test_basic():
print
print "==== BASIC OPERATION ===="
test_string('Basic Ophis operation', '.byte "Hello, world!", 10',
'Hello, world!\n')
if failed == 0:
test_file('Basic instructions', 'testbase.oph', 'testbase.bin')
test_file('Basic data pragmas', 'testdata.oph', 'testdata.bin')
test_file('Undocumented instructions', 'test6510.oph', 'test6510.bin',
['-u'])
test_file('65c02 extensions', 'test65c02.oph', 'test65c02.bin', ['-c'])
test_file('Wide instructions', 'testwide.oph', 'testwide.bin', ['-c'])
test_file('Branch restrictions (6502)', 'longbranch.oph', None,
['--no-branch-extend'])
test_file('Branch restrictions (65c02)', 'branch_c02.oph', None,
['-c', '--no-branch-extend'])
test_file('Branch extension, error-free (6502)', 'longbranch.oph',
'longbranch.bin')
test_file('Branch extension, correct code (6502)',
'longbranch_ref.oph', 'longbranch.bin')
test_file('Branch extension, error-free (65c02)', 'branch_c02.oph',
'branch_c02.bin', ['-c'])
test_file('Branch extension, correct code (65c02)',
'branch_c02_ref.oph', 'branch_c02.bin', ['-c'])
def test_outfile():
global failed
print "\n==== INPUT AND OUTPUT ===="
if os.path.exists("ophis.bin"):
print "TEST SUITE FAILED: unclean test environment (ophis.bin exists)"
failed += 1
return
elif os.path.exists("custom.bin"):
print "TEST SUITE FAILED: unclean test environment (custom.bin exists)"
failed += 1
return
# Test 1: Defaults
try:
assemble_raw('.byte "Hello, world!", 10', ['-'])
f = open('ophis.bin', 'rb')
if f.read() != 'Hello, world!\n':
print "Default output filename: FAILED (bad output)"
failed += 1
else:
print "Default output filename: SUCCESS"
f.close()
os.unlink('ophis.bin')
except:
print "Default output filename: FAILED (exception)"
failed += 1
# Test 2: Command line override
try:
assemble_raw('.byte "Hello, world!", 10', ['-', '-o', 'custom.bin'])
f = open('custom.bin', 'rb')
if f.read() != 'Hello, world!\n':
print "Commandline output filename: FAILED (bad output)"
failed += 1
else:
print "Commandline output filename: SUCCESS"
f.close()
os.unlink('custom.bin')
except:
print "Commandline output filename: FAILED (exception)"
failed += 1
# Test 3: Pragma override
try:
assemble_raw('.outfile "custom.bin"\n.byte "Hello, world!", 10', ['-'])
f = open('custom.bin', 'rb')
if f.read() != 'Hello, world!\n':
print "Commandline output filename: FAILED (bad output)"
failed += 1
else:
print "Commandline output filename: SUCCESS"
f.close()
os.unlink('custom.bin')
except:
print "Commandline output filename: FAILED (exception)"
failed += 1
# Test 4: Command line override of .outfile
try:
assemble_raw('.outfile "custom2.bin"\n'
'.byte "Hello, world!", 10', ['-', '-o', 'custom.bin'])
f = open('custom.bin', 'rb')
if f.read() != 'Hello, world!\n':
print "Commandline override of pragma: FAILED (bad output)"
failed += 1
else:
print "Commandline override of pragma: SUCCESS"
f.close()
os.unlink('custom.bin')
except:
print "Commandline override of pragma: FAILED (exception)"
failed += 1
# Test 5: Pragma repetition priority
try:
assemble_raw('.outfile "custom.bin"\n'
'.outfile "custom2.bin"\n'
'.byte "Hello, world!", 10', ['-'])
f = open('custom.bin', 'rb')
if f.read() != 'Hello, world!\n':
print "Pragma repetition: FAILED (bad output)"
failed += 1
else:
print "Pragma repetition: SUCCESS"
f.close()
os.unlink('custom.bin')
except:
print "Pragma repetition: FAILED (exception)"
failed += 1
# Test 6: multiple input files
try:
out = assemble_raw('', ['-o', '-', '-u',
os.path.join(homepath, "testbase.oph"),
os.path.join(homepath, "test6510.oph")])[0]
f = open(os.path.join(homepath, "testbase.bin"), 'rb')
s = f.read()
f.close()
f = open(os.path.join(homepath, "test6510.bin"), 'rb')
s += f.read()
f.close()
if out != s:
print "Multiple input files: FAILED (bad output)"
failed += 1
else:
print "Multiple input files: SUCCESS"
except:
print "Multiple input files: FAILED (exception)"
failed += 1
def test_transforms():
print "\n==== BINARY TRANSFORM PASSES ===="
print "Simple zero page selection: SUCCESS (covered in basic tests)"
test_string('Chained collapse', '.org $fa \n lda + \n lda ^ \n * rts \n',
'\xa5\xfe\xa5\xfc\x60')
test_string('Reversible collapse', '.org $fb \n bne ^+200 \n lda ^ \n',
'\xf0\x03\x4c\xc5\x01\xad\x00\x01')
def test_systematic():
test_outfile()
test_transforms()
if __name__ == '__main__':
print "Using Python interpreter:", pythonpath
test_basic()
if failed == 0:
test_systematic()
else:
print "\nBasic test cases failed, aborting test."
if failed > 0:
print "\nTotal test case failures: %d" % failed
else:
print "\nAll test cases succeeded"