def test_read_lock_no_lockfile(lock_dir, lock_path): """read-only directory, no lockfile (so can't create).""" with read_only(lock_dir): lock = lk.Lock(lock_path) with pytest.raises(lk.CantCreateLockError): with lk.ReadTransaction(lock): pass with pytest.raises(lk.CantCreateLockError): with lk.WriteTransaction(lock): pass
def test_read_lock_on_read_only_lockfile(lock_dir, lock_path): """read-only directory, read-only lockfile.""" touch(lock_path) with read_only(lock_path, lock_dir): lock = lk.Lock(lock_path) with lk.ReadTransaction(lock): pass with pytest.raises(lk.LockROFileError): with lk.WriteTransaction(lock): pass
def test_nested_reads(lock_path): """Ensure that write transactions won't re-read data.""" def read(): vals['read'] += 1 vals = collections.defaultdict(lambda: 0) lock = AssertLock(lock_path, vals) # read/read vals.clear() assert vals['read'] == 0 with lk.ReadTransaction(lock, acquire=read): assert vals['read'] == 1 with lk.ReadTransaction(lock, acquire=read): assert vals['read'] == 1 # write/write vals.clear() assert vals['read'] == 0 with lk.WriteTransaction(lock, acquire=read): assert vals['read'] == 1 with lk.WriteTransaction(lock, acquire=read): assert vals['read'] == 1 # read/write vals.clear() assert vals['read'] == 0 with lk.ReadTransaction(lock, acquire=read): assert vals['read'] == 1 with lk.WriteTransaction(lock, acquire=read): assert vals['read'] == 1 # write/read/write vals.clear() assert vals['read'] == 0 with lk.WriteTransaction(lock, acquire=read): assert vals['read'] == 1 with lk.ReadTransaction(lock, acquire=read): assert vals['read'] == 1 with lk.WriteTransaction(lock, acquire=read): assert vals['read'] == 1 # read/write/read/write vals.clear() assert vals['read'] == 0 with lk.ReadTransaction(lock, acquire=read): assert vals['read'] == 1 with lk.WriteTransaction(lock, acquire=read): assert vals['read'] == 1 with lk.ReadTransaction(lock, acquire=read): assert vals['read'] == 1 with lk.WriteTransaction(lock, acquire=read): assert vals['read'] == 1
def test_nested_write_transaction(lock_path): """Ensure that the outermost write transaction writes.""" def write(t, v, tb): vals['wrote'] = True vals = collections.defaultdict(lambda: False) lock = AssertLock(lock_path, vals) # write/write with lk.WriteTransaction(lock, release=write): assert not vals['wrote'] with lk.WriteTransaction(lock, release=write): assert not vals['wrote'] assert not vals['wrote'] assert vals['wrote'] # read/write vals.clear() with lk.ReadTransaction(lock): assert not vals['wrote'] with lk.WriteTransaction(lock, release=write): assert not vals['wrote'] assert vals['wrote'] # write/read/write vals.clear() with lk.WriteTransaction(lock, release=write): assert not vals['wrote'] with lk.ReadTransaction(lock): assert not vals['wrote'] with lk.WriteTransaction(lock, release=write): assert not vals['wrote'] assert not vals['wrote'] assert not vals['wrote'] assert vals['wrote'] # read/write/read/write vals.clear() with lk.ReadTransaction(lock): with lk.WriteTransaction(lock, release=write): assert not vals['wrote'] with lk.ReadTransaction(lock): assert not vals['wrote'] with lk.WriteTransaction(lock, release=write): assert not vals['wrote'] assert not vals['wrote'] assert not vals['wrote'] assert vals['wrote']
def test_transaction(lock_path): def enter_fn(): vals['entered'] = True def exit_fn(t, v, tb): vals['exited'] = True vals['exception'] = (t or v or tb) lock = lk.Lock(lock_path) vals = {'entered': False, 'exited': False, 'exception': False} with lk.ReadTransaction(lock, enter_fn, exit_fn): pass assert vals['entered'] assert vals['exited'] assert not vals['exception'] vals = {'entered': False, 'exited': False, 'exception': False} with lk.WriteTransaction(lock, enter_fn, exit_fn): pass assert vals['entered'] assert vals['exited'] assert not vals['exception']
def do_write_with_exception(exit_fn): with lk.WriteTransaction(lock, TestContextManager, exit_fn): raise Exception()
def do_write_with_exception(): with lk.WriteTransaction(lock, enter_fn, exit_fn): raise Exception()
def test_lock_with_no_parent_directory(tmpdir): """Make sure locks work even when their parent directory does not exist.""" with tmpdir.as_cwd(): lock = lk.Lock('foo/bar/baz/lockfile') with lk.WriteTransaction(lock): pass
def test_transaction_with_context_manager(lock_path): class TestContextManager(object): def __enter__(self): vals['entered'] = True def __exit__(self, t, v, tb): vals['exited'] = True vals['exception'] = (t or v or tb) def exit_fn(t, v, tb): vals['exited_fn'] = True vals['exception_fn'] = (t or v or tb) lock = lk.Lock(lock_path) vals = { 'entered': False, 'exited': False, 'exited_fn': False, 'exception': False, 'exception_fn': False } with lk.ReadTransaction(lock, TestContextManager, exit_fn): pass assert vals['entered'] assert vals['exited'] assert not vals['exception'] assert vals['exited_fn'] assert not vals['exception_fn'] vals = { 'entered': False, 'exited': False, 'exited_fn': False, 'exception': False, 'exception_fn': False } with lk.ReadTransaction(lock, TestContextManager): pass assert vals['entered'] assert vals['exited'] assert not vals['exception'] assert not vals['exited_fn'] assert not vals['exception_fn'] vals = { 'entered': False, 'exited': False, 'exited_fn': False, 'exception': False, 'exception_fn': False } with lk.WriteTransaction(lock, TestContextManager, exit_fn): pass assert vals['entered'] assert vals['exited'] assert not vals['exception'] assert vals['exited_fn'] assert not vals['exception_fn'] vals = { 'entered': False, 'exited': False, 'exited_fn': False, 'exception': False, 'exception_fn': False } with lk.WriteTransaction(lock, TestContextManager): pass assert vals['entered'] assert vals['exited'] assert not vals['exception'] assert not vals['exited_fn'] assert not vals['exception_fn']