diff --git a/opbtest/opbtestassertions.py b/opbtest/opbtestassertions.py index c8644ff..2cbd70e 100644 --- a/opbtest/opbtestassertions.py +++ b/opbtest/opbtestassertions.py @@ -1,17 +1,47 @@ import functools -class OpbTestAssertions(): +class OpbTestBaseAssertions(): def __init__(self, json, case): self.jsondata = json self.case = case - self.registers = None - def regs(self, registers): - if type(registers) is not list: - self.case.fail("Expected a list of registers") - self.registers = list(map(lambda reg: self.torawregistername(reg), registers)) - return self + def dong(self): + print("dong") + + def _tocontain(self, expected): + raise Exception("to implement in sublcass") + + def _contains(self, expected): + raise Exception("to implement in sublcass") + + def _getlist_to_fill(self): + raise Exception("to implement in sublcass") + + def contains(self, expected): + listtofill = self._getlist_to_fill() + if listtofill is None: + self.case.fail("First setup what to check by calling other methods!") + + if type(expected) is int or type(expected) is str: + return self._tocontain(expected) + + if type(expected) is not list: + self.case.fail("Expected array as expected values!") + if len(expected) != len(listtofill): + self.case.fail("Given values and expected results arrays length does not match!") + self.fail_if_results(self._contains(expected)) + + def fail_if_results(self, results): + if len(results) > 0: + self.case.fail( + "Output dos not contain expected values: \n" + functools.reduce(lambda a, b: a + "\n" + b, results)) + + +class OpbTestRegAssertions(OpbTestBaseAssertions): + def __init__(self, json, case): + super().__init__(json, case) + self.registers = None def torawregistername(self, register): return int(register[1], 16) @@ -25,30 +55,116 @@ class OpbTestAssertions(): self.registers = [int(register[1], 16)] return self - def tocontain(self, expected): + def regs(self, registers): + if type(registers) is not list: + self.case.fail("Expected a list of registers") + self.registers = list(map(lambda reg: self.torawregistername(reg), registers)) + return self + + def _getlist_to_fill(self): + return self.registers + + def _tocontain(self, expected): for register in self.registers: result = self.case.checkReg(self.jsondata, "a", register, expected) if result != "": self.case.fail(result) - def contains(self, expected): - if self.registers is None: - self.case.fail("First call reg()/regs() to assert which register to check!") - - if type(expected) is int or type(expected) is str: - return self.tocontain(expected) - - if type(expected) is not list: - self.case.fail("Expected array as expected register values!") - if len(expected) != len(self.registers): - self.case.fail("Given registers and expected results arrays do not match!") - + def _contains(self, expected): results = [] for i in range(0, len(expected)): result = self.case.checkReg(self.jsondata, "a", self.registers[i], expected[i]) if result != "": results.append(result) - if len(results) > 0: - self.case.fail( - "Registers do not contain expected values: \n" + functools.reduce(lambda a, b: a + "\n" + b, results)) + return results + +class OpbTestIndexAssertions(OpbTestBaseAssertions): + def __init__(self, json, case, maxindex, json_index_name): + super().__init__(json, case) + self.indices = None + self.maxindex = maxindex + self.json_index_name = json_index_name + + def assertindexname(self, index): + if index < 0 or index > self.maxindex: + self.case.fail("Index should be between 0 and 255, but instead was " + index) + + def torawindex(self, index): + if type(index) is str: + index = int(index, 16) + self.assertindexname(index) + return index + + def _index(self, index): + self.indices = [self.torawindex(index)] + return self + + def _indices(self, indices): + if type(indices) is not list: + self.case.fail("Expected a list of indices") + self.indices = list(map(lambda port: self.torawindex(port), indices)) + return self + + def _getlist_to_fill(self): + return self.indices + + def _tocontain(self, expected): + for index in self.indices: + result = self.case._check(self.json_index_name, self.jsondata, index, expected) + if result != "": + self.case.fail(result) + + def _contains(self, expected): + results = [] + for i in range(0, len(expected)): + result = self.case._check(self.json_index_name, self.jsondata, self.indices[i], expected[i]) + if result != "": + results.append(result) + return results + + +class OpbTestOutputAssertions(OpbTestIndexAssertions): + def __init__(self, json, case): + super().__init__(json, case, 16 * 16, "ports_out") + + def port(self, port): + return self._index(port) + + def ports(self, ports): + return self._indices(ports) + + +class OpbTestScratchAssertions(OpbTestIndexAssertions): + def __init__(self, json, case): + super().__init__(json, case, 16 * 4, "scratchpad") + + def scratchpad(self, port): + return self._index(port) + + def scratchpads(self, ports): + return self._indices(ports) + + +class OpbTestAssertions(): + def __init__(self, json, case): + self.jsondata = json + self.case = case + + def port(self, port): + return OpbTestOutputAssertions(self.jsondata, self.case).port(port) + + def ports(self, port): + return OpbTestOutputAssertions(self.jsondata, self.case).ports(port) + + def scratchpad(self, index): + return OpbTestScratchAssertions(self.jsondata, self.case).scratchpad(index) + + def scratchpads(self, indices): + return OpbTestScratchAssertions(self.jsondata, self.case).scratchpads(indices) + + def regs(self, registers): + return OpbTestRegAssertions(self.jsondata, self.case).regs(registers) + + def reg(self, register): + return OpbTestRegAssertions(self.jsondata, self.case).reg(register) diff --git a/opbtest/opbtestcase.py b/opbtest/opbtestcase.py index dcf0f4b..817fd67 100644 --- a/opbtest/opbtestcase.py +++ b/opbtest/opbtestcase.py @@ -75,7 +75,7 @@ class OpbTestCase(TestCase): json_out = json.loads(json_out) self.assertTrue(json_out['termination'] == 'termNormal', 'Simulation failed with ' + json_out['termination']) - return json_out + return self.assertPsm(json_out) def execute_psm(self, psm): with open("tmp_" + str(time.time()) + ".psm4", "w") as file: @@ -85,6 +85,15 @@ class OpbTestCase(TestCase): def assertPsm(self, jsondata): return OpbTestAssertions(jsondata, self) + def _check(self, jsonindex, jsondata, index, expected): + actual = jsondata[jsonindex][index] + if expected == actual: + return "" + return "output " + jsonindex + " " + str(index) + " should contain " + str(expected) + " but instead contains " + str(actual) + + def checkPort(self, jsondata, port, expected): + self._check("ports_out", jsondata, port, expected) + def checkReg(self, jsondata, bank, nr, expected): actual = jsondata["regs_" + bank][nr] if type(expected) is int: diff --git a/opbtest/opbtestmockable.py b/opbtest/opbtestmockable.py index 6168165..0f1ab14 100644 --- a/opbtest/opbtestmockable.py +++ b/opbtest/opbtestmockable.py @@ -3,6 +3,7 @@ class OpbTestMockable(): self.case = case self.filename = filename self.prepender = [] + self.inputs = {} self.proctotest = "" self.appender = ["\nopbtestquitfn: output sD, FF\n"] @@ -17,6 +18,10 @@ class OpbTestMockable(): self.prepender.append("load " + key + ", " + str(val) + "\n") return self + def mockinput(self, port, value): + self.inputs[port] = value + return self + def execute(self): with open(self.filename, 'r') as original: data = original.readlines() @@ -42,8 +47,25 @@ class OpbTestMockable(): data = data[0:linenr] + ["jump opbtestquitfn\n"] + data[linenr:] return data + def setupinputs(data): + newdata = [] + for line in data: + if line.startswith("input "): + found = False + for key, value in self.inputs.items(): + if ", " + str(key) in line or "," + str(key) in line: + newdata.append(line.split(",")[0].replace("input", "load") + ", " + str(value) + "\n") + found = True + if found is False: + newdata.append(line) + else: + newdata.append(line) + return newdata + if len(self.proctotest) > 0: data = setupproc(data) + if len(self.inputs) > 0: + data = setupinputs(data) firstjump = findlinebetween(data, "jump", "jump") diff --git a/test/basicasm.py b/test/basicasm.py deleted file mode 100644 index b8d3a53..0000000 --- a/test/basicasm.py +++ /dev/null @@ -1,20 +0,0 @@ - - -from opbtest import OpbTestCase - -class TestBasicAsm(OpbTestCase): - - def test_basic_register_loading_form_file_psm4(self): - result = self.execute_file("basic_register_loading.psm4") - self.assertPsm(result).reg("s0").contains(1) - - def test_basic_register_loading_form_file_psm(self): - result = self.execute_file("basic_register_loading.psm") - self.assertPsm(result).reg("s0").contains(1) - - def test_basic_register_loading_inline(self): - psm = """load s0, 1 -output sD, FF""" - - result = self.execute_psm(psm) - self.assertPsm(result).reg("s0").contains(1) diff --git a/test/input.psm4 b/test/input.psm4 new file mode 100644 index 0000000..221f682 --- /dev/null +++ b/test/input.psm4 @@ -0,0 +1,2 @@ +input s0, 0 +load s1, s0 diff --git a/test/test_basicasm.py b/test/test_basicasm.py new file mode 100644 index 0000000..02b96f7 --- /dev/null +++ b/test/test_basicasm.py @@ -0,0 +1,43 @@ + + +from opbtest import OpbTestCase + +class TestBasicAsm(OpbTestCase): + + def setUp(self): + pass + #self.do_not_cleanup_files() + + def test_basic_register_loading_form_file_psm4(self): + self.execute_file("basic_register_loading.psm4").reg("s0").contains(1) + + def test_basic_register_loading_form_file_psm(self): + self.execute_file("basic_register_loading.psm").reg("s0").contains(1) + + def test_basic_scratchpad_assertion(self): + psm = """load s0, 1 + store s0, (s0) + load s0, 2 + store s0, (s0) + load s0, 3 + store s0, (s0) + output sD, FF""" + + assert_that = self.execute_psm(psm) + assert_that.scratchpad(1).contains(1) + assert_that.scratchpads(["0", "1", "2", "3"]).contains([0, 1, 2, 3]) + + def test_basic_output_assertion(self): + psm = """load s2, 5 + output s2, 1 + output sD, FF""" + + assert_that = self.execute_psm(psm) + assert_that.port(1).contains(5) + assert_that.ports(["1", "FF"]).contains([5, 0]) + + def test_basic_register_loading_inline(self): + psm = """load s0, 1 + output sD, FF""" + + self.execute_psm(psm).reg("s0").contains(1) diff --git a/test/functions.py b/test/test_functions.py similarity index 58% rename from test/functions.py rename to test/test_functions.py index f141a99..35c7f80 100644 --- a/test/functions.py +++ b/test/test_functions.py @@ -22,17 +22,17 @@ class TestFunctions(OpbTestCase): pass def test_proc3_adds_to_existing_register(self): - result = self.load_file("functions.psm4").testproc("proc3").setregs({"s5": 2}).execute() - self.assertPsm(result).reg("s5").contains(3) + assert_that = self.load_file("functions.psm4").testproc("proc3").setregs({"s5": 2}).execute() + assert_that.reg("s5").contains(3) def test_proc2_testproc_does_not_execute_rest_of_psm(self): - result = self.load_file("functions.psm4").testproc("proc2").execute() - self.assertPsm(result).regs(["s2", "s4"]).contains([0, 42]) + assert_that = self.load_file("functions.psm4").testproc("proc2").execute() + assert_that.regs(["s2", "s4"]).contains([0, 42]) def test_proc1_calls_proc2(self): - result = self.load_file("functions.psm4").testproc("proc1").execute() - self.assertPsm(result).regs(["s0", "s4"]).contains([42, 42]) + assert_that = self.load_file("functions.psm4").testproc("proc1").execute() + assert_that.regs(["s0", "s4"]).contains([42, 42]) def test_func1_calls_func1(self): - result = self.load_file("functions.psm4").testfunc("func1").execute() - self.assertPsm(result).reg("s1").contains(52) + assert_that = self.load_file("functions.psm4").testfunc("func1").execute() + assert_that.reg("s1").contains(52) diff --git a/test/test_input.py b/test/test_input.py new file mode 100644 index 0000000..453053b --- /dev/null +++ b/test/test_input.py @@ -0,0 +1,12 @@ +from opbtest import OpbTestCase + + +class TestInput(OpbTestCase): + + def setUp(self): + pass + #self.do_not_cleanup_files() + + def test_setup_input(self): + assert_that = self.load_file("input.psm4").mockinput(0, 4).execute() + assert_that.regs(["s0", "s1"]).contains(4) \ No newline at end of file