tests: Separate tests for llnl.util.lock and spack.util.lock
- llnl.util.lock tests are now independent of Spack
This commit is contained in:
		| @@ -96,7 +96,7 @@ def test(parser, args, unknown_args): | |||||||
|         pytest.main(['-h']) |         pytest.main(['-h']) | ||||||
|         return |         return | ||||||
|  |  | ||||||
|     # pytest.ini lives in the root of the spack repository. |     # pytest.ini lives in lib/spack/spack/test | ||||||
|     with working_dir(spack.paths.test_path): |     with working_dir(spack.paths.test_path): | ||||||
|         # --list and --long-list print the test output better. |         # --list and --long-list print the test output better. | ||||||
|         if args.list or args.long_list: |         if args.list or args.long_list: | ||||||
|   | |||||||
| @@ -1,24 +0,0 @@ | |||||||
| ############################################################################## |  | ||||||
| # Copyright (c) 2013-2018, Lawrence Livermore National Security, LLC. |  | ||||||
| # Produced at the Lawrence Livermore National Laboratory. |  | ||||||
| # |  | ||||||
| # This file is part of Spack. |  | ||||||
| # Created by Todd Gamblin, tgamblin@llnl.gov, All rights reserved. |  | ||||||
| # LLNL-CODE-647188 |  | ||||||
| # |  | ||||||
| # For details, see https://github.com/spack/spack |  | ||||||
| # Please also see the NOTICE and LICENSE files for our notice and the LGPL. |  | ||||||
| # |  | ||||||
| # This program is free software; you can redistribute it and/or modify |  | ||||||
| # it under the terms of the GNU Lesser General Public License (as |  | ||||||
| # published by the Free Software Foundation) version 2.1, February 1999. |  | ||||||
| # |  | ||||||
| # This program is distributed in the hope that it will be useful, but |  | ||||||
| # WITHOUT ANY WARRANTY; without even the IMPLIED WARRANTY OF |  | ||||||
| # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the terms and |  | ||||||
| # conditions of the GNU Lesser General Public License for more details. |  | ||||||
| # |  | ||||||
| # You should have received a copy of the GNU Lesser General Public |  | ||||||
| # License along with this program; if not, write to the Free Software |  | ||||||
| # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |  | ||||||
| ############################################################################## |  | ||||||
| @@ -72,11 +72,9 @@ | |||||||
|  |  | ||||||
| import pytest | import pytest | ||||||
|  |  | ||||||
|  | import llnl.util.lock as lk | ||||||
| import llnl.util.multiproc as mp | import llnl.util.multiproc as mp | ||||||
| from llnl.util.filesystem import touch, group_ids | from llnl.util.filesystem import touch | ||||||
|  |  | ||||||
| import spack.util.lock |  | ||||||
| from spack.util.lock import Lock, WriteTransaction, ReadTransaction, LockError |  | ||||||
|  |  | ||||||
|  |  | ||||||
| # | # | ||||||
| @@ -267,7 +265,7 @@ def wait(self): | |||||||
| # | # | ||||||
| def acquire_write(lock_path, start=0, length=0): | def acquire_write(lock_path, start=0, length=0): | ||||||
|     def fn(barrier): |     def fn(barrier): | ||||||
|         lock = Lock(lock_path, start, length) |         lock = lk.Lock(lock_path, start, length) | ||||||
|         lock.acquire_write()  # grab exclusive lock |         lock.acquire_write()  # grab exclusive lock | ||||||
|         barrier.wait() |         barrier.wait() | ||||||
|         barrier.wait()  # hold the lock until timeout in other procs. |         barrier.wait()  # hold the lock until timeout in other procs. | ||||||
| @@ -276,7 +274,7 @@ def fn(barrier): | |||||||
|  |  | ||||||
| def acquire_read(lock_path, start=0, length=0): | def acquire_read(lock_path, start=0, length=0): | ||||||
|     def fn(barrier): |     def fn(barrier): | ||||||
|         lock = Lock(lock_path, start, length) |         lock = lk.Lock(lock_path, start, length) | ||||||
|         lock.acquire_read()  # grab shared lock |         lock.acquire_read()  # grab shared lock | ||||||
|         barrier.wait() |         barrier.wait() | ||||||
|         barrier.wait()  # hold the lock until timeout in other procs. |         barrier.wait()  # hold the lock until timeout in other procs. | ||||||
| @@ -285,9 +283,9 @@ def fn(barrier): | |||||||
|  |  | ||||||
| def timeout_write(lock_path, start=0, length=0): | def timeout_write(lock_path, start=0, length=0): | ||||||
|     def fn(barrier): |     def fn(barrier): | ||||||
|         lock = Lock(lock_path, start, length) |         lock = lk.Lock(lock_path, start, length) | ||||||
|         barrier.wait()  # wait for lock acquire in first process |         barrier.wait()  # wait for lock acquire in first process | ||||||
|         with pytest.raises(LockError): |         with pytest.raises(lk.LockError): | ||||||
|             lock.acquire_write(lock_fail_timeout) |             lock.acquire_write(lock_fail_timeout) | ||||||
|         barrier.wait() |         barrier.wait() | ||||||
|     return fn |     return fn | ||||||
| @@ -295,9 +293,9 @@ def fn(barrier): | |||||||
|  |  | ||||||
| def timeout_read(lock_path, start=0, length=0): | def timeout_read(lock_path, start=0, length=0): | ||||||
|     def fn(barrier): |     def fn(barrier): | ||||||
|         lock = Lock(lock_path, start, length) |         lock = lk.Lock(lock_path, start, length) | ||||||
|         barrier.wait()  # wait for lock acquire in first process |         barrier.wait()  # wait for lock acquire in first process | ||||||
|         with pytest.raises(LockError): |         with pytest.raises(lk.LockError): | ||||||
|             lock.acquire_read(lock_fail_timeout) |             lock.acquire_read(lock_fail_timeout) | ||||||
|         barrier.wait() |         barrier.wait() | ||||||
|     return fn |     return fn | ||||||
| @@ -552,7 +550,7 @@ def test_upgrade_read_to_write(private_lock_path): | |||||||
|     # to begin wtih. |     # to begin wtih. | ||||||
|     touch(private_lock_path) |     touch(private_lock_path) | ||||||
|  |  | ||||||
|     lock = Lock(private_lock_path) |     lock = lk.Lock(private_lock_path) | ||||||
|     assert lock._reads == 0 |     assert lock._reads == 0 | ||||||
|     assert lock._writes == 0 |     assert lock._writes == 0 | ||||||
|  |  | ||||||
| @@ -577,16 +575,14 @@ def test_upgrade_read_to_write(private_lock_path): | |||||||
|     assert lock._file is None |     assert lock._file is None | ||||||
|  |  | ||||||
|  |  | ||||||
| # |  | ||||||
| # Test that read-only file can be read-locked but not write-locked. |  | ||||||
| # |  | ||||||
| def test_upgrade_read_to_write_fails_with_readonly_file(private_lock_path): | def test_upgrade_read_to_write_fails_with_readonly_file(private_lock_path): | ||||||
|     # ensure lock file exists the first time, so we open it read-only |     """Test that read-only file can be read-locked but not write-locked.""" | ||||||
|     # to begin wtih. |     # ensure lock file exists the first time | ||||||
|     touch(private_lock_path) |     touch(private_lock_path) | ||||||
|  |  | ||||||
|  |     # open it read-only to begin wtih. | ||||||
|     with read_only(private_lock_path): |     with read_only(private_lock_path): | ||||||
|         lock = Lock(private_lock_path) |         lock = lk.Lock(private_lock_path) | ||||||
|         assert lock._reads == 0 |         assert lock._reads == 0 | ||||||
|         assert lock._writes == 0 |         assert lock._writes == 0 | ||||||
|  |  | ||||||
| @@ -595,7 +591,8 @@ def test_upgrade_read_to_write_fails_with_readonly_file(private_lock_path): | |||||||
|         assert lock._writes == 0 |         assert lock._writes == 0 | ||||||
|         assert lock._file.mode == 'r' |         assert lock._file.mode == 'r' | ||||||
|  |  | ||||||
|         with pytest.raises(LockError): |         # upgrade to writ here | ||||||
|  |         with pytest.raises(lk.LockError): | ||||||
|             lock.acquire_write() |             lock.acquire_write() | ||||||
|  |  | ||||||
|  |  | ||||||
| @@ -605,7 +602,7 @@ def test_upgrade_read_to_write_fails_with_readonly_file(private_lock_path): | |||||||
| # | # | ||||||
| def test_complex_acquire_and_release_chain(lock_path): | def test_complex_acquire_and_release_chain(lock_path): | ||||||
|     def p1(barrier): |     def p1(barrier): | ||||||
|         lock = Lock(lock_path) |         lock = lk.Lock(lock_path) | ||||||
|  |  | ||||||
|         lock.acquire_write() |         lock.acquire_write() | ||||||
|         barrier.wait()  # ---------------------------------------- 1 |         barrier.wait()  # ---------------------------------------- 1 | ||||||
| @@ -613,7 +610,7 @@ def p1(barrier): | |||||||
|         barrier.wait()  # ---------------------------------------- 2 |         barrier.wait()  # ---------------------------------------- 2 | ||||||
|         lock.release_write()   # release and others acquire read |         lock.release_write()   # release and others acquire read | ||||||
|         barrier.wait()  # ---------------------------------------- 3 |         barrier.wait()  # ---------------------------------------- 3 | ||||||
|         with pytest.raises(LockError): |         with pytest.raises(lk.LockError): | ||||||
|             lock.acquire_write(lock_fail_timeout) |             lock.acquire_write(lock_fail_timeout) | ||||||
|         lock.acquire_read() |         lock.acquire_read() | ||||||
|         barrier.wait()  # ---------------------------------------- 4 |         barrier.wait()  # ---------------------------------------- 4 | ||||||
| @@ -622,9 +619,9 @@ def p1(barrier): | |||||||
|  |  | ||||||
|         # p2 upgrades read to write |         # p2 upgrades read to write | ||||||
|         barrier.wait()  # ---------------------------------------- 6 |         barrier.wait()  # ---------------------------------------- 6 | ||||||
|         with pytest.raises(LockError): |         with pytest.raises(lk.LockError): | ||||||
|             lock.acquire_write(lock_fail_timeout) |             lock.acquire_write(lock_fail_timeout) | ||||||
|         with pytest.raises(LockError): |         with pytest.raises(lk.LockError): | ||||||
|             lock.acquire_read(lock_fail_timeout) |             lock.acquire_read(lock_fail_timeout) | ||||||
|         barrier.wait()  # ---------------------------------------- 7 |         barrier.wait()  # ---------------------------------------- 7 | ||||||
|         # p2 releases write and read |         # p2 releases write and read | ||||||
| @@ -634,9 +631,9 @@ def p1(barrier): | |||||||
|         barrier.wait()  # ---------------------------------------- 9 |         barrier.wait()  # ---------------------------------------- 9 | ||||||
|         # p3 upgrades read to write |         # p3 upgrades read to write | ||||||
|         barrier.wait()  # ---------------------------------------- 10 |         barrier.wait()  # ---------------------------------------- 10 | ||||||
|         with pytest.raises(LockError): |         with pytest.raises(lk.LockError): | ||||||
|             lock.acquire_write(lock_fail_timeout) |             lock.acquire_write(lock_fail_timeout) | ||||||
|         with pytest.raises(LockError): |         with pytest.raises(lk.LockError): | ||||||
|             lock.acquire_read(lock_fail_timeout) |             lock.acquire_read(lock_fail_timeout) | ||||||
|         barrier.wait()  # ---------------------------------------- 11 |         barrier.wait()  # ---------------------------------------- 11 | ||||||
|         # p3 releases locks |         # p3 releases locks | ||||||
| @@ -646,13 +643,13 @@ def p1(barrier): | |||||||
|         lock.release_read() |         lock.release_read() | ||||||
|  |  | ||||||
|     def p2(barrier): |     def p2(barrier): | ||||||
|         lock = Lock(lock_path) |         lock = lk.Lock(lock_path) | ||||||
|  |  | ||||||
|         # p1 acquires write |         # p1 acquires write | ||||||
|         barrier.wait()  # ---------------------------------------- 1 |         barrier.wait()  # ---------------------------------------- 1 | ||||||
|         with pytest.raises(LockError): |         with pytest.raises(lk.LockError): | ||||||
|             lock.acquire_write(lock_fail_timeout) |             lock.acquire_write(lock_fail_timeout) | ||||||
|         with pytest.raises(LockError): |         with pytest.raises(lk.LockError): | ||||||
|             lock.acquire_read(lock_fail_timeout) |             lock.acquire_read(lock_fail_timeout) | ||||||
|         barrier.wait()  # ---------------------------------------- 2 |         barrier.wait()  # ---------------------------------------- 2 | ||||||
|         lock.acquire_read() |         lock.acquire_read() | ||||||
| @@ -674,9 +671,9 @@ def p2(barrier): | |||||||
|         barrier.wait()  # ---------------------------------------- 9 |         barrier.wait()  # ---------------------------------------- 9 | ||||||
|         # p3 upgrades read to write |         # p3 upgrades read to write | ||||||
|         barrier.wait()  # ---------------------------------------- 10 |         barrier.wait()  # ---------------------------------------- 10 | ||||||
|         with pytest.raises(LockError): |         with pytest.raises(lk.LockError): | ||||||
|             lock.acquire_write(lock_fail_timeout) |             lock.acquire_write(lock_fail_timeout) | ||||||
|         with pytest.raises(LockError): |         with pytest.raises(lk.LockError): | ||||||
|             lock.acquire_read(lock_fail_timeout) |             lock.acquire_read(lock_fail_timeout) | ||||||
|         barrier.wait()  # ---------------------------------------- 11 |         barrier.wait()  # ---------------------------------------- 11 | ||||||
|         # p3 releases locks |         # p3 releases locks | ||||||
| @@ -686,13 +683,13 @@ def p2(barrier): | |||||||
|         lock.release_read() |         lock.release_read() | ||||||
|  |  | ||||||
|     def p3(barrier): |     def p3(barrier): | ||||||
|         lock = Lock(lock_path) |         lock = lk.Lock(lock_path) | ||||||
|  |  | ||||||
|         # p1 acquires write |         # p1 acquires write | ||||||
|         barrier.wait()  # ---------------------------------------- 1 |         barrier.wait()  # ---------------------------------------- 1 | ||||||
|         with pytest.raises(LockError): |         with pytest.raises(lk.LockError): | ||||||
|             lock.acquire_write(lock_fail_timeout) |             lock.acquire_write(lock_fail_timeout) | ||||||
|         with pytest.raises(LockError): |         with pytest.raises(lk.LockError): | ||||||
|             lock.acquire_read(lock_fail_timeout) |             lock.acquire_read(lock_fail_timeout) | ||||||
|         barrier.wait()  # ---------------------------------------- 2 |         barrier.wait()  # ---------------------------------------- 2 | ||||||
|         lock.acquire_read() |         lock.acquire_read() | ||||||
| @@ -704,9 +701,9 @@ def p3(barrier): | |||||||
|  |  | ||||||
|         # p2 upgrades read to write |         # p2 upgrades read to write | ||||||
|         barrier.wait()  # ---------------------------------------- 6 |         barrier.wait()  # ---------------------------------------- 6 | ||||||
|         with pytest.raises(LockError): |         with pytest.raises(lk.LockError): | ||||||
|             lock.acquire_write(lock_fail_timeout) |             lock.acquire_write(lock_fail_timeout) | ||||||
|         with pytest.raises(LockError): |         with pytest.raises(lk.LockError): | ||||||
|             lock.acquire_read(lock_fail_timeout) |             lock.acquire_read(lock_fail_timeout) | ||||||
|         barrier.wait()  # ---------------------------------------- 7 |         barrier.wait()  # ---------------------------------------- 7 | ||||||
|         # p2 releases write & read |         # p2 releases write & read | ||||||
| @@ -736,9 +733,9 @@ def exit_fn(t, v, tb): | |||||||
|         vals['exited'] = True |         vals['exited'] = True | ||||||
|         vals['exception'] = (t or v or tb) |         vals['exception'] = (t or v or tb) | ||||||
|  |  | ||||||
|     lock = Lock(lock_path) |     lock = lk.Lock(lock_path) | ||||||
|     vals = {'entered': False, 'exited': False, 'exception': False} |     vals = {'entered': False, 'exited': False, 'exception': False} | ||||||
|     with ReadTransaction(lock, enter_fn, exit_fn): |     with lk.ReadTransaction(lock, enter_fn, exit_fn): | ||||||
|         pass |         pass | ||||||
|  |  | ||||||
|     assert vals['entered'] |     assert vals['entered'] | ||||||
| @@ -746,7 +743,7 @@ def exit_fn(t, v, tb): | |||||||
|     assert not vals['exception'] |     assert not vals['exception'] | ||||||
|  |  | ||||||
|     vals = {'entered': False, 'exited': False, 'exception': False} |     vals = {'entered': False, 'exited': False, 'exception': False} | ||||||
|     with WriteTransaction(lock, enter_fn, exit_fn): |     with lk.WriteTransaction(lock, enter_fn, exit_fn): | ||||||
|         pass |         pass | ||||||
|  |  | ||||||
|     assert vals['entered'] |     assert vals['entered'] | ||||||
| @@ -762,14 +759,14 @@ def exit_fn(t, v, tb): | |||||||
|         vals['exited'] = True |         vals['exited'] = True | ||||||
|         vals['exception'] = (t or v or tb) |         vals['exception'] = (t or v or tb) | ||||||
|  |  | ||||||
|     lock = Lock(lock_path) |     lock = lk.Lock(lock_path) | ||||||
|  |  | ||||||
|     def do_read_with_exception(): |     def do_read_with_exception(): | ||||||
|         with ReadTransaction(lock, enter_fn, exit_fn): |         with lk.ReadTransaction(lock, enter_fn, exit_fn): | ||||||
|             raise Exception() |             raise Exception() | ||||||
|  |  | ||||||
|     def do_write_with_exception(): |     def do_write_with_exception(): | ||||||
|         with WriteTransaction(lock, enter_fn, exit_fn): |         with lk.WriteTransaction(lock, enter_fn, exit_fn): | ||||||
|             raise Exception() |             raise Exception() | ||||||
|  |  | ||||||
|     vals = {'entered': False, 'exited': False, 'exception': False} |     vals = {'entered': False, 'exited': False, 'exception': False} | ||||||
| @@ -801,11 +798,11 @@ def exit_fn(t, v, tb): | |||||||
|         vals['exited_fn'] = True |         vals['exited_fn'] = True | ||||||
|         vals['exception_fn'] = (t or v or tb) |         vals['exception_fn'] = (t or v or tb) | ||||||
|  |  | ||||||
|     lock = Lock(lock_path) |     lock = lk.Lock(lock_path) | ||||||
|  |  | ||||||
|     vals = {'entered': False, 'exited': False, 'exited_fn': False, |     vals = {'entered': False, 'exited': False, 'exited_fn': False, | ||||||
|             'exception': False, 'exception_fn': False} |             'exception': False, 'exception_fn': False} | ||||||
|     with ReadTransaction(lock, TestContextManager, exit_fn): |     with lk.ReadTransaction(lock, TestContextManager, exit_fn): | ||||||
|         pass |         pass | ||||||
|  |  | ||||||
|     assert vals['entered'] |     assert vals['entered'] | ||||||
| @@ -816,7 +813,7 @@ def exit_fn(t, v, tb): | |||||||
|  |  | ||||||
|     vals = {'entered': False, 'exited': False, 'exited_fn': False, |     vals = {'entered': False, 'exited': False, 'exited_fn': False, | ||||||
|             'exception': False, 'exception_fn': False} |             'exception': False, 'exception_fn': False} | ||||||
|     with ReadTransaction(lock, TestContextManager): |     with lk.ReadTransaction(lock, TestContextManager): | ||||||
|         pass |         pass | ||||||
|  |  | ||||||
|     assert vals['entered'] |     assert vals['entered'] | ||||||
| @@ -827,7 +824,7 @@ def exit_fn(t, v, tb): | |||||||
|  |  | ||||||
|     vals = {'entered': False, 'exited': False, 'exited_fn': False, |     vals = {'entered': False, 'exited': False, 'exited_fn': False, | ||||||
|             'exception': False, 'exception_fn': False} |             'exception': False, 'exception_fn': False} | ||||||
|     with WriteTransaction(lock, TestContextManager, exit_fn): |     with lk.WriteTransaction(lock, TestContextManager, exit_fn): | ||||||
|         pass |         pass | ||||||
|  |  | ||||||
|     assert vals['entered'] |     assert vals['entered'] | ||||||
| @@ -838,7 +835,7 @@ def exit_fn(t, v, tb): | |||||||
|  |  | ||||||
|     vals = {'entered': False, 'exited': False, 'exited_fn': False, |     vals = {'entered': False, 'exited': False, 'exited_fn': False, | ||||||
|             'exception': False, 'exception_fn': False} |             'exception': False, 'exception_fn': False} | ||||||
|     with WriteTransaction(lock, TestContextManager): |     with lk.WriteTransaction(lock, TestContextManager): | ||||||
|         pass |         pass | ||||||
|  |  | ||||||
|     assert vals['entered'] |     assert vals['entered'] | ||||||
| @@ -861,14 +858,14 @@ def exit_fn(t, v, tb): | |||||||
|         vals['exited_fn'] = True |         vals['exited_fn'] = True | ||||||
|         vals['exception_fn'] = (t or v or tb) |         vals['exception_fn'] = (t or v or tb) | ||||||
|  |  | ||||||
|     lock = Lock(lock_path) |     lock = lk.Lock(lock_path) | ||||||
|  |  | ||||||
|     def do_read_with_exception(exit_fn): |     def do_read_with_exception(exit_fn): | ||||||
|         with ReadTransaction(lock, TestContextManager, exit_fn): |         with lk.ReadTransaction(lock, TestContextManager, exit_fn): | ||||||
|             raise Exception() |             raise Exception() | ||||||
|  |  | ||||||
|     def do_write_with_exception(exit_fn): |     def do_write_with_exception(exit_fn): | ||||||
|         with WriteTransaction(lock, TestContextManager, exit_fn): |         with lk.WriteTransaction(lock, TestContextManager, exit_fn): | ||||||
|             raise Exception() |             raise Exception() | ||||||
|  |  | ||||||
|     vals = {'entered': False, 'exited': False, 'exited_fn': False, |     vals = {'entered': False, 'exited': False, 'exited_fn': False, | ||||||
| @@ -910,91 +907,3 @@ def do_write_with_exception(exit_fn): | |||||||
|     assert vals['exception'] |     assert vals['exception'] | ||||||
|     assert not vals['exited_fn'] |     assert not vals['exited_fn'] | ||||||
|     assert not vals['exception_fn'] |     assert not vals['exception_fn'] | ||||||
|  |  | ||||||
|  |  | ||||||
| def test_disable_locking(private_lock_path): |  | ||||||
|     """Ensure that locks do no real locking when disabled.""" |  | ||||||
|     old_value = spack.config.get('config:locks') |  | ||||||
|  |  | ||||||
|     with spack.config.override('config:locks', False): |  | ||||||
|         lock = Lock(private_lock_path) |  | ||||||
|  |  | ||||||
|         lock.acquire_read() |  | ||||||
|         assert not os.path.exists(private_lock_path) |  | ||||||
|  |  | ||||||
|         lock.acquire_write() |  | ||||||
|         assert not os.path.exists(private_lock_path) |  | ||||||
|  |  | ||||||
|         lock.release_write() |  | ||||||
|         assert not os.path.exists(private_lock_path) |  | ||||||
|  |  | ||||||
|         lock.release_read() |  | ||||||
|         assert not os.path.exists(private_lock_path) |  | ||||||
|  |  | ||||||
|     assert old_value == spack.config.get('config:locks') |  | ||||||
|  |  | ||||||
|  |  | ||||||
| def test_lock_checks_user(tmpdir): |  | ||||||
|     """Ensure lock checks work with a self-owned, self-group repo.""" |  | ||||||
|     uid = os.getuid() |  | ||||||
|     if uid not in group_ids(): |  | ||||||
|         pytest.skip("user has no group with gid == uid") |  | ||||||
|  |  | ||||||
|     # self-owned, own group |  | ||||||
|     tmpdir.chown(uid, uid) |  | ||||||
|  |  | ||||||
|     # safe |  | ||||||
|     path = str(tmpdir) |  | ||||||
|     tmpdir.chmod(0o744) |  | ||||||
|     spack.util.lock.check_lock_safety(path) |  | ||||||
|  |  | ||||||
|     # safe |  | ||||||
|     tmpdir.chmod(0o774) |  | ||||||
|     spack.util.lock.check_lock_safety(path) |  | ||||||
|  |  | ||||||
|     # unsafe |  | ||||||
|     tmpdir.chmod(0o777) |  | ||||||
|     with pytest.raises(spack.error.SpackError): |  | ||||||
|         spack.util.lock.check_lock_safety(path) |  | ||||||
|  |  | ||||||
|     # safe |  | ||||||
|     tmpdir.chmod(0o474) |  | ||||||
|     spack.util.lock.check_lock_safety(path) |  | ||||||
|  |  | ||||||
|     # safe |  | ||||||
|     tmpdir.chmod(0o477) |  | ||||||
|     spack.util.lock.check_lock_safety(path) |  | ||||||
|  |  | ||||||
|  |  | ||||||
| def test_lock_checks_group(tmpdir): |  | ||||||
|     """Ensure lock checks work with a self-owned, non-self-group repo.""" |  | ||||||
|     uid = os.getuid() |  | ||||||
|     gid = next((g for g in group_ids() if g != uid), None) |  | ||||||
|     if not gid: |  | ||||||
|         pytest.skip("user has no group with gid != uid") |  | ||||||
|  |  | ||||||
|     # self-owned, another group |  | ||||||
|     tmpdir.chown(uid, gid) |  | ||||||
|  |  | ||||||
|     # safe |  | ||||||
|     path = str(tmpdir) |  | ||||||
|     tmpdir.chmod(0o744) |  | ||||||
|     spack.util.lock.check_lock_safety(path) |  | ||||||
|  |  | ||||||
|     # unsafe |  | ||||||
|     tmpdir.chmod(0o774) |  | ||||||
|     with pytest.raises(spack.error.SpackError): |  | ||||||
|         spack.util.lock.check_lock_safety(path) |  | ||||||
|  |  | ||||||
|     # unsafe |  | ||||||
|     tmpdir.chmod(0o777) |  | ||||||
|     with pytest.raises(spack.error.SpackError): |  | ||||||
|         spack.util.lock.check_lock_safety(path) |  | ||||||
|  |  | ||||||
|     # safe |  | ||||||
|     tmpdir.chmod(0o474) |  | ||||||
|     spack.util.lock.check_lock_safety(path) |  | ||||||
|  |  | ||||||
|     # safe |  | ||||||
|     tmpdir.chmod(0o477) |  | ||||||
|     spack.util.lock.check_lock_safety(path) |  | ||||||
|   | |||||||
							
								
								
									
										123
									
								
								lib/spack/spack/test/util/spack_lock_wrapper.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										123
									
								
								lib/spack/spack/test/util/spack_lock_wrapper.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,123 @@ | |||||||
|  | ############################################################################## | ||||||
|  | # Copyright (c) 2013-2018, Lawrence Livermore National Security, LLC. | ||||||
|  | # Produced at the Lawrence Livermore National Laboratory. | ||||||
|  | # | ||||||
|  | # This file is part of Spack. | ||||||
|  | # Created by Todd Gamblin, tgamblin@llnl.gov, All rights reserved. | ||||||
|  | # LLNL-CODE-647188 | ||||||
|  | # | ||||||
|  | # For details, see https://github.com/spack/spack | ||||||
|  | # Please also see the NOTICE and LICENSE files for our notice and the LGPL. | ||||||
|  | # | ||||||
|  | # This program is free software; you can redistribute it and/or modify | ||||||
|  | # it under the terms of the GNU Lesser General Public License (as | ||||||
|  | # published by the Free Software Foundation) version 2.1, February 1999. | ||||||
|  | # | ||||||
|  | # This program is distributed in the hope that it will be useful, but | ||||||
|  | # WITHOUT ANY WARRANTY; without even the IMPLIED WARRANTY OF | ||||||
|  | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the terms and | ||||||
|  | # conditions of the GNU Lesser General Public License for more details. | ||||||
|  | # | ||||||
|  | # You should have received a copy of the GNU Lesser General Public | ||||||
|  | # License along with this program; if not, write to the Free Software | ||||||
|  | # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||||||
|  | ############################################################################## | ||||||
|  | """Tests for Spack's wrapper module around llnl.util.lock.""" | ||||||
|  | import os | ||||||
|  |  | ||||||
|  | import pytest | ||||||
|  |  | ||||||
|  | from llnl.util.filesystem import group_ids | ||||||
|  |  | ||||||
|  | import spack.config | ||||||
|  | import spack.util.lock as lk | ||||||
|  |  | ||||||
|  |  | ||||||
|  | def test_disable_locking(tmpdir): | ||||||
|  |     """Ensure that locks do no real locking when disabled.""" | ||||||
|  |     lock_path = str(tmpdir.join('lockfile')) | ||||||
|  |  | ||||||
|  |     old_value = spack.config.get('config:locks') | ||||||
|  |  | ||||||
|  |     with spack.config.override('config:locks', False): | ||||||
|  |         lock = lk.Lock(lock_path) | ||||||
|  |  | ||||||
|  |         lock.acquire_read() | ||||||
|  |         assert not os.path.exists(lock_path) | ||||||
|  |  | ||||||
|  |         lock.acquire_write() | ||||||
|  |         assert not os.path.exists(lock_path) | ||||||
|  |  | ||||||
|  |         lock.release_write() | ||||||
|  |         assert not os.path.exists(lock_path) | ||||||
|  |  | ||||||
|  |         lock.release_read() | ||||||
|  |         assert not os.path.exists(lock_path) | ||||||
|  |  | ||||||
|  |     assert old_value == spack.config.get('config:locks') | ||||||
|  |  | ||||||
|  |  | ||||||
|  | def test_lock_checks_user(tmpdir): | ||||||
|  |     """Ensure lock checks work with a self-owned, self-group repo.""" | ||||||
|  |     uid = os.getuid() | ||||||
|  |     if uid not in group_ids(): | ||||||
|  |         pytest.skip("user has no group with gid == uid") | ||||||
|  |  | ||||||
|  |     # self-owned, own group | ||||||
|  |     tmpdir.chown(uid, uid) | ||||||
|  |  | ||||||
|  |     # safe | ||||||
|  |     path = str(tmpdir) | ||||||
|  |     tmpdir.chmod(0o744) | ||||||
|  |     lk.check_lock_safety(path) | ||||||
|  |  | ||||||
|  |     # safe | ||||||
|  |     tmpdir.chmod(0o774) | ||||||
|  |     lk.check_lock_safety(path) | ||||||
|  |  | ||||||
|  |     # unsafe | ||||||
|  |     tmpdir.chmod(0o777) | ||||||
|  |     with pytest.raises(spack.error.SpackError): | ||||||
|  |         lk.check_lock_safety(path) | ||||||
|  |  | ||||||
|  |     # safe | ||||||
|  |     tmpdir.chmod(0o474) | ||||||
|  |     lk.check_lock_safety(path) | ||||||
|  |  | ||||||
|  |     # safe | ||||||
|  |     tmpdir.chmod(0o477) | ||||||
|  |     lk.check_lock_safety(path) | ||||||
|  |  | ||||||
|  |  | ||||||
|  | def test_lock_checks_group(tmpdir): | ||||||
|  |     """Ensure lock checks work with a self-owned, non-self-group repo.""" | ||||||
|  |     uid = os.getuid() | ||||||
|  |     gid = next((g for g in group_ids() if g != uid), None) | ||||||
|  |     if not gid: | ||||||
|  |         pytest.skip("user has no group with gid != uid") | ||||||
|  |  | ||||||
|  |     # self-owned, another group | ||||||
|  |     tmpdir.chown(uid, gid) | ||||||
|  |  | ||||||
|  |     # safe | ||||||
|  |     path = str(tmpdir) | ||||||
|  |     tmpdir.chmod(0o744) | ||||||
|  |     lk.check_lock_safety(path) | ||||||
|  |  | ||||||
|  |     # unsafe | ||||||
|  |     tmpdir.chmod(0o774) | ||||||
|  |     with pytest.raises(spack.error.SpackError): | ||||||
|  |         lk.check_lock_safety(path) | ||||||
|  |  | ||||||
|  |     # unsafe | ||||||
|  |     tmpdir.chmod(0o777) | ||||||
|  |     with pytest.raises(spack.error.SpackError): | ||||||
|  |         lk.check_lock_safety(path) | ||||||
|  |  | ||||||
|  |     # safe | ||||||
|  |     tmpdir.chmod(0o474) | ||||||
|  |     lk.check_lock_safety(path) | ||||||
|  |  | ||||||
|  |     # safe | ||||||
|  |     tmpdir.chmod(0o477) | ||||||
|  |     lk.check_lock_safety(path) | ||||||
		Reference in New Issue
	
	Block a user
	 Todd Gamblin
					Todd Gamblin