fix testing infra
parent
dd77d1b387
commit
e1fbe4f11d
@ -1,73 +0,0 @@
|
|||||||
import contextlib
|
|
||||||
import os
|
|
||||||
from abc import abstractmethod
|
|
||||||
from tempfile import NamedTemporaryFile
|
|
||||||
from typing import Optional, Union, Tuple
|
|
||||||
from unittest import TestCase
|
|
||||||
|
|
||||||
from riscemu import CPU, UserModeCPU, InstructionSetDict, RunConfig
|
|
||||||
from riscemu.types import Program
|
|
||||||
|
|
||||||
|
|
||||||
class EndToEndTest(TestCase):
|
|
||||||
|
|
||||||
def __init__(self, cpu: Optional[CPU] = None):
|
|
||||||
super().__init__()
|
|
||||||
if cpu is None:
|
|
||||||
cpu = UserModeCPU(InstructionSetDict.values(), RunConfig())
|
|
||||||
self.cpu = cpu
|
|
||||||
|
|
||||||
@abstractmethod
|
|
||||||
def get_source(self) -> Tuple[str, Union[bytes, str, bytearray]]:
|
|
||||||
"""
|
|
||||||
This method returns the source code of the program
|
|
||||||
:return:
|
|
||||||
"""
|
|
||||||
pass
|
|
||||||
|
|
||||||
def test_run_program(self):
|
|
||||||
"""
|
|
||||||
Runs the program and verifies output
|
|
||||||
:return:
|
|
||||||
"""
|
|
||||||
with self.with_source_file() as names:
|
|
||||||
fname, orig_name = names
|
|
||||||
loader = self.cpu.get_best_loader_for(fname)
|
|
||||||
self.program = loader.instantiate(fname, loader.get_options([])).parse()
|
|
||||||
self._change_program_file_name(self.program, orig_name)
|
|
||||||
self.cpu.load_program(self.program)
|
|
||||||
self.after_program_load(self.program)
|
|
||||||
if isinstance(self.cpu, UserModeCPU):
|
|
||||||
self.cpu.setup_stack()
|
|
||||||
try:
|
|
||||||
self.cpu.launch(self.program)
|
|
||||||
except Exception as ex:
|
|
||||||
if self.is_exception_expected(ex):
|
|
||||||
pass
|
|
||||||
raise ex
|
|
||||||
|
|
||||||
@contextlib.contextmanager
|
|
||||||
def with_source_file(self):
|
|
||||||
name, content = self.get_source()
|
|
||||||
if isinstance(content, str):
|
|
||||||
f = NamedTemporaryFile('w', suffix=name, delete=False)
|
|
||||||
else:
|
|
||||||
f = NamedTemporaryFile('wb', suffix=name, delete=False)
|
|
||||||
f.write(content)
|
|
||||||
f.flush()
|
|
||||||
f.close()
|
|
||||||
try:
|
|
||||||
yield f.name, name
|
|
||||||
finally:
|
|
||||||
os.unlink(f.name)
|
|
||||||
|
|
||||||
def after_program_load(self, program):
|
|
||||||
pass
|
|
||||||
|
|
||||||
def is_exception_expected(self, ex: Exception) -> bool:
|
|
||||||
return False
|
|
||||||
|
|
||||||
def _change_program_file_name(self, program: Program, new_name: str):
|
|
||||||
program.name = new_name
|
|
||||||
for sec in program.sections:
|
|
||||||
sec.owner = new_name
|
|
@ -1,7 +1,15 @@
|
|||||||
from unittest import TestCase
|
|
||||||
|
|
||||||
from riscemu.helpers import *
|
from riscemu.helpers import *
|
||||||
|
|
||||||
|
def test_align_address():
|
||||||
|
assert align_addr(3, 1) == 3
|
||||||
|
assert align_addr(3, 2) == 4
|
||||||
|
assert align_addr(3, 4) == 4
|
||||||
|
assert align_addr(3, 8) == 8
|
||||||
|
assert align_addr(8, 8) == 8
|
||||||
|
|
||||||
class TestHelpers(TestCase):
|
|
||||||
pass
|
def test_parse_numeric():
|
||||||
|
assert parse_numeric_argument('13') == 13
|
||||||
|
assert parse_numeric_argument('0x100') == 256
|
||||||
|
assert parse_numeric_argument('-13') == -13
|
||||||
|
@ -1,19 +1,15 @@
|
|||||||
from unittest import TestCase
|
|
||||||
|
|
||||||
from riscemu.types import Int32, UInt32
|
from riscemu.types import Int32, UInt32
|
||||||
|
|
||||||
|
|
||||||
class TestTokenizer(TestCase):
|
def test_logical_right_shift():
|
||||||
|
a = Int32(100)
|
||||||
def test_logical_right_shift(self):
|
assert a.shift_right_logical(0) == a
|
||||||
a = Int32(100)
|
assert a.shift_right_logical(10) == 0
|
||||||
self.assertEqual(a.shift_right_logical(0), a)
|
assert a.shift_right_logical(1) == 100 >> 1
|
||||||
self.assertEqual(a.shift_right_logical(10), 0)
|
|
||||||
self.assertEqual(a.shift_right_logical(1), 100>>1)
|
|
||||||
|
|
||||||
a = Int32(-100)
|
a = Int32(-100)
|
||||||
self.assertEqual(a.shift_right_logical(0), a)
|
assert a.shift_right_logical(0) == a
|
||||||
self.assertEqual(a.shift_right_logical(1), 2147483598)
|
assert a.shift_right_logical(1) == 2147483598
|
||||||
self.assertEqual(a.shift_right_logical(10), 4194303)
|
assert a.shift_right_logical(10) == 4194303
|
||||||
self.assertEqual(a.shift_right_logical(31), 1)
|
assert a.shift_right_logical(31) == 1
|
||||||
self.assertEqual(a.shift_right_logical(32), 0)
|
assert a.shift_right_logical(32) == 0
|
||||||
|
@ -1,53 +0,0 @@
|
|||||||
from riscemu import AssemblyFileLoader
|
|
||||||
from riscemu.colors import *
|
|
||||||
|
|
||||||
FMT_SUCCESS = FMT_GREEN + FMT_BOLD
|
|
||||||
|
|
||||||
def run_test(path: str):
|
|
||||||
from riscemu import CPU, UserModeCPU, RunConfig
|
|
||||||
from riscemu.instructions import InstructionSetDict
|
|
||||||
from test.test_isa import TestIS
|
|
||||||
import os
|
|
||||||
|
|
||||||
fname = os.path.basename(path)
|
|
||||||
|
|
||||||
ISAs = list(InstructionSetDict.values())
|
|
||||||
ISAs.append(TestIS)
|
|
||||||
|
|
||||||
cpu = UserModeCPU(ISAs, RunConfig())
|
|
||||||
try:
|
|
||||||
program = AssemblyFileLoader(path, {}).parse()
|
|
||||||
cpu.load_program(program)
|
|
||||||
cpu.launch(program)
|
|
||||||
except Exception as ex:
|
|
||||||
print(FMT_ERROR + '[Test] 🔴 failed with exception "{}" ({})'.format(ex, fname) + FMT_NONE)
|
|
||||||
raise ex
|
|
||||||
|
|
||||||
if cpu.halted:
|
|
||||||
for isa in cpu.instruction_sets:
|
|
||||||
if isinstance(isa, TestIS):
|
|
||||||
if not isa.failed:
|
|
||||||
print(FMT_SUCCESS + '[Test] 🟢 successful {}'.format(fname) + FMT_NONE)
|
|
||||||
return not isa.failed
|
|
||||||
return False
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
|
|
||||||
import os
|
|
||||||
import glob
|
|
||||||
|
|
||||||
successes = 0
|
|
||||||
failures = 0
|
|
||||||
ttl = 0
|
|
||||||
|
|
||||||
for path in glob.glob(f'{os.path.dirname(__file__)}/*.asm'):
|
|
||||||
print(FMT_BLUE + '[Test] running testcase ' + os.path.basename(path) + FMT_NONE)
|
|
||||||
ttl += 1
|
|
||||||
if run_test(path):
|
|
||||||
successes += 1
|
|
||||||
else:
|
|
||||||
failures += 1
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -1,7 +0,0 @@
|
|||||||
.data
|
|
||||||
|
|
||||||
data:
|
|
||||||
.word 0xFFFFFFFF, 0x0000FFFF, 0xFF00FF00, 0x7FFFFFFF
|
|
||||||
|
|
||||||
.text
|
|
||||||
ebreak
|
|
@ -1,20 +0,0 @@
|
|||||||
.text
|
|
||||||
|
|
||||||
main:
|
|
||||||
addi a0, zero, main
|
|
||||||
addi a1, zero, main
|
|
||||||
addi t0, zero, 1000
|
|
||||||
assert a0, ==, 0x100
|
|
||||||
1:
|
|
||||||
addi a1, a1, 1
|
|
||||||
blt a1, t0, 1b
|
|
||||||
sub a1, a1, a0
|
|
||||||
j 1f
|
|
||||||
addi a1, zero, 0
|
|
||||||
fail
|
|
||||||
1:
|
|
||||||
assert a1, ==, 744
|
|
||||||
add a0, zero, a1 ; set exit code to a1
|
|
||||||
addi a7, zero, SCALL_EXIT ; exit syscall code
|
|
||||||
scall
|
|
||||||
fail
|
|
Loading…
Reference in New Issue