示例#1
0
    def test_no_dir_hard_support(self):
        # Test dir test creating when dir does not support hard lock
        self.assertFalse(test_dir(self.temp_dir.name))
        lock_dir1 = get_lock_dir('no_dir_hard1')
        lock_dir2 = get_lock_dir('no_dir_hard2')
        lock_dir3 = get_lock_dir('no_dir_hard3')

        self.assertNotExist(lock_dir1)
        self.assertNotExist(lock_dir2)
        self.assertNotExist(lock_dir3)
        # When test would show using hard locks would fail
        resource1 = Resource('no_dir_hard1', 1, use_softfilelock=None)
        resource2 = Resource(
            'no_dir_hard2',
            1,  # noqa: F841
            use_softfilelock=True)
        resource3 = Resource(
            'no_dir_hard3',
            1,  # noqa: F841
            use_softfilelock=False)
        self.assertExist(lock_dir1, is_dir=True)
        self.assertNotExist(lock_dir2)
        self.assertNotExist(lock_dir3)

        self.assertEqual(resource1.FileLock, filelock.SoftFileLock)
示例#2
0
    def test_file_name(self):
        # test Resource.lock_file_name
        resource = Resource('stuff', 1)
        lock_dir = get_lock_dir('stuff')

        self.assertEqual(resource.lock_file_name(0, 0),
                         os.path.join(lock_dir, '0.0.lock'))

        self.assertEqual(resource.lock_file_name(10, 999),
                         os.path.join(lock_dir, '10.999.lock'))
示例#3
0
    def test_no_os_hard(self):
        # test when the os doesn't support hard locks
        lock_dir = get_lock_dir('no_os_hard')
        self.assertNotExist(lock_dir)
        resource1 = Resource('no_os_hard', 1, use_softfilelock=None)
        resource2 = Resource('no_os_hard', 1, use_softfilelock=False)
        resource3 = Resource('no_os_hard', 1, use_softfilelock=True)
        self.assertNotExist(lock_dir)

        self.assertEqual(resource1.FileLock, filelock.SoftFileLock)
        self.assertEqual(resource2.FileLock, filelock.SoftFileLock)
        self.assertEqual(resource3.FileLock, filelock.SoftFileLock)
示例#4
0
    def test_full(self):
        # Test resource recovery after a premature termination
        lock_dir = get_lock_dir('full')
        resource = Resource('full', ['foo'], 1)

        os.makedirs(lock_dir, exist_ok=True)
        with open(os.path.join(lock_dir, '0.0.lock'), 'w') as fid:
            fid.write(str(os.getpid()))

        with self.assertRaises(ResourceError):
            resource.acquire()

        process = Process(target=lambda: 0)
        process.start()
        dead_pid = process.pid
        process.join()

        with open(os.path.join(lock_dir, '0.0.lock'), 'w') as fid:
            fid.write(str(dead_pid))

        lock = resource.acquire()

        self.assertEqual(lock, 'foo')
        # Test that additional calls to acquire after recovering resource, work
        self.assertEqual(lock, resource.acquire())

        # Clean up warnings
        resource.release(force=True)
示例#5
0
    def test_release_on_delete(self):
        # test leftover locks are detected and cleaned up
        test = Resource('test', 1, 1)

        test.acquire()

        with self.assertLogs('terra.executor.resources',
                             level='WARNING') as cm:
            filename = test._local.lock._lock_file
            self.assertExist(filename)
            del (test)
            self.assertNotExist(filename)
        self.assertIn(
            'A test resource was not released. Cleaning up on delete.',
            cm.output[0])
示例#6
0
 def test_local_storage_type(self):
     # test the types are right
     resource = Resource('storage', 2, 1)
     if self.Executor.multiprocess:
         self.assertIsInstance(resource._local, ProcessLocalStorage)
     else:
         self.assertIsInstance(resource._local, ThreadLocalStorage)
示例#7
0
    def test_softlock_test(self):
        # Test dir test creating when os does support hard lock
        lock_dir1 = get_lock_dir('soft1')
        lock_dir2 = get_lock_dir('soft2')
        lock_dir3 = get_lock_dir('soft3')

        self.assertNotExist(lock_dir1)
        self.assertNotExist(lock_dir2)
        self.assertNotExist(lock_dir3)
        resource1 = Resource('soft1', 1, use_softfilelock=None)  # noqa: F841
        resource2 = Resource('soft2', 1, use_softfilelock=True)  # noqa: F841
        resource3 = Resource('soft3', 1, use_softfilelock=False)  # noqa: F841

        self.assertExist(lock_dir1, is_dir=True)
        self.assertNotExist(lock_dir2)
        self.assertNotExist(lock_dir3)
        self.assertTrue(is_dir_empty(lock_dir1))
