summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/spack/spack/test/cmd/buildcache.py1
-rw-r--r--lib/spack/spack/test/cmd/debug.py3
-rw-r--r--lib/spack/spack/test/cmd/module.py6
-rw-r--r--lib/spack/spack/test/conftest.py63
-rw-r--r--lib/spack/spack/test/database.py77
-rw-r--r--lib/spack/spack/test/spec_syntax.py6
6 files changed, 95 insertions, 61 deletions
diff --git a/lib/spack/spack/test/cmd/buildcache.py b/lib/spack/spack/test/cmd/buildcache.py
index 329f3501d5..2c4f351d86 100644
--- a/lib/spack/spack/test/cmd/buildcache.py
+++ b/lib/spack/spack/test/cmd/buildcache.py
@@ -17,5 +17,6 @@ buildcache = spack.main.SpackCommand('buildcache')
platform.system().lower() != 'linux',
reason='implementation for MacOS still missing'
)
+@pytest.mark.db
def test_buildcache_preview_just_runs(database):
buildcache('preview', 'mpileaks')
diff --git a/lib/spack/spack/test/cmd/debug.py b/lib/spack/spack/test/cmd/debug.py
index 20bf2bec2e..aba46c2398 100644
--- a/lib/spack/spack/test/cmd/debug.py
+++ b/lib/spack/spack/test/cmd/debug.py
@@ -3,6 +3,8 @@
#
# SPDX-License-Identifier: (Apache-2.0 OR MIT)
+import pytest
+
import os
import os.path
@@ -12,6 +14,7 @@ from spack.util.executable import which
debug = SpackCommand('debug')
+@pytest.mark.db
def test_create_db_tarball(tmpdir, database):
with tmpdir.as_cwd():
debug('create-db-tarball')
diff --git a/lib/spack/spack/test/cmd/module.py b/lib/spack/spack/test/cmd/module.py
index c88f680b0e..6222401d66 100644
--- a/lib/spack/spack/test/cmd/module.py
+++ b/lib/spack/spack/test/cmd/module.py
@@ -19,6 +19,12 @@ def _module_files(module_type, *specs):
return [writer_cls(spec).layout.filename for spec in specs]
+@pytest.fixture(scope='module', autouse=True)
+def ensure_module_files_are_there(database):
+ module('dotkit', 'refresh', '-y')
+ module('tcl', 'refresh', '-y')
+
+
@pytest.fixture(
params=[
['rm', 'doesnotexist'], # Try to remove a non existing module
diff --git a/lib/spack/spack/test/conftest.py b/lib/spack/spack/test/conftest.py
index 146c5f7d5b..53493eda91 100644
--- a/lib/spack/spack/test/conftest.py
+++ b/lib/spack/spack/test/conftest.py
@@ -406,45 +406,58 @@ def _populate(mock_db):
_install('externaltest')
+@pytest.fixture(scope='session')
+def _store_dir_and_cache(tmpdir_factory):
+ """Returns the directory where to build the mock database and
+ where to cache it.
+ """
+ store = tmpdir_factory.mktemp('mock_store')
+ cache = tmpdir_factory.mktemp('mock_store_cache')
+ return store, cache
+
+
@pytest.fixture(scope='module')
-def database(tmpdir_factory, mock_packages, config):
- """Creates a mock database with some packages installed note that
- the ref count for dyninst here will be 3, as it's recycled
+def database(tmpdir_factory, mock_packages, config, _store_dir_and_cache):
+ """Creates a read-only mock database with some packages installed note
+ that the ref count for dyninst here will be 3, as it's recycled
across each install.
"""
- # save the real store
real_store = spack.store.store
+ store_path, store_cache = _store_dir_and_cache
- # Make a fake install directory
- install_path = tmpdir_factory.mktemp('install_for_database')
+ mock_store = spack.store.Store(str(store_path))
+ spack.store.store = mock_store
- # Make fake store (database and install layout)
- tmp_store = spack.store.Store(str(install_path))
- spack.store.store = tmp_store
+ # If the cache does not exist populate the store and create it
+ if not os.path.exists(str(store_cache.join('.spack-db'))):
+ _populate(mock_store.db)
+ store_path.copy(store_cache, mode=True, stat=True)
- _populate(tmp_store.db)
+ # Make the database read-only to ensure we can't modify entries
+ store_path.join('.spack-db').chmod(mode=0o555, rec=1)
- yield tmp_store.db
+ yield mock_store.db
- with tmp_store.db.write_transaction():
- for spec in tmp_store.db.query():
- if spec.package.installed:
- PackageBase.uninstall_by_spec(spec, force=True)
- else:
- tmp_store.db.remove(spec)
-
- install_path.remove(rec=1)
+ store_path.join('.spack-db').chmod(mode=0o755, rec=1)
spack.store.store = real_store
@pytest.fixture(scope='function')
-def mutable_database(database):
- """For tests that need to modify the database instance."""
+def mutable_database(database, _store_dir_and_cache):
+ """Writeable version of the fixture, restored to its initial state
+ after each test.
+ """
+ # Make the database writeable, as we are going to modify it
+ store_path, store_cache = _store_dir_and_cache
+ store_path.join('.spack-db').chmod(mode=0o755, rec=1)
+
yield database
- with database.write_transaction():
- for spec in spack.store.db.query():
- PackageBase.uninstall_by_spec(spec, force=True)
- _populate(database)
+
+ # Restore the initial state by copying the content of the cache back into
+ # the store and making the database read-only
+ store_path.remove(rec=1)
+ store_cache.copy(store_path, mode=True, stat=True)
+ store_path.join('.spack-db').chmod(mode=0o555, rec=1)
@pytest.fixture(scope='function')
diff --git a/lib/spack/spack/test/database.py b/lib/spack/spack/test/database.py
index fc2549b574..6938b5d0f0 100644
--- a/lib/spack/spack/test/database.py
+++ b/lib/spack/spack/test/database.py
@@ -19,6 +19,7 @@ from llnl.util.tty.colify import colify
import spack.repo
import spack.store
import spack.database
+import spack.package
import spack.spec
from spack.test.conftest import MockPackage, MockPackageMultiRepo
from spack.util.executable import Executable
@@ -411,7 +412,7 @@ def test_010_all_install_sanity(database):
) == 1
-def test_015_write_and_read(database):
+def test_015_write_and_read(mutable_database):
# write and read DB
with spack.store.db.write_transaction():
specs = spack.store.db.query()
@@ -430,10 +431,10 @@ def test_020_db_sanity(database):
_check_db_sanity(database)
-def test_025_reindex(database):
+def test_025_reindex(mutable_database):
"""Make sure reindex works and ref counts are valid."""
spack.store.store.reindex()
- _check_db_sanity(database)
+ _check_db_sanity(mutable_database)
def test_030_db_sanity_from_another_process(mutable_database):
@@ -492,64 +493,64 @@ def test_050_basic_query(database):
assert len(database.query(end_date=datetime.datetime.max)) == 16
-def test_060_remove_and_add_root_package(database):
- _check_remove_and_add_package(database, 'mpileaks ^mpich')
+def test_060_remove_and_add_root_package(mutable_database):
+ _check_remove_and_add_package(mutable_database, 'mpileaks ^mpich')
-def test_070_remove_and_add_dependency_package(database):
- _check_remove_and_add_package(database, 'dyninst')
+def test_070_remove_and_add_dependency_package(mutable_database):
+ _check_remove_and_add_package(mutable_database, 'dyninst')
-def test_080_root_ref_counts(database):
- rec = database.get_record('mpileaks ^mpich')
+def test_080_root_ref_counts(mutable_database):
+ rec = mutable_database.get_record('mpileaks ^mpich')
# Remove a top-level spec from the DB
- database.remove('mpileaks ^mpich')
+ mutable_database.remove('mpileaks ^mpich')
# record no longer in DB
- assert database.query('mpileaks ^mpich', installed=any) == []
+ assert mutable_database.query('mpileaks ^mpich', installed=any) == []
# record's deps have updated ref_counts
- assert database.get_record('callpath ^mpich').ref_count == 0
- assert database.get_record('mpich').ref_count == 1
+ assert mutable_database.get_record('callpath ^mpich').ref_count == 0
+ assert mutable_database.get_record('mpich').ref_count == 1
# Put the spec back
- database.add(rec.spec, spack.store.layout)
+ mutable_database.add(rec.spec, spack.store.layout)
# record is present again
- assert len(database.query('mpileaks ^mpich', installed=any)) == 1
+ assert len(mutable_database.query('mpileaks ^mpich', installed=any)) == 1
# dependencies have ref counts updated
- assert database.get_record('callpath ^mpich').ref_count == 1
- assert database.get_record('mpich').ref_count == 2
+ assert mutable_database.get_record('callpath ^mpich').ref_count == 1
+ assert mutable_database.get_record('mpich').ref_count == 2
-def test_090_non_root_ref_counts(database):
- database.get_record('mpileaks ^mpich')
- database.get_record('callpath ^mpich')
+def test_090_non_root_ref_counts(mutable_database):
+ mutable_database.get_record('mpileaks ^mpich')
+ mutable_database.get_record('callpath ^mpich')
# "force remove" a non-root spec from the DB
- database.remove('callpath ^mpich')
+ mutable_database.remove('callpath ^mpich')
# record still in DB but marked uninstalled
- assert database.query('callpath ^mpich', installed=True) == []
- assert len(database.query('callpath ^mpich', installed=any)) == 1
+ assert mutable_database.query('callpath ^mpich', installed=True) == []
+ assert len(mutable_database.query('callpath ^mpich', installed=any)) == 1
# record and its deps have same ref_counts
- assert database.get_record(
+ assert mutable_database.get_record(
'callpath ^mpich', installed=any
).ref_count == 1
- assert database.get_record('mpich').ref_count == 2
+ assert mutable_database.get_record('mpich').ref_count == 2
# remove only dependent of uninstalled callpath record
- database.remove('mpileaks ^mpich')
+ mutable_database.remove('mpileaks ^mpich')
# record and parent are completely gone.
- assert database.query('mpileaks ^mpich', installed=any) == []
- assert database.query('callpath ^mpich', installed=any) == []
+ assert mutable_database.query('mpileaks ^mpich', installed=any) == []
+ assert mutable_database.query('callpath ^mpich', installed=any) == []
# mpich ref count updated properly.
- mpich_rec = database.get_record('mpich')
+ mpich_rec = mutable_database.get_record('mpich')
assert mpich_rec.ref_count == 0
@@ -596,18 +597,18 @@ def test_115_reindex_with_packages_not_in_repo(mutable_database):
_check_db_sanity(mutable_database)
-def test_external_entries_in_db(database):
- rec = database.get_record('mpileaks ^zmpi')
+def test_external_entries_in_db(mutable_database):
+ rec = mutable_database.get_record('mpileaks ^zmpi')
assert rec.spec.external_path is None
assert rec.spec.external_module is None
- rec = database.get_record('externaltool')
+ rec = mutable_database.get_record('externaltool')
assert rec.spec.external_path == '/path/to/external_tool'
assert rec.spec.external_module is None
assert rec.explicit is False
rec.spec.package.do_install(fake=True, explicit=True)
- rec = database.get_record('externaltool')
+ rec = mutable_database.get_record('externaltool')
assert rec.spec.external_path == '/path/to/external_tool'
assert rec.spec.external_module is None
assert rec.explicit is True
@@ -646,3 +647,13 @@ def test_old_external_entries_prefix(mutable_database):
assert record.path is None
assert record.spec._prefix is None
assert record.spec.prefix == record.spec.external_path
+
+
+def test_uninstall_by_spec(mutable_database):
+ with mutable_database.write_transaction():
+ for spec in mutable_database.query():
+ if spec.package.installed:
+ spack.package.PackageBase.uninstall_by_spec(spec, force=True)
+ else:
+ mutable_database.remove(spec)
+ assert len(mutable_database.query()) == 0
diff --git a/lib/spack/spack/test/spec_syntax.py b/lib/spack/spack/test/spec_syntax.py
index 0af2ffdbd1..9437cb31fa 100644
--- a/lib/spack/spack/test/spec_syntax.py
+++ b/lib/spack/spack/test/spec_syntax.py
@@ -310,15 +310,15 @@ class TestSpecSyntax(object):
assert len(specs) == 2
@pytest.mark.db
- def test_ambiguous_hash(self, database):
+ def test_ambiguous_hash(self, mutable_database):
x1 = Spec('a')
x1._hash = 'xy'
x1._concrete = True
x2 = Spec('a')
x2._hash = 'xx'
x2._concrete = True
- database.add(x1, spack.store.layout)
- database.add(x2, spack.store.layout)
+ mutable_database.add(x1, spack.store.layout)
+ mutable_database.add(x2, spack.store.layout)
# ambiguity in first hash character
self._check_raises(AmbiguousHashError, ['/x'])