def test_op_add(self): """ Tests ADD op code [dst]:=[a]+[b] """ e = ElfCPU() # Invalid address 44 for a e.load_string('1,44,0,0') with self.assertRaises(ProtectionFaultError): e.step() # Invalid address 44 for b e.load_string('1,0,44,0') with self.assertRaises(ProtectionFaultError): e.step() # Invalid address 44 for dst e.load_string('1,0,0,44') with self.assertRaises(ProtectionFaultError): e.step() # 1 + 1 = 2 @ address 0 e.load_string('1,0,0,0,99') e.step() self.assertEqual(e.peek(0), 2) # 2**64 + 1 = 1 @ address 0 (overflow and wrap) e.load_string('1,5,6,0,99,' + str(2**64) + ',1') e.step() self.assertEqual(e.peek(0), 1)
def test_op_mul(self): """ Tests MUL op code [dst]:=[a]*[b] """ e = ElfCPU() # Invalid address 44 for a e.load_string('2,44,0,0') with self.assertRaises(ProtectionFaultError): e.step() # Invalid address 44 for b e.load_string('2,0,44,0') with self.assertRaises(ProtectionFaultError): e.step() # Invalid address 44 for dst e.load_string('2,0,0,44') with self.assertRaises(ProtectionFaultError): e.step() # 2 * 2 = 4 @ address 0 e.load_string('2,0,0,0,99') e.step() self.assertEqual(e.peek(0), 4) # 2**63 * 3 = 9223372036854775808 @ address 0 (overflow and wrap) e.load_string('2,5,6,0,99,' + str(2**63) + ',3') e.step() self.assertEqual(e.peek(0), 9223372036854775808)
def test_invalid_instr(self): """ Tests for invalid op code """ e = ElfCPU() e.load_string('123456789') with self.assertRaises(InvalidInstructionError): e.execute()
def test_gpf(self): """ Tests for a general protection fault by allowing the program counter to go past the end of the memory """ e = ElfCPU() e.load_string('1,0,0,0') with self.assertRaises(ProtectionFaultError): e.execute()
def test_load_string_types(self): """ Checks for TypeError """ e = ElfCPU() with self.assertRaises(TypeError): # noinspection PyTypeChecker e.load_string(0) e.load_string('1,2,3,4')
def test_halt(self): """ Tests for the halt op code """ e = ElfCPU() e.load_string('1,0,0,0,99') e.step() self.assertFalse(e.is_halted) e.step() self.assertTrue(e.is_halted)
def test_op_input(self): """ Tests input op code Use unittest.mock.patch to fake the input value """ e = ElfCPU() e.load_string('3,3,99,-1') with patch('builtins.input', return_value='1234'): e.execute() self.assertEqual(e.peek(3), 1234)
def test_op_cmp_lessthan(self): """ Tests compare less than op code """ e = ElfCPU() """ Tests if value of address 5 (5) is less than value of address 6 (10). Since this is true write 1 to address 7. """ e.load_string('7,5,6,7,99,5,10,-1') e.execute() self.assertEqual(e.peek(7), 1) """ Tests if value of address 5 (10) is less than value of address 6 (5). Since this is false write 0 to address 7. """ e.load_string('7,5,6,7,99,10,5,-1') e.execute() self.assertEqual(e.peek(7), 0) """ Tests if immediate value of 5 is less than immediate value of 10. Since this is true write 1 to address 7. """ e.load_string('1107,5,10,7,99,0,0,-1') e.execute() self.assertEqual(e.peek(7), 1) """ Tests if immediate value of 10 is less than immediate value of 5. Since this is false write 0 to address 7. """ e.load_string('1107,10,5,7,99,0,0,-1') e.execute() self.assertEqual(e.peek(7), 0)
def test_op_jmp_true(self): """ Tests jump if true op code """ e = ElfCPU() """ Tests address 8 (which is 1) if it is non-zero. Since this is true, it jumps to the value of address 9 (which is 7). This terminates the program. """ e.load_string('5,8,9,1101,1,1,8,99,1,7') e.execute() self.assertEqual(e.peek(8), 1) """ Tests immediate value 8 if it is non-zero. Since it is true, jump to immediate address 7 which terminates. """ e.load_string('1105,8,7,1101,1,1,8,99,1,7') e.execute() self.assertEqual(e.peek(8), 1) """ Tests address 8 (which is 0) if it is non-zero. Since this is false it does not jump and instead adds 1+1 to address 8. """ e.load_string('5,8,9999,1101,1,1,8,99,0,7') e.execute() self.assertEqual(e.peek(8), 2) """ Tests immediate value 0 if it is non-zero. Since it is false it does not jump and instead adds 1+1 to address 8. """ e.load_string('1105,0,9999,1101,1,1,8,99,0,7') e.execute() self.assertEqual(e.peek(8), 2)
def test_peek(self): """ Tests address range for peek """ e = ElfCPU() e.load_string('0,1,2,3,4,5,6,7,8,9') with self.assertRaises(TypeError): # noinspection PyTypeChecker e.peek('x') with self.assertRaises(ValueError): e.peek(20) with self.assertRaises(ValueError): e.peek(-1) self.assertEqual(e.peek(0), 0) self.assertEqual(e.peek(9), 9)
def test_reset(self): """ Tests for CPU reset """ e = ElfCPU() e.load_string('1,0,0,0,99') e.execute() e.reset() # Halted gets cleared self.assertFalse(e.is_halted) # Program counter goes to 0 self.assertEqual(e.pc, 0) # Memory gets wiped so address 1 becomes invalid with self.assertRaises(ValueError): e.peek(1)
def test_op_output(self): """ Tests output op code Use io.StringIO() to capture the output """ e = ElfCPU() e.load_string('4,5,104,66,99,55') result = None with patch('sys.stdout', new=io.StringIO()) as output: e.execute() result = output.getvalue() result = result.splitlines() # First is a reference to memory address 5 self.assertEqual(result[0].strip(), '55') # Second is an immediate value self.assertEqual(result[1].strip(), '66')
def test_poke(self): """ Tests address range and data for poke """ e = ElfCPU() e.load_string('0,1,2,3,4,5,6,7,8,9') # Address with self.assertRaises(TypeError): # noinspection PyTypeChecker e.poke('x', 2) with self.assertRaises(ValueError): e.poke(20, 2) with self.assertRaises(ValueError): e.poke(-1, 2) # Value with self.assertRaises(ValueError): e.poke(0, 2**64 + 1) self.assertEqual(e.poke(0, 99), 99) self.assertEqual(e.poke(9, 88), 88) self.assertEqual(e.peek(0), 99) self.assertEqual(e.peek(9), 88)
def test_op_eq(self): """ Tests equals op code """ e = ElfCPU() """ Tests if value of address 5 (10) is equal to value of address 6 (10). Since this is true, write 1 to address 7. """ e.load_string('8,5,6,7,99,10,10,-1') e.execute() self.assertEqual(e.peek(7), 1) """ Tests if value of address 5 (10) is equal to value of address 6 (0). Since this is false, write 0 to address 7. """ e.load_string('8,5,6,7,99,10,0,-1') e.execute() self.assertEqual(e.peek(7), 0) """ Tests if immediate value 10 is equal to immediate value 10. Since this is true, write 1 to address 7. """ e.load_string('1108,10,10,7,99,2,3,-1') e.execute() self.assertEqual(e.peek(7), 1) """ Tests if immediate value of 0 is equal to immediate value 10. Since this is false, write 0 to address 7. """ e.load_string('1108,0,10,7,99,2,3,-1') e.execute() self.assertEqual(e.peek(7), 0)