示例#8
0
    def test_dirty_dir(self):
        # test leftover locks are detected and cleaned up
        lock_dir = get_lock_dir('dirty')
        os.makedirs(lock_dir, exist_ok=True)

        with self.assertLogs('terra.executor.resources',
                             level='WARNING') as cm:
            resource_logger.warning('None')
            Resource('dirty', 1, 1)
        self.assertEqual(len(cm.output), 1)

        with open(os.path.join(lock_dir, 'foo'), 'w') as fid:
            fid.write('ok')
        with self.assertLogs('terra.executor.resources',
                             level='WARNING') as cm:
            resource2 = Resource('dirty', 1, 1)

        self.assertIn('is not empty. Deleting it now', cm.output[0])
        self.assertFalse(os.path.exists(resource2.lock_dir))
示例#9
0
    def test_atexit(self):
        test2 = Resource('test2', 1, 1)
        test3 = Resource('test3', 1, 1)

        test2.acquire()
        test3.acquire()
        test3.acquire()

        filename2 = test2._local.lock._lock_file
        filename3 = test3._local.lock._lock_file
        self.assertExist(filename2)
        self.assertExist(filename3)
        atexit_resource_release()
        self.assertNotExist(filename2)
        self.assertNotExist(filename3)
示例#10
0
    def test_multiple_executor(self):
        # unlike test_acquire, this is not trying to test the exception, so there
        # is no need to force locks to not unlock. In fact that would break this
        # test. Test to see that locks are indeed cleaned up automatically in a
        # way that means one executor after the other will not interfere with each
        # other.
        data[self.name] = Resource(self.name, 1, 1)
        for _ in range(2):
            futures = []
            with self.Executor(max_workers=1) as executor:
                futures.append(executor.submit(simple_acquire, self.name))

                for future in as_completed(futures):
                    future.result()

        # double check resource was freed
        data[self.name].acquire()
        data[self.name].release()
示例#11
0
    def test_with_context(self):
        # test with
        resource = Resource('test', 2, 1)

        self.assertFalse(resource.is_locked)
        with resource as r1:
            self.assertTrue(resource.is_locked)

        self.assertFalse(resource.is_locked)

        with resource as r2:
            with resource as r3:
                self.assertTrue(resource.is_locked)
                self.assertEqual(resource._local.lock._lock_counter, 2)
            self.assertTrue(resource.is_locked)
        self.assertFalse(resource.is_locked)

        self.assertEqual(r1, r2)
        self.assertEqual(r2, r3)
示例#12
0
 def test_dir_cleanup(self):
     # Test that empty lock dir is auto deleted
     resource = Resource('test', 1, 1)
     if filelock.FileLock == filelock.SoftFileLock:
         self.assertNotExist(resource.lock_dir)
     else:
         self.assertExist(resource.lock_dir, is_dir=True)
     resource.acquire()
     self.assertExist(resource.lock_dir, is_dir=True)
     lock_file = resource._local.lock.lock_file
     self.assertExist(lock_file)
     resource.release()
     self.assertNotExist(lock_file)
     self.assertNotExist(resource.lock_dir)
示例#13
0
    def test_release(self):
        # test releasing a lock in a single thread
        test = Resource('test', 1, 1)

        test.acquire()
        lock = test._local.lock
        self.assertIsNotNone(test._local.lock)
        self.assertIsNotNone(test._local.resource_id)
        self.assertIsNotNone(test._local.instance_id)

        test.release()
        # make sure file and cache is cleaned up
        self.assertNotExist(lock.lock_file)
        self.assertIsNone(test._local.lock)
        self.assertIsNone(test._local.resource_id)
        self.assertIsNone(test._local.instance_id)
示例#14
0
    def test_acquire(self):
        # test acquiring in parallel
        data[self.name] = Resource(self.name, 2, 1)

        futures = []
        results = []
        exceptions = 0

        with self.Executor(max_workers=3) as executor:
            for i in range(3):
                futures.append(executor.submit(acquire, self.name, i))

            for future in as_completed(futures):
                try:
                    results.append(future.result())
                except ResourceError:
                    exceptions += 1
        self.assertEqual(exceptions, 1)

        self.assertNotEqual(results[0], results[1])
        self.assertEqual(results[0][0], results[0][1])
        self.assertEqual(results[1][0], results[1][1])
示例#15
0
 def test_force_release(self):
     test = Resource('test', 1, 1)
     test.acquire()
     test.acquire()
     test.release(force=True)
     self.assertFalse(test.is_locked)
示例#16
0
    def test_acquire_single(self):
        # test acquiring a lock in a single thread
        test1 = Resource('single', 2, 1)
        test2 = Resource('single', 2, 1)
        test3 = Resource('single', 2, 1)

        lock1 = test1.acquire()
        lock2 = test1.acquire()

        # Acquiring twice, should use the same value
        self.assertEqual(lock1, lock2)

        lock3 = test2.acquire()
        # However, using an entirely different resource instance, won't have cache
        self.assertNotEqual(lock1, lock3)

        # At this point, I should be out of resources
        with self.assertRaises(ResourceError):
            test3.acquire()

        # cleanup warnings
        test1.release(force=True)
        test2.release(force=True)
示例#17
0
    def test_multiple_release(self):
        test = Resource('test', 1, 1)
        self.assertFalse(test.is_locked)
        test.acquire()
        self.assertTrue(test.is_locked)
        self.assertEqual(test._local.lock._lock_counter, 1)
        test.acquire()
        self.assertTrue(test.is_locked)
        self.assertEqual(test._local.lock._lock_counter, 2)

        test.release()
        self.assertTrue(test.is_locked)
        self.assertEqual(test._local.lock._lock_counter, 1)

        test.release()
        self.assertFalse(test.is_locked)

        with self.assertRaisesRegex(ValueError,
                                    "Release called with no lock acquired"):
            test.release()
示例#18
0
    def test_repeats(self):
        # test repeated resources
        repeat1 = Resource('repeat', 2, 2)
        repeat2 = Resource('repeat', 2, 2)
        repeat3 = Resource('repeat', 2, 2)
        repeat4 = Resource('repeat', 2, 2)
        repeat5 = Resource('repeat', 2, 2)

        lock1 = repeat1.acquire()
        lock2 = repeat2.acquire()
        lock3 = repeat3.acquire()
        lock4 = repeat4.acquire()

        # Four unique names
        self.assertEqual(
            len({
                repeat1._local.lock.lock_file, repeat2._local.lock.lock_file,
                repeat3._local.lock.lock_file, repeat4._local.lock.lock_file
            }), 4)

        # reacquire, cache
        lock1b = repeat1.acquire()
        lock2b = repeat2.acquire()
        lock3b = repeat3.acquire()
        lock4b = repeat4.acquire()

        self.assertEqual(lock1, lock1b)
        self.assertEqual(lock2, lock2b)
        self.assertEqual(lock3, lock3b)
        self.assertEqual(lock4, lock4b)

        with self.assertRaises(ResourceError):
            repeat5.acquire()

        self.assertEqual(lock1, 0)
        self.assertEqual(repeat1._local.instance_id, 0)
        self.assertEqual(lock2, 1)
        self.assertEqual(repeat2._local.instance_id, 0)
        self.assertEqual(lock3, 0)
        self.assertEqual(repeat3._local.instance_id, 1)
        self.assertEqual(lock4, 1)
        self.assertEqual(repeat4._local.instance_id, 1)

        # Clean up warnings
        repeat1.release(force=True)
        repeat2.release(force=True)
        repeat3.release(force=True)
        repeat4.release(force=True)
示例#19
0
    def test_items(self):
        # Test list of objects as resources
        resource1 = Resource('items', ['foo', 'bar'])
        resource2 = Resource('items', ['foo', 'bar'])
        resource3 = Resource('items', ['foo', 'bar'])

        foo = resource1.acquire()
        self.assertEqual(foo, 'foo')
        self.assertEqual(foo, resource1.acquire())

        bar = resource2.acquire()
        self.assertEqual(bar, 'bar')
        self.assertEqual(bar, resource2.acquire())

        with self.assertRaises(ResourceError):
            resource3.acquire()

        # Clean up warnings
        resource1.release(force=True)
        resource2.release(force=True)
示例#20
0
    def test_none(self):
        # Early version of the code used None in such a way it tripped up the logic
        # This test is to make sure that doesn't happen again.

        resource1 = Resource('none', [None, None, 1], 1)
        resource2 = Resource('none', [None, None, 1], 1)
        resource3 = Resource('none', [None, None], 1)

        n1 = resource1.acquire()
        self.assertIsNone(n1)
        # Prevent the accidental delete lock loophole, which would create a race
        # condition, if not caught
        lock1 = resource1._local.lock
        self.assertIsNone(resource1.acquire())

        n2 = resource2.acquire()
        self.assertIsNone(n2)
        # resource2 should already be acquired, make sure it's not accidentally
        # unlocking and relocking again
        lock1.release()
        self.assertIsNone(resource2.acquire())
        lock1.acquire(timeout=0)

        # two unique names
        self.assertEqual(
            len({
                resource1._local.lock.lock_file,
                resource2._local.lock.lock_file
            }), 2)

        with self.assertRaises(ResourceError):
            resource3.acquire()

        # Clean up warnings
        resource1.release(force=True)
        resource2.release(force=True)
示例#21
0
 def test_resource_registry(self):
     # Test that the ledger of all resources is working
     resource = Resource('ok', 1)
     self.assertIn(resource, Resource._resources)
     resource = None
     self.assertNotIn(resource, Resource._resources)