class TestsProgramLoader(unittest.TestCase):
    def setUp(self):
        self.disk = Disk()
        self.irqQueueMock = Queue()
        self.killHandleMock = Mock()
        self.timeOutHandleMock = Mock()
        self.ioHandleMock = Mock()

        self.lockProcessingMock = Condition()
        self.lockIrqQueueMock = Condition()
        self.lockReadyQueueMock = Condition()
        self.lockInstructions = Condition()
        self.lockIrq = Condition()
        self.memory = Memory(self.lockInstructions)

        self.interruptionManager = InterruptionManager(self.lockReadyQueueMock,
                                                       self.lockProcessingMock,
                                                       self.irqQueueMock,
                                                       self.lockIrqQueueMock)
        self.interruptionManager.registerHandler(IRQ.kill, self.killHandleMock)
        self.interruptionManager.registerHandler(IRQ.timeOut,
                                                 self.timeOutHandleMock)
        self.interruptionManager.registerHandler(IRQ.IO, self.ioHandleMock)
        self.programLoader = ProgramLoader(self.disk, self.memory,
                                           self.interruptionManager,
                                           PcbTable(), self.lockIrq)
        self.memoryManager = MemoryManager(self.memory, self.disk, Mock(),
                                           Mock())

    def test_when_have_a_program_Then_I_want_to_create_a_pcb_with_pid_1(self):

        program = Program()
        self.assertEqual(
            self.programLoader.createPcb(program, "program0").pid, 1)

    def test_when_have_a_program_Then_the_memory_is_write_with_a_new_program(
            self):

        program = Program()
        instruction1 = Instruction("Cpu Instruction1", InstructionType.cpu,
                                   ResourceType.Monitor)
        instruction2 = Instruction("Cpu Instruction1", InstructionType.cpu,
                                   ResourceType.Monitor)
        instruction3 = Instruction("Cpu Instruction1", InstructionType.cpu,
                                   ResourceType.Monitor)
        instruction4 = Instruction("Cpu Instruction1", InstructionType.cpu,
                                   ResourceType.Monitor)
        program.add(instruction1)
        program.add(instruction2)
        program.add(instruction3)
        program.add(instruction4)
        self.memoryManager.loadToMemory(
            self.programLoader.createPcb(program, "program0"),
            program.instructions)
        self.assertEqual(self.memory.cells[1], instruction2)
class InterruptionManagerTests(unittest.TestCase):
    def setUp(self):
        self.killHandleMock = Mock()
        self.timeOutHandleMock = Mock()
        self.ioHandleMock = Mock()

        self.lockProcessingMock = Condition()
        self.irqQueueMock = Queue()
        self.lockIrqQueueMock = Condition()
        self.lockReadyQueueMock = Condition()

        self.interruptionManager = InterruptionManager(self.lockReadyQueueMock,
                                                       self.lockProcessingMock,
                                                       self.irqQueueMock,
                                                       self.lockIrqQueueMock)
        self.interruptionManager.registerHandler(IRQ.kill, self.killHandleMock)
        self.interruptionManager.registerHandler(IRQ.timeOut,
                                                 self.timeOutHandleMock)
        self.interruptionManager.registerHandler(IRQ.IO, self.ioHandleMock)

    def test_registry(self):
        self.assertEqual(len(self.interruptionManager.handles), 3)

    def testCanHandleKILL(self):
        self.interruptionManager.setDaemon(True)
        irq = IRQ(IRQ.kill, Pcb(0, 0, 0), None, Mock())
        self.interruptionManager.handle(irq)
        self.interruptionManager.start()
        self.killHandleMock.handle.assert_called_with(irq)
        self.assertEqual(self.ioHandleMock.call_count, 0)
        self.assertEqual(self.timeOutHandleMock.call_count, 0)

    def testCanHandleTIMEOUT(self):
        self.interruptionManager.setDaemon(True)
        irq = IRQ(IRQ.timeOut, Pcb(0, 0, 0), None, Mock())
        self.interruptionManager.handle(irq)
        self.interruptionManager.start()
        self.timeOutHandleMock.handle.assert_called_with(irq)
        self.assertEqual(self.ioHandleMock.call_count, 0)
        self.assertEqual(self.killHandleMock.call_count, 0)

    def testCanHandleIO(self):
        self.interruptionManager.setDaemon(True)
        irq = IRQ(IRQ.IO, Pcb(0, 0, 1), None, Mock())
        self.interruptionManager.handle(irq)
        self.interruptionManager.start()
        self.ioHandleMock.handle.assert_called_with(irq)
        self.assertEqual(self.killHandleMock.call_count, 0)
        self.assertEqual(self.timeOutHandleMock.call_count, 0)
