class ThreadTests(unittest.TestCase): """Test various things around thread synchronization.""" def setUp(self): self.__msgq = MsgQ() self.__abort_wait = False self.__result = None self.__notify_thread = threading.Thread(target=self.__notify) self.__wait_thread = threading.Thread(target=self.__wait) # Make sure the threads are killed if left behind by the test. self.__notify_thread.daemon = True self.__wait_thread.daemon = True def __notify(self): """Call the cfgmgr_ready.""" if self.__abort_wait: self.__msgq.cfgmgr_ready(False) else: self.__msgq.cfgmgr_ready() def __wait(self): """Wait for config manager and store the result.""" self.__result = self.__msgq.wait_cfgmgr() def test_wait_cfgmgr(self): """One thread signals the config manager subscribed, the other waits for it. We then check it terminated correctly. """ self.__notify_thread.start() self.__wait_thread.start() # Timeout to ensure the test terminates even on failure self.__wait_thread.join(60) self.assertTrue(self.__result) def test_wait_cfgmgr_2(self): """Same as test_wait_cfgmgr, but starting the threads in reverse order (the result should be the same). """ self.__wait_thread.start() self.__notify_thread.start() # Timeout to ensure the test terminates even on failure self.__wait_thread.join(60) self.assertTrue(self.__result) def test_wait_abort(self): """Similar to test_wait_cfgmgr, but the config manager is never subscribed and it is aborted. """ self.__abort_wait = True self.__wait_thread.start() self.__notify_thread.start() # Timeout to ensure the test terminates even on failure self.__wait_thread.join(60) self.assertIsNotNone(self.__result) self.assertFalse(self.__result) def __check_ready_and_abort(self): """Check that when we first say the config manager is ready and then try to abort, it uses the first result. """ self.__msgq.cfgmgr_ready() self.__msgq.cfgmgr_ready(False) self.__result = self.__msgq.wait_cfgmgr() def test_ready_and_abort(self): """Perform the __check_ready_and_abort test, but in a separate thread, so in case something goes wrong with the synchronisation and it deadlocks, the test will terminate anyway. """ test_thread = threading.Thread(target=self.__check_ready_and_abort) test_thread.daemon = True test_thread.start() test_thread.join(60) self.assertTrue(self.__result)