diff --git a/pyasm/asm_tests/test_harness b/pyasm/asm_tests/test_harness index 3c05d8b..1c370a7 100755 --- a/pyasm/asm_tests/test_harness +++ b/pyasm/asm_tests/test_harness @@ -23,17 +23,101 @@ import glob import getopt import tempfile import shutil +import string +import struct TestDirectory = './tests' TempPrefix = '_#TEMP#_' +BlockloaderSize = 8 * 16 # 8 lines of 16 bytes + +HighBitMask = 0100000 + + +def oct_dec_int(s): + """Convert string 's' to binary integer.""" + + if s[0] == '0': + result = int(s, base=8) + else: + result = int(s) + + return result +def pyword(word): + """Convert a 16bit value to a real python integer. + + That is, convert 0xFFFF to -1. + """ + + byte = (word >> 8) & 0xff + byte2 = word & 0xff + bstr = chr(byte) + chr(byte2) + return struct.unpack(">h", bstr)[0] + +def get_byte(handle): + """Read one byte from the input file.""" + + byte = handle.read(1) + val = struct.unpack("B", byte)[0] + return val + +def get_word(handle): + """Read one word from input file.""" + + val = (get_byte(handle) << 8) + get_byte(handle) + return val + +def read_block(handle, memory): + """Read data blocks from file, update memory dict. + + Returns False if the end block was read. + """ + + # read load address, num data words and checksum + base_address = get_word(handle) + if base_address & HighBitMask: + return False + + neg_size = get_word(handle) + data_size = -pyword(neg_size) + + checksum = get_word(handle) + + # read data words, placing into dictionary + for _ in range(data_size): + data_word = get_word(handle) + memory[base_address] = data_word + base_address += 1 + + return True + +def get_memory(ptp): + """Read a PTP file, return memory contents as a dictionary. + + Do not return the blockloader contents. + + We don't check the checksum. + """ + + memory = {} + with open(ptp, 'rb') as handle: + # skip leading zeros + while get_byte(handle) == 0: + pass + # then skip block loader + for _ in range(BlockloaderSize - 1): + get_byte(handle) + + # now read blocks until finished + while read_block(handle, memory): + pass + + return memory def test_file(filename): """Test one ASM test file.""" - print('test_file: testing %s' % filename) - # assemble file into known listing file and PTP file lst_file = '%s.lst' % TempPrefix ptp_file = '%s.ptp' % TempPrefix @@ -45,29 +129,59 @@ def test_file(filename): return os.remove(lst_file) - print('processing %s' % ptp_file) # get the test instructions from the ASM file with open(filename, 'rb') as handle: lines = handle.readlines() lines = [line.rstrip() for line in lines] - print('lines=%s' % str(lines)) tests = [] - seen_code = False - for line in lines: - if line.startswith(';'): - if seen_code is True: - tests.append(line[1:].strip()) - else: - seen_code = True - print('tests=%s' % str(tests)) + for (lnum, line) in enumerate(lines): + if line.startswith(';!'): + test = line[2:].strip() + test = test.replace('\t', ' ') + if len(test.split()) < 2: + warn("%d: %s\nbad test comment in file '%s'" + % (lnum+1, line, filename)) + return # finished with this file + tests.append((lnum+1, test)) + # get the generated code from the PTP file + # put memory locations into a dictionary + memory = get_memory(ptp_file) # interpret the test instructions and check generated code + errors = False + for (lnum, test) in tests: + (address, value) = test.split() + address = oct_dec_int(address) + value = oct_dec_int(value) + try: + mem_value = memory[address] + except KeyError: + warn("%s\n" + "%2d: %s\n" + "Test comment has check for address %04o which isn't in block" + % (filename, lnum, test, address)) + else: + if mem_value != value: + errors = True + warn("%s\n" + "%2d: %s\n" + "Memory at address %04o should be %06o, got %06o" + % (filename, lnum, test, address, value, mem_value)) + if errors: + print("File '%s' had errors" % filename) + +def warn(msg): + """Print error message and continue.""" + + print('---------------------------------\n' + '%s\n' + '---------------------------------' % msg) def error(msg): """Print error message and stop.""" - print('\n%s\n\n' % msg) + warn(msg) sys.exit(10) def run_tests(directory, prefix): diff --git a/pyasm/asm_tests/tests/aalpha b/pyasm/asm_tests/tests/aalpha index f1a7656..b8d5bfe 100644 --- a/pyasm/asm_tests/tests/aalpha +++ b/pyasm/asm_tests/tests/aalpha @@ -1,7 +1,7 @@ ; test file org 0100 + law 1 hlt end -; 0100 000000 -;\t$ xxxxxx -; .\tyyyyyy +;! 0100 004001 +;! 0101 000000 diff --git a/pyasm/asm_tests/tests/alpha b/pyasm/asm_tests/tests/alpha index 57c9c34..1a3289e 100644 --- a/pyasm/asm_tests/tests/alpha +++ b/pyasm/asm_tests/tests/alpha @@ -1,3 +1,8 @@ -; test file - smoke test for test_harness - end -; +; test file + org 0100 + law 1 + hlt + end +;! 0100 004002 +;! 0101 000000 +;! 0102 000000