class InterruptionManagerTests(unittest.TestCase):
    def setUp(self):
        self.killHandleMock = Mock()
        self.timeOutHandleMock = Mock()
        self.ioHandleMock = Mock()

        self.lockProcessingMock= Condition()
        self.irqQueueMock =Queue()
        self.lockIrqQueueMock = Condition()
        self.lockReadyQueueMock= Condition()

        self.interruptionManager = InterruptionManager(self.lockReadyQueueMock,self.lockProcessingMock, self.irqQueueMock, self.lockIrqQueueMock)
        self.interruptionManager.registerHandler(IRQ.kill, self.killHandleMock)
        self.interruptionManager.registerHandler(IRQ.timeOut, self.timeOutHandleMock)
        self.interruptionManager.registerHandler(IRQ.IO, self.ioHandleMock)


    def test_registry(self):
        self.assertEqual(len(self.interruptionManager.handles), 3)

    def testCanHandleKILL(self):
        self.interruptionManager.setDaemon(True)
        irq = IRQ(IRQ.kill, Pcb(0, 0, 0), None,Mock())
        self.interruptionManager.handle(irq)
        self.interruptionManager.start()
        self.killHandleMock.handle.assert_called_with(irq)
        self.assertEqual(self.ioHandleMock.call_count, 0)
        self.assertEqual(self.timeOutHandleMock.call_count, 0)

    def testCanHandleTIMEOUT(self):
        self.interruptionManager.setDaemon(True)
        irq = IRQ(IRQ.timeOut, Pcb(0, 0, 0), None, Mock())
        self.interruptionManager.handle(irq)
        self.interruptionManager.start()
        self.timeOutHandleMock.handle.assert_called_with(irq)
        self.assertEqual(self.ioHandleMock.call_count, 0)
        self.assertEqual(self.killHandleMock.call_count, 0)

    def testCanHandleIO(self):
        self.interruptionManager.setDaemon(True)
        irq = IRQ(IRQ.IO, Pcb(0, 0, 1), None, Mock())
        self.interruptionManager.handle(irq)
        self.interruptionManager.start()
        self.ioHandleMock.handle.assert_called_with(irq)
        self.assertEqual(self.killHandleMock.call_count, 0)
        self.assertEqual(self.timeOutHandleMock.call_count, 0)
class TestsProgramLoader(unittest.TestCase):

    def setUp(self):
        self.disk= Disk()
        self.irqQueueMock =Queue()
        self.killHandleMock = Mock()
        self.timeOutHandleMock = Mock()
        self.ioHandleMock = Mock()

        self.lockProcessingMock= Condition()
        self.lockIrqQueueMock = Condition()
        self.lockReadyQueueMock= Condition()
        self.lockInstructions= Condition()
        self.lockIrq= Condition()
        self.memory= Memory(self.lockInstructions)

        self.interruptionManager = InterruptionManager(self.lockReadyQueueMock,self.lockProcessingMock, self.irqQueueMock, self.lockIrqQueueMock)
        self.interruptionManager.registerHandler(IRQ.kill, self.killHandleMock)
        self.interruptionManager.registerHandler(IRQ.timeOut, self.timeOutHandleMock)
        self.interruptionManager.registerHandler(IRQ.IO, self.ioHandleMock)
        self.programLoader= ProgramLoader(self.disk, self.memory, self.interruptionManager, PcbTable(), self.lockIrq)
        self.memoryManager= MemoryManager(self.memory, self.disk,Mock(),Mock())

    def test_when_have_a_program_Then_I_want_to_create_a_pcb_with_pid_1(self):

        program= Program()
        self.assertEqual(self.programLoader.createPcb(program, "program0").pid, 1)

    def test_when_have_a_program_Then_the_memory_is_write_with_a_new_program(self):

        program= Program()
        instruction1= Instruction("Cpu Instruction1", InstructionType.cpu, ResourceType.Monitor)
        instruction2= Instruction("Cpu Instruction1", InstructionType.cpu, ResourceType.Monitor)
        instruction3= Instruction("Cpu Instruction1", InstructionType.cpu, ResourceType.Monitor)
        instruction4= Instruction("Cpu Instruction1", InstructionType.cpu, ResourceType.Monitor)
        program.add(instruction1)
        program.add(instruction2)
        program.add(instruction3)
        program.add(instruction4)
        self.memoryManager.loadToMemory(self.programLoader.createPcb(program,"program0"), program.instructions)
        self.assertEqual(self.memory.cells[1], instruction2)