コード例 #1
0
ファイル: test_cpu.py プロジェクト: Zoopa/chip8emu
class CpuTest(unittest.TestCase):

    def setUp(self):
        self.memory = Memory(CpuConstants.MEM_SIZE)
        self.screen = Screen(CpuConstants.SCREEN_W, CpuConstants.SCREEN_H)
        self.cpu = CPU(self.memory, self.screen)
        self.cpu.programCounter = CpuConstants.PC_BEFORE

    def tearDown(self):
        pass

    def assertProgramCounterIncreased(self):
        self.assertEqual(self.cpu.programCounter, CpuConstants.PC_AFTER)

    def assertInstructionSkipped(self):
        self.assertEqual(self.cpu.programCounter, CpuConstants.PC_AFTER_SKIP)

    def assertRegisterIsZero(self, register):
        self.assertTrue(register == 0x00)

    def assertRegistersAreZero(self, registers):
        self.assertTrue(registers == [0] * len(registers))

    def assertCarryIsNotSet(self):
        self.assertRegisterIsZero(self.cpu.vRegister[CpuConstants.V_CARRY])

    def assertCarryIsSet(self):
        self.assertTrue(self.cpu.vRegister[CpuConstants.V_CARRY] == 0x01)

    def testShouldHaveMemory(self):
        self.assertIsInstance(self.cpu.memory, Memory)

    def testShouldFullyInitialiseOpcodeTable(self):
        pass

    def testShouldInitialiseAllRegisters(self):
        self.assertRegistersAreZero(self.cpu.vRegister)
        self.assertRegisterIsZero(self.cpu.opcode)
        self.assertRegisterIsZero(self.cpu.indexRegister)
        self.assertRegisterIsZero(self.cpu.delayTimer)
        self.assertRegisterIsZero(self.cpu.soundTimer)
        self.assertRegisterIsZero(self.cpu.soundTimer)

        #setUp sets program counter...
        #self.assertRegisterIsZero(self.cpu.programCounter)

    def testShouldInitialiseStackAndPointer(self):
        self.assertRegistersAreZero(self.cpu.stack)
        self.assertRegisterIsZero(self.cpu.stackPointer)

    def testShouldFetchCorrectOpcode(self):
        self.memory.getByte = Mock(return_value=CpuConstants.OPCODE)
        self.cpu.fetchOpcode(CpuConstants.MEM_ADDRESS)
        self.memory.getByte.assert_has_calls([
            call(CpuConstants.MEM_ADDRESS),
            call(CpuConstants.MEM_ADDRESS + 1)
        ])

    def testShouldDecodeOpcodeCorrectly(self):
        self.cpu.opcode = CpuConstants.OPCODE
        decodedOpcode = self.cpu.decodeOpcode()
        self.assertEqual(decodedOpcode, CpuConstants.DECODED_OPCODE)

    def testShouldRaiseExceptionOnUnknownOpcode(self):
        with self.assertRaises(UnknownOpcodeException):
            self.cpu.opcode = CpuConstants.INVALID_OPCODE
            self.cpu.decodeOpcode()

    def testShouldDelegateOpcodeExecutionCorrectly(self):
        """ How? """
        pass

    def testShouldIncreaseProgramCounterByTwo(self):
        self.cpu.increaseProgramCounter()
        self.assertProgramCounterIncreased()

    def testShouldIncreaseProgramCounterByFourOnSkip(self):
        self.cpu.skipInstruction()
        self.assertInstructionSkipped()

    def testShouldSetCarryCorrectly(self):
        self.cpu.setCarry(True)
        self.assertCarryIsSet()

        self.cpu.setCarry(False)
        self.assertCarryIsNotSet()

    def testShouldRaiseErrorOnWrongOpcode(self):
        with self.assertRaises(KeyError):
            self.cpu.executeOpcode(CpuConstants.OPCODE)

    def testShouldExecuteOpcode00E0Correctly(self):
        self.cpu.opcode = CpuConstants.OPCODE_00E0
        self.screen.clear = Mock()
        self.cpu.executeOpcode00E0()
        self.screen.clear.assert_called_once_with()
        self.assertProgramCounterIncreased()

    def testShouldExecuteOpcodeANNNCorrectly(self):
        self.cpu.opcode = CpuConstants.OPCODE_ANNN
        self.cpu.executeOpcodeANNN()
        self.assertEqual(self.cpu.indexRegister, CpuConstants.IR_ANNN)
        self.assertProgramCounterIncreased()

    def testShouldExecuteOpcode1NNNCorrectly(self):
        self.cpu.opcode = CpuConstants.OPCODE_1NNN
        self.cpu.executeOpcode1NNN()
        self.assertEqual(self.cpu.programCounter, CpuConstants.PC_1NNN)

    def testShouldExecuteOpcode2NNNCorrectly(self):
        oldSp = self.cpu.stackPointer
        self.cpu.opcode = CpuConstants.OPCODE_2NNN
        self.cpu.executeOpcode2NNN()
        self.assertEqual(self.cpu.stackPointer, CpuConstants.SP_2NNN)
        self.assertEqual(self.cpu.programCounter, CpuConstants.PC_2NNN)
        self.assertEqual(self.cpu.stack[oldSp], CpuConstants.PC_ON_STACK_2NNN)

    def testShouldSkipInstructionForOpcode3XNN(self):
        self.cpu.opcode = CpuConstants.OPCODE_3XNN
        self.cpu.vRegister[CpuConstants.X_3XNN] = CpuConstants.VX_3XNN_EQ
        self.cpu.executeOpcode3XNN()
        self.assertInstructionSkipped()

    def testShouldNotSkipInstructionForOpcode3XNN(self):
        self.cpu.opcode = CpuConstants.OPCODE_3XNN
        self.cpu.vRegister[CpuConstants.X_3XNN] = CpuConstants.VX_3XNN_NEQ
        self.cpu.executeOpcode3XNN()
        self.assertProgramCounterIncreased()

    def testShouldSkipInstructionForOpcode4XNN(self):
        self.cpu.opcode = CpuConstants.OPCODE_4XNN
        self.cpu.vRegister[CpuConstants.X_4XNN] = CpuConstants.VX_4XNN_NEQ
        self.cpu.executeOpcode4XNN()
        self.assertInstructionSkipped()

    def testShouldNotSkipInstructionForOpcode4XNN(self):
        self.cpu.opcode = CpuConstants.OPCODE_4XNN
        self.cpu.vRegister[CpuConstants.X_4XNN] = CpuConstants.VX_4XNN_EQ
        self.cpu.executeOpcode4XNN()
        self.assertProgramCounterIncreased()

    def testShouldSkipInstructionForOpcode5XY0(self):
        self.cpu.opcode = CpuConstants.OPCODE_5XY0
        self.cpu.vRegister[CpuConstants.X_5XY0] = CpuConstants.VX_5XY0_EQ
        self.cpu.vRegister[CpuConstants.Y_5XY0] = CpuConstants.VY_5XY0_EQ
        self.cpu.executeOpcode5XY0()
        self.assertInstructionSkipped()

    def testShouldNotSkipInstructionForOpcode5XY0(self):
        self.cpu.opcode = CpuConstants.OPCODE_5XY0
        self.cpu.vRegister[CpuConstants.X_5XY0] = CpuConstants.VX_5XY0_EQ
        self.cpu.vRegister[CpuConstants.Y_5XY0] = CpuConstants.VY_5XY0_NEQ
        self.cpu.executeOpcode5XY0()
        self.assertProgramCounterIncreased()

    def testShouldExecuteOpcode6XNNCorrectly(self):
        self.cpu.opcode = CpuConstants.OPCODE_6XNN
        self.cpu.executeOpcode6XNN()
        self.assertEqual(
            self.cpu.vRegister[CpuConstants.X_6XNN],
            CpuConstants.VX_6XNN
        )
        self.assertProgramCounterIncreased()

    def testShouldExecuteOpcode7XNNWithoutOverflow(self):
        self.cpu.opcode = CpuConstants.OPCODE_7XNN
        self.cpu.vRegister[CpuConstants.X_7XNN] = CpuConstants.VX_7XNN
        self.cpu.executeOpcode7XNN()
        self.assertEqual(
            self.cpu.vRegister[CpuConstants.X_7XNN],
            CpuConstants.VX_7XNN_SUM
        )
        self.assertProgramCounterIncreased()

    def testShouldExecuteOpcode7XNNWithOverflow(self):
        self.cpu.opcode = CpuConstants.OPCODE_7XNN_OVERFLOW
        self.cpu.vRegister[CpuConstants.X_7XNN] = CpuConstants.VX_7XNN
        self.cpu.executeOpcode7XNN()
        self.assertEqual(
            self.cpu.vRegister[CpuConstants.X_7XNN],
            CpuConstants.VX_7XNN_SUM_OVERFLOW
        )
        self.assertProgramCounterIncreased()

    def testShouldExecuteOpcode8XY0Correctly(self):
        self.cpu.opcode = CpuConstants.OPCODE_8XY0
        self.cpu.vRegister[CpuConstants.X_8XY0] = CpuConstants.VX_8XY0_BEFORE
        self.cpu.vRegister[CpuConstants.Y_8XY0] = CpuConstants.VY_8XY0
        self.cpu.executeOpcode8XY0()
        self.assertEqual(
            self.cpu.vRegister[CpuConstants.X_8XY0],
            CpuConstants.VX_8XY0_AFTER
        )
        self.assertProgramCounterIncreased()

    def testShouldExecuteOpcode8XY1Correctly(self):
        self.cpu.opcode = CpuConstants.OPCODE_8XY1
        self.cpu.vRegister[CpuConstants.X_8XY1] = CpuConstants.VX_8XY1_BEFORE
        self.cpu.vRegister[CpuConstants.Y_8XY1] = CpuConstants.VY_8XY1
        self.cpu.executeOpcode8XY1()
        self.assertEqual(
            self.cpu.vRegister[CpuConstants.X_8XY1],
            CpuConstants.VX_8XY1_AFTER
        )
        self.assertProgramCounterIncreased()

    def testShouldExecuteOpcode8XY2Correctly(self):
        self.cpu.opcode = CpuConstants.OPCODE_8XY2
        self.cpu.vRegister[CpuConstants.X_8XY2] = CpuConstants.VX_8XY2_BEFORE
        self.cpu.vRegister[CpuConstants.Y_8XY2] = CpuConstants.VY_8XY2
        self.cpu.executeOpcode8XY2()
        self.assertEqual(
            self.cpu.vRegister[CpuConstants.X_8XY2],
            CpuConstants.VX_8XY2_AFTER
        )
        self.assertProgramCounterIncreased()

    def testShouldExecuteOpcode8XY3Correctly(self):
        self.cpu.opcode = CpuConstants.OPCODE_8XY3
        self.cpu.vRegister[CpuConstants.X_8XY3] = CpuConstants.VX_8XY3_BEFORE
        self.cpu.vRegister[CpuConstants.Y_8XY3] = CpuConstants.VY_8XY3
        self.cpu.executeOpcode8XY3()
        self.assertEqual(
            self.cpu.vRegister[CpuConstants.X_8XY3],
            CpuConstants.VX_8XY3_AFTER
        )
        self.assertProgramCounterIncreased()

    def testShouldExecuteOpcode8XY4WithoutOverflowAndNoCarry(self):
        self.cpu.opcode = CpuConstants.OPCODE_8XY4
        self.cpu.vRegister[CpuConstants.V_CARRY] = 0x01
        self.cpu.vRegister[CpuConstants.X_8XY4] = CpuConstants.VX_8XY4_BEFORE
        self.cpu.vRegister[CpuConstants.Y_8XY4] = CpuConstants.VY_8XY4_NORMAL
        self.cpu.executeOpcode8XY4()
        self.assertEqual(
            self.cpu.vRegister[CpuConstants.X_8XY4],
            CpuConstants.VX_8XY4_AFTER_NO_OVERFLOW
        )
        self.assertCarryIsNotSet()
        self.assertProgramCounterIncreased()

    def testShouldExecuteOpcode8XY4WithOverflowAndCarry(self):
        self.cpu.opcode = CpuConstants.OPCODE_8XY4
        self.cpu.vRegister[CpuConstants.V_CARRY] = 0x00
        self.cpu.vRegister[CpuConstants.X_8XY4] = CpuConstants.VX_8XY4_BEFORE
        self.cpu.vRegister[CpuConstants.Y_8XY4] = CpuConstants.VY_8XY4_OVERFLOW
        self.cpu.executeOpcode8XY4()
        self.assertEqual(
            self.cpu.vRegister[CpuConstants.X_8XY4],
            CpuConstants.VX_8XY4_AFTER_OVERFLOW
        )
        self.assertCarryIsSet()
        self.assertProgramCounterIncreased()

    def testShouldExecuteOpcode8XY5WithoutOverflowAndNoBorrow(self):
        self.cpu.opcode = CpuConstants.OPCODE_8XY5
        self.cpu.vRegister[CpuConstants.V_CARRY] = 0x00
        self.cpu.vRegister[CpuConstants.X_8XY5] = CpuConstants.VX_8XY5_BEFORE
        self.cpu.vRegister[CpuConstants.Y_8XY5] = CpuConstants.VY_8XY5_NORMAL
        self.cpu.executeOpcode8XY5()
        self.assertEqual(
            self.cpu.vRegister[CpuConstants.X_8XY5],
            CpuConstants.VX_8XY5_AFTER_NO_OVERFLOW
        )
        self.assertCarryIsSet()
        self.assertProgramCounterIncreased()

    def testShouldExecuteOpcode8XY5WithOverflowAndBorrow(self):
        self.cpu.opcode = CpuConstants.OPCODE_8XY5
        self.cpu.vRegister[CpuConstants.V_CARRY] = 0x01
        self.cpu.vRegister[CpuConstants.X_8XY5] = CpuConstants.VX_8XY5_BEFORE
        self.cpu.vRegister[CpuConstants.Y_8XY5] = CpuConstants.VY_8XY5_OVERFLOW
        self.cpu.executeOpcode8XY5()
        self.assertEqual(
            self.cpu.vRegister[CpuConstants.X_8XY5],
            CpuConstants.VX_8XY5_AFTER_OVERFLOW
        )
        self.assertCarryIsNotSet()
        self.assertProgramCounterIncreased()

    def testShouldExecuteOpcode8XY6WithLSB0(self):
        self.cpu.opcode = CpuConstants.OPCODE_8XY6
        self.cpu.vRegister[CpuConstants.V_CARRY] = 0x00
        self.cpu.vRegister[CpuConstants.X_8XY6] = CpuConstants.VX_8XY6_LSB0
        self.cpu.executeOpcode8XY6()
        self.assertEqual(
            self.cpu.vRegister[CpuConstants.X_8XY6],
            CpuConstants.VX_8XY6_AFTER
        )
        self.assertCarryIsNotSet()
        self.assertProgramCounterIncreased()

    def testShouldExecuteOpcode8XY6WithLSB1(self):
        self.cpu.opcode = CpuConstants.OPCODE_8XY6
        self.cpu.vRegister[CpuConstants.V_CARRY] = 0x00
        self.cpu.vRegister[CpuConstants.X_8XY6] = CpuConstants.VX_8XY6_LSB1
        self.cpu.executeOpcode8XY6()
        self.assertEqual(
            self.cpu.vRegister[CpuConstants.X_8XY6],
            CpuConstants.VX_8XY6_AFTER
        )
        self.assertCarryIsSet()
        self.assertProgramCounterIncreased()

    def testShouldExecuteOpcode8XY7WithoutOverflowAndNoBorrow(self):
        self.cpu.opcode = CpuConstants.OPCODE_8XY7
        self.cpu.vRegister[CpuConstants.V_CARRY] = 0x00
        self.cpu.vRegister[CpuConstants.X_8XY7] = CpuConstants.VX_8XY7_BEFORE
        self.cpu.vRegister[CpuConstants.Y_8XY7] = CpuConstants.VY_8XY7_NORMAL
        self.cpu.executeOpcode8XY7()
        self.assertEqual(
            self.cpu.vRegister[CpuConstants.X_8XY7],
            CpuConstants.VX_8XY7_AFTER_NO_OVERFLOW
        )
        self.assertCarryIsSet()
        self.assertProgramCounterIncreased()

    def testShouldExecuteOpcode8XY7WithOverflowAndBorrow(self):
        self.cpu.opcode = CpuConstants.OPCODE_8XY7
        self.cpu.vRegister[CpuConstants.V_CARRY] = 0x01
        self.cpu.vRegister[CpuConstants.X_8XY7] = CpuConstants.VX_8XY7_BEFORE
        self.cpu.vRegister[CpuConstants.Y_8XY7] = CpuConstants.VY_8XY7_OVERFLOW
        self.cpu.executeOpcode8XY7()
        self.assertEqual(
            self.cpu.vRegister[CpuConstants.X_8XY7],
            CpuConstants.VX_8XY7_AFTER_OVERFLOW
        )
        self.assertCarryIsNotSet()
        self.assertProgramCounterIncreased()

    def testShouldExecuteOpcode8XYEWithMSB0(self):
        self.cpu.opcode = CpuConstants.OPCODE_8XYE
        self.cpu.vRegister[CpuConstants.V_CARRY] = 0x01
        self.cpu.vRegister[CpuConstants.X_8XYE] = (
            CpuConstants.VX_8XYE_MSB0_BEFORE
        )
        self.cpu.executeOpcode8XYE()
        self.assertEqual(
            self.cpu.vRegister[CpuConstants.X_8XYE],
            CpuConstants.VX_8XYE_MSB0_AFTER
        )
        self.assertCarryIsNotSet()
        self.assertProgramCounterIncreased()

    def testShouldExecuteOpcode8XYEWithMSB1(self):
        self.cpu.opcode = CpuConstants.OPCODE_8XYE
        self.cpu.vRegister[CpuConstants.V_CARRY] = 0x00
        self.cpu.vRegister[CpuConstants.X_8XYE] = (
            CpuConstants.VX_8XYE_MSB1_BEFORE
        )
        self.cpu.executeOpcode8XYE()
        self.assertEqual(
            self.cpu.vRegister[CpuConstants.X_8XYE],
            CpuConstants.VX_8XYE_MSB1_AFTER
        )
        self.assertCarryIsSet()
        self.assertProgramCounterIncreased()

    def testShouldExecuteOpcodeFX15Correctly(self):
        self.cpu.opcode = CpuConstants.OPCODE_FX15
        self.cpu.vRegister[CpuConstants.X_FX15] = CpuConstants.VX_FX15
        self.cpu.executeOpcodeFX15()
        self.assertEqual(self.cpu.delayTimer, CpuConstants.DT_FX15)
        self.assertProgramCounterIncreased()

    def testShouldExecuteOpcodeFX18Correctly(self):
        self.cpu.opcode = CpuConstants.OPCODE_FX18
        self.cpu.vRegister[CpuConstants.X_FX18] = CpuConstants.VX_FX18
        self.cpu.executeOpcodeFX18()
        self.assertEqual(self.cpu.soundTimer, CpuConstants.ST_FX18)
        self.assertProgramCounterIncreased()