示例#1
0
 def test_invalid_instr(self):
     """
     Tests for invalid op code
     """
     e = ElfCPU()
     e.load_string('123456789')
     with self.assertRaises(InvalidInstructionError):
         e.execute()
示例#2
0
 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()
示例#3
0
 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')
示例#4
0
 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)
示例#5
0
 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)
示例#6
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)
示例#7
0
    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)
示例#8
0
    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)
示例#9
0
    def test_op_input(self):
        """
        Tests input op code

        Use unittest.mock.patch to fake the input value
        """
        e = ElfCPU()

        # Interrupts off
        e.load_string('3,3,99,-1')
        e.interrupts = False
        with patch('builtins.input', return_value='1234'):
            e.execute()
            self.assertEqual(e.peek(3), 1234)

        # Interrupts on
        e.load_string('3,5,3,5,99,-1')
        e.interrupts = True
        with self.assertRaises(InputInterrupt):
            e.step()

        # Should be back at pc = 0
        self.assertEqual(e.pc, 0)

        # Load input
        e.input_buffer = 567

        # Loading again overflows
        with self.assertRaises(InputOverflow):
            e.input_buffer = 123

        # Execute the input instruction
        e.step()
        self.assertEqual(e.peek(5), 567)

        # Exec next input instruction
        with self.assertRaises(InputInterrupt):
            e.step()

        e.input_buffer = 987

        # Execute until end
        e.execute()
        self.assertEqual(e.peek(5), 987)
示例#10
0
    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)
示例#11
0
    def test_op_output(self):
        """
        Tests output op code

        Use io.StringIO() to capture the output
        """
        e = ElfCPU()

        # Interrupts off
        e.load_string('4,5,104,66,99,55')
        e.interrupts = False

        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')

        # Interrupts on

        e.load_string('4,5,104,66,99,55')
        e.interrupts = True

        with self.assertRaises(OutputInterrupt):
            e.execute()
        self.assertEqual(e.output_buffer, 55)
        # Don't clear buffer
        with self.assertRaises(OutputOverflow):
            e.execute()

        # Restart test
        e.reset()
        e.load_string('4,5,104,66,99,55')
        e.interrupts = True

        with self.assertRaises(OutputInterrupt):
            e.execute()
        self.assertEqual(e.output_buffer, 55)

        # Clear buffer
        del e.output_buffer

        with self.assertRaises(OutputInterrupt):
            e.execute()
        self.assertEqual(e.output_buffer, 66)
示例#12
0
    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)
示例#13
0
    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)

        # dst:=a+[b]
        e.load_string('101,44,5,6,99,2,-1')
        e.execute()
        self.assertEqual(e.peek(6), 46)

        # dst:=[a]+b
        e.load_string('1001,5,50,6,99,2,-1')
        e.execute()
        self.assertEqual(e.peek(6), 52)

        # dst:=a+b
        e.load_string('1101,5,5,6,99,2,-1')
        e.execute()
        self.assertEqual(e.peek(6), 10)
示例#14
0
    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)

        # dst:=a*[b]
        e.load_string('102,44,5,6,99,2,-1')
        e.execute()
        self.assertEqual(e.peek(6), 88)

        # dst:=[a]*b
        e.load_string('1002,5,50,6,99,2,-1')
        e.execute()
        self.assertEqual(e.peek(6), 100)

        # dst:=a*b
        e.load_string('1102,5,5,6,99,2,-1')
        e.execute()
        self.assertEqual(e.peek(6), 25)
示例#15
0
# Max thruster
thruster = 0

with open('input.txt') as f:
    intcode = ''.join(f.readlines())

# Iterate through phases
for phase in phases:
    input_signal = 0
    # Iterate through amps
    for position in range(5):
        # Clear state
        amp.reset()
        # Reload code
        amp.load_string(intcode)
        # Interrupts on
        amp.interrupts = True

        # Run until phase is requested
        try:
            amp.execute()
        except InputInterrupt:
            pass

        # Provide phase
        amp.input_buffer = phase[position]

        # Run until input signal is requested
        try:
            amp.execute()