def test_double_acquire_many(self): activated = collections.deque() acquires = collections.deque() n_lock = lock_utils.MultiLock((threading.RLock(), threading.RLock())) def critical_section(): start = now() time.sleep(NAPPY_TIME) end = now() activated.append((start, end)) def run(): with n_lock as gotten: acquires.append(gotten) critical_section() with n_lock as gotten: acquires.append(gotten) critical_section() critical_section() threads = [] for i in range(0, self.THREAD_COUNT): t = threading_utils.daemon_thread(run) threads.append(t) t.start() while threads: t = threads.pop() t.join() self.assertTrue(all(acquires)) self.assertEqual(self.THREAD_COUNT * 2, len(acquires)) self.assertEqual(self.THREAD_COUNT * 3, len(activated)) for (start, end) in activated: self.assertEqual(1, _find_overlaps(activated, start, end))
def test_creation(self): locks = [] for _i in range(0, 10): locks.append(threading.Lock()) n_lock = lock_utils.MultiLock(locks) self.assertEqual(0, n_lock.obtained) self.assertEqual(len(locks), len(n_lock))
def test_double_acquire_single(self): activated = collections.deque() acquires = [] def run(): start = now() time.sleep(NAPPY_TIME) end = now() activated.append((start, end)) lock1 = threading.RLock() lock2 = threading.RLock() n_lock = lock_utils.MultiLock((lock1, lock2)) with n_lock as gotten: acquires.append(gotten) run() with n_lock as gotten: acquires.append(gotten) run() run() self.assertTrue(all(acquires)) self.assertEqual(2, len(acquires)) for (start, end) in activated: self.assertEqual(1, _find_overlaps(activated, start, end))
def test_double_acquire_many(self): activated = collections.deque() n_lock = lock_utils.MultiLock((threading.RLock(), threading.RLock())) def critical_section(): start = time.time() time.sleep(0.05) end = time.time() activated.append((start, end)) def run(): with n_lock: critical_section() with n_lock: critical_section() critical_section() threads = [] for i in range(0, 20): t = threading_utils.daemon_thread(run) threads.append(t) t.start() while threads: t = threads.pop() t.join() for (start, end) in activated: self.assertEqual(1, _find_overlaps(activated, start, end))
def test_acquired_pass(self): activated = collections.deque() lock1 = threading.Lock() lock2 = threading.Lock() n_lock = lock_utils.MultiLock((lock1, lock2)) def critical_section(): start = time.time() time.sleep(0.05) end = time.time() activated.append((start, end)) def run(): with n_lock: critical_section() threads = [] for _i in range(0, 20): t = threading_utils.daemon_thread(run) threads.append(t) t.start() while threads: t = threads.pop() t.join() for (start, end) in activated: self.assertEqual(1, _find_overlaps(activated, start, end)) self.assertFalse(lock1.locked()) self.assertFalse(lock2.locked())
def test_partial_acquired_failure(self): lock1 = threading.Lock() lock2 = mock.create_autospec(threading.Lock()) lock2.acquire.side_effect = RuntimeError("Broke") n_lock = lock_utils.MultiLock((lock1, lock2)) self.assertRaises(threading.ThreadError, n_lock.acquire) self.assertEqual(1, n_lock.obtained) n_lock.release()
def test_acquired_context_manager(self): lock1 = threading.Lock() n_lock = lock_utils.MultiLock([lock1]) with n_lock as gotten: self.assertTrue(gotten) self.assertTrue(lock1.locked()) self.assertFalse(lock1.locked()) self.assertEqual(0, n_lock.obtained)
def test_partial_acquired(self): lock1 = threading.Lock() lock2 = mock.create_autospec(threading.Lock()) lock2.acquire.return_value = False n_lock = lock_utils.MultiLock((lock1, lock2)) with n_lock as gotten: self.assertFalse(gotten) self.assertTrue(lock1.locked()) self.assertEqual(1, n_lock.obtained) self.assertEqual(2, len(n_lock)) self.assertEqual(0, n_lock.obtained)
def test_acquired(self): lock1 = threading.Lock() lock2 = threading.Lock() n_lock = lock_utils.MultiLock((lock1, lock2)) self.assertTrue(n_lock.acquire()) try: self.assertTrue(lock1.locked()) self.assertTrue(lock2.locked()) finally: n_lock.release() self.assertFalse(lock1.locked()) self.assertFalse(lock2.locked())
def test_release_failure(self): lock1 = threading.Lock() lock2 = mock.create_autospec(threading.Lock()) lock2.acquire.return_value = True lock2.release.side_effect = RuntimeError("Broke") n_lock = lock_utils.MultiLock((lock1, lock2)) self.assertTrue(n_lock.acquire()) self.assertEqual(2, n_lock.obtained) self.assertRaises(threading.ThreadError, n_lock.release) self.assertEqual(2, n_lock.obtained) lock2.release.side_effect = None n_lock.release() self.assertEqual(0, n_lock.obtained)
def __init__(self, *args, **kwargs): test.TestCase.__init__(self, *args, **kwargs) # We need to make sure that each test goes through a set of locks # to ensure that multiple tests are not modifying the database, # dropping it, creating it at the same time. To accomplish this we use # a lock that ensures multiple parallel processes can't run at the # same time as well as a in-process lock to ensure that multiple # threads can't run at the same time. lock_path = os.path.join(tempfile.gettempdir(), 'taskflow-%s.lock' % (self.LOCK_NAME)) locks = [ lock_utils.InterProcessLock(lock_path), threading.RLock(), ] self.big_lock = lock_utils.MultiLock(locks)
def test_acquired_fail(self): activated = collections.deque() acquires = collections.deque() lock1 = threading.Lock() lock2 = threading.Lock() n_lock = lock_utils.MultiLock((lock1, lock2)) def run(): with n_lock as gotten: acquires.append(gotten) start = now() time.sleep(NAPPY_TIME) end = now() activated.append((start, end)) def run_fail(): try: with n_lock as gotten: acquires.append(gotten) raise RuntimeError() except RuntimeError: pass threads = [] for i in range(0, self.THREAD_COUNT): if i % 2 == 1: target = run_fail else: target = run t = threading_utils.daemon_thread(target) threads.append(t) t.start() while threads: t = threads.pop() t.join() self.assertEqual(self.THREAD_COUNT, len(acquires)) self.assertTrue(all(acquires)) for (start, end) in activated: self.assertEqual(1, _find_overlaps(activated, start, end)) self.assertFalse(lock1.locked()) self.assertFalse(lock2.locked())
def test_double_acquire_single(self): activated = collections.deque() def run(): start = time.time() time.sleep(0.05) end = time.time() activated.append((start, end)) lock1 = threading.RLock() lock2 = threading.RLock() n_lock = lock_utils.MultiLock((lock1, lock2)) with n_lock: run() with n_lock: run() run() for (start, end) in activated: self.assertEqual(1, _find_overlaps(activated, start, end))
def test_acquired_fail(self): activated = collections.deque() lock1 = threading.Lock() lock2 = threading.Lock() n_lock = lock_utils.MultiLock((lock1, lock2)) def run(): with n_lock: start = time.time() time.sleep(0.05) end = time.time() activated.append((start, end)) def run_fail(): try: with n_lock: raise RuntimeError() except RuntimeError: pass threads = [] for i in range(0, 20): if i % 2 == 1: target = run_fail else: target = run t = threading.Thread(target=target) threads.append(t) t.daemon = True t.start() while threads: t = threads.pop() t.join() for (start, end) in activated: self.assertEqual(1, _find_overlaps(activated, start, end)) self.assertFalse(lock1.locked()) self.assertFalse(lock2.locked())
def test_no_acquire_release(self): lock1 = threading.Lock() lock2 = threading.Lock() n_lock = lock_utils.MultiLock((lock1, lock2)) self.assertRaises(threading.ThreadError, n_lock.release)