diff --git a/tests/test_ophis.py b/tests/test_ophis.py index e114237..fee6a95 100755 --- a/tests/test_ophis.py +++ b/tests/test_ophis.py @@ -2,6 +2,7 @@ import sys import subprocess +import os import os.path pythonpath = sys.executable @@ -10,14 +11,22 @@ 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_string(asm, options=[]): - p = subprocess.Popen([pythonpath, ophispath, "-o", "-", "-"] + options, + +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: @@ -41,8 +50,13 @@ def test_file(test_name, fname, ename, options=[]): test_string(test_name, asm, expected, options) -if __name__ == '__main__': - print "Using Python interpreter:", pythonpath +# 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: @@ -51,6 +65,7 @@ if __name__ == '__main__': 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, @@ -64,7 +79,143 @@ if __name__ == '__main__': test_file('Branch extension, correct code (65c02)', 'branch_c02_ref.oph', 'branch_c02.bin', ['-c']) - if failed > 0: - print "Total test case failures: %d" % failed + +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 "All test cases succeeded" + print "\nBasic test cases failed, aborting test." + + if failed > 0: + print "\nTotal test case failures: %d" % failed + else: + print "\nAll test cases succeeded" diff --git a/tests/testwide.bin b/tests/testwide.bin new file mode 100644 index 0000000..abdb5ca Binary files /dev/null and b/tests/testwide.bin differ diff --git a/tests/testwide.oph b/tests/testwide.oph new file mode 100644 index 0000000..c7dabb6 --- /dev/null +++ b/tests/testwide.oph @@ -0,0 +1,61 @@ +; Test file for 'wide' 65(c)02 opcode compliance + +; This odd little source file uses every absolute addressing mode of +; every opcode, and uses the opcode itself as the argument to each +; instruction. The resulting binary's bytes are thus in strictly +; increasing numerical order. Since this uses wide instructions, they +; should be separated by zeroes. + +; This test file also uses 65c02 extensions and will require the -c +; options to Ophis. + + + TSB.W $0C + ORA.W $0D + ASL.W $0E + ORA.W $19, Y + TRB.W $1C + ORA.W $1D, X + ASL.W $1E, X + BIT.W $2C + AND.W $2D + ROL.W $2E + AND.W $39, Y + AND.W $3D, X + ROL.W $3E, X + EOR.W $4D + LSR.W $4E + EOR.W $59, Y + EOR.W $5D, X + LSR.W $5E, X + ADC.W $6D + ROR.W $6E + ADC.W $79, Y + ADC.W $7D, X + ROR.W $7E, X + STY.W $8C + STA.W $8D + STX.W $8E + STA.W $99, Y + STZ.W $9C + STA.W $9D, X + STZ.W $9E, X + LDY.W $AC + LDA.W $AD + LDX.W $AE + LDA.W $B9,Y + LDY.W $BC, X + LDA.W $BD, X + LDX.W $BE, Y + CPY.W $CC + CMP.W $CD + DEC.W $CE + CMP.W $D9, Y + CMP.W $DD, X + DEC.W $DE, X + CPX.W $EC + SBC.W $ED + INC.W $EE + SBC.W $F9, Y + SBC.W $FD, X + INC.W $FE, X