def testSystemExitOnUnhandledExceptionInEventLoopThread( self, _modelRunnerProxyClassMock): # Test that an unhandled exception in SlotAgent's event loop thread results # in os._exit(). modelFinishedQ = Queue.Queue() def modelFinishedCallback(modelID, exitStatus): modelFinishedQ.put((modelID, exitStatus)) # Patch os._exit and run model in SlotAgent osExitCodeQ = Queue.Queue() with patch.object(os, "_exit", autospec=True, side_effect=osExitCodeQ.put): sa = slot_agent.SlotAgent(slotID=1) modelID = "abc" sa.startModel( modelID=modelID, modelFinishedCallback=partial(modelFinishedCallback, modelID)) # Wait for the call to os._exit() # NOTE: if we get the Queue.Empty exception, it means that we didn't get # the expected call to os._exit() exitCode = osExitCodeQ.get(timeout=5) self.assertEqual( exitCode, slot_agent._EXIT_CODE_ON_UNHANDLED_EXCEPTION_IN_THREAD) self.assertNotEqual(exitCode, 0)
def testCreateSlotAgentAndCloseIt(self, _modelRunnerProxyClassMock): sa = slot_agent.SlotAgent(slotID=1) self.assertIsNotNone(sa._thread) t = threading.Thread(target=sa.close) t.setDaemon(True) t.start() t.join(timeout=5) self.assertFalse(t.isAlive()) self.assertIsNone(sa._thread)
def testSwapModelsInSlotAgent(self, modelRunnerProxyClassMock): # Create mock ModelRunnerProxy factory modelRunnerProxyMocks = [] def createModelRunnerProxyMock( modelID, onTermination, logger): # pylint: disable=W0613 modelRunnerProxyMock = Mock( spec_set=slot_agent.ModelRunnerProxy, stopGracefully=Mock( spec_set=slot_agent.ModelRunnerProxy.stopGracefully, return_value=0)) modelRunnerProxyMocks.append(modelRunnerProxyMock) return modelRunnerProxyMock modelRunnerProxyClassMock.side_effect = createModelRunnerProxyMock modelFinishedQ = Queue.Queue() def modelFinishedCallback(modelID, exitStatus): modelFinishedQ.put((modelID, exitStatus)) sa = slot_agent.SlotAgent(slotID=1) # Test swapping of the models in the single SlotAgent instance modelIDs = ["abc", "def"] for modelID in modelIDs: sa.startModel( modelID=modelID, modelFinishedCallback=partial(modelFinishedCallback, modelID)) sa.stopModel() self.assertEqual((modelID, 0), modelFinishedQ.get(timeout=5)) sa.releaseSlot() # Close slot agent t = threading.Thread(target=sa.close) t.setDaemon(True) t.start() t.join(timeout=5) self.assertFalse(t.isAlive()) self.assertIsNone(sa._thread) # Verify ModelRunnerProxy constructor calls self.assertEqual(modelRunnerProxyClassMock.call_count, len(modelIDs)) # Very modelRunnerProxyMock.stopGracefully calls self.assertEqual(len(modelRunnerProxyMocks), len(modelIDs)) for modelRunnerProxyMock in modelRunnerProxyMocks: self.assertEqual(modelRunnerProxyMock.stopGracefully.call_count, 1)