summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTodd Gamblin <tgamblin@llnl.gov>2020-04-23 18:21:49 -0700
committerGitHub <noreply@github.com>2020-04-23 18:21:49 -0700
commitc6ada206af08f66817fe1c2aeeee8f45f92a192e (patch)
tree1ca858e8d821f8f436a1f6b5f811d958b2b01f72
parent433a0b243ffa97add96bc0f51477c4bda3449c12 (diff)
downloadspack-c6ada206af08f66817fe1c2aeeee8f45f92a192e.tar.gz
spack-c6ada206af08f66817fe1c2aeeee8f45f92a192e.tar.bz2
spack-c6ada206af08f66817fe1c2aeeee8f45f92a192e.tar.xz
spack-c6ada206af08f66817fe1c2aeeee8f45f92a192e.zip
tests: each mock package now has its own class (#16157)
Packages in Spack are classes, and we need to be able to execute class methods on mock packages. The previous design used instances of a single MockPackage class; this version gives each package its own class that can spider depenencies. This allows us to implement class methods like `possible_dependencies()` on mock packages. This design change moves mock package creation into the `MockPackageMultiRepo`, and mock packages now *must* be created from a repo. This is required for us to mock `possible_dependencies()`, which needs to be able to get dependency packages from the package repo. Changes include: * `MockPackage` is now `MockPackageBase` * `MockPackageBase` instances must now be created with `MockPackageMultiRepo.add_package()` * add `possible_dependencies()` method to `MockPackageBase` * refactor tests to use new code structure * move package mocking infrastructure into `spack.util.mock_package`, as it's becoming a more sophisticated class and it gets lots in `conftest.py`
-rw-r--r--lib/spack/spack/test/cmd/ci.py19
-rw-r--r--lib/spack/spack/test/cmd/env.py30
-rw-r--r--lib/spack/spack/test/concretize.py10
-rw-r--r--lib/spack/spack/test/conftest.py73
-rw-r--r--lib/spack/spack/test/database.py37
-rw-r--r--lib/spack/spack/test/spec_dag.py40
-rw-r--r--lib/spack/spack/test/spec_yaml.py19
-rw-r--r--lib/spack/spack/test/util/mock_package.py43
-rw-r--r--lib/spack/spack/util/mock_package.py161
9 files changed, 279 insertions, 153 deletions
diff --git a/lib/spack/spack/test/cmd/ci.py b/lib/spack/spack/test/cmd/ci.py
index 89ed471868..36236b0cc1 100644
--- a/lib/spack/spack/test/cmd/ci.py
+++ b/lib/spack/spack/test/cmd/ci.py
@@ -18,7 +18,7 @@ from spack.main import SpackCommand
import spack.paths as spack_paths
import spack.repo as repo
from spack.spec import Spec
-from spack.test.conftest import MockPackage, MockPackageMultiRepo
+from spack.util.mock_package import MockPackageMultiRepo
import spack.util.executable as exe
import spack.util.spack_yaml as syaml
import spack.util.gpg
@@ -101,15 +101,14 @@ and then 'd', 'b', and 'a' to be put in the next three stages, respectively.
"""
default = ('build', 'link')
- g = MockPackage('g', [], [])
- f = MockPackage('f', [], [])
- e = MockPackage('e', [], [])
- d = MockPackage('d', [f, g], [default, default])
- c = MockPackage('c', [], [])
- b = MockPackage('b', [d, e], [default, default])
- a = MockPackage('a', [b, c], [default, default])
-
- mock_repo = MockPackageMultiRepo([a, b, c, d, e, f, g])
+ mock_repo = MockPackageMultiRepo()
+ g = mock_repo.add_package('g', [], [])
+ f = mock_repo.add_package('f', [], [])
+ e = mock_repo.add_package('e', [], [])
+ d = mock_repo.add_package('d', [f, g], [default, default])
+ c = mock_repo.add_package('c', [], [])
+ b = mock_repo.add_package('b', [d, e], [default, default])
+ mock_repo.add_package('a', [b, c], [default, default])
with repo.swap(mock_repo):
spec_a = Spec('a')
diff --git a/lib/spack/spack/test/cmd/env.py b/lib/spack/spack/test/cmd/env.py
index 4f3abb4438..f35b0a4bc1 100644
--- a/lib/spack/spack/test/cmd/env.py
+++ b/lib/spack/spack/test/cmd/env.py
@@ -20,7 +20,7 @@ from spack.main import SpackCommand
from spack.stage import stage_prefix
from spack.spec_list import SpecListError
-from spack.test.conftest import MockPackage, MockPackageMultiRepo
+from spack.util.mock_package import MockPackageMultiRepo
import spack.util.spack_json as sjson
@@ -733,10 +733,10 @@ def create_v1_lockfile_dict(roots, all_specs):
def test_read_old_lock_and_write_new(tmpdir):
build_only = ('build',)
- y = MockPackage('y', [], [])
- x = MockPackage('x', [y], [build_only])
+ mock_repo = MockPackageMultiRepo()
+ y = mock_repo.add_package('y', [], [])
+ mock_repo.add_package('x', [y], [build_only])
- mock_repo = MockPackageMultiRepo([x, y])
with spack.repo.swap(mock_repo):
x = Spec('x')
x.concretize()
@@ -765,9 +765,9 @@ def test_read_old_lock_creates_backup(tmpdir):
"""When reading a version-1 lockfile, make sure that a backup of that file
is created.
"""
- y = MockPackage('y', [], [])
+ mock_repo = MockPackageMultiRepo()
+ y = mock_repo.add_package('y', [], [])
- mock_repo = MockPackageMultiRepo([y])
with spack.repo.swap(mock_repo):
y = Spec('y')
y.concretize()
@@ -796,11 +796,10 @@ def test_indirect_build_dep():
default = ('build', 'link')
build_only = ('build',)
- z = MockPackage('z', [], [])
- y = MockPackage('y', [z], [build_only])
- x = MockPackage('x', [y], [default])
-
- mock_repo = MockPackageMultiRepo([x, y, z])
+ mock_repo = MockPackageMultiRepo()
+ z = mock_repo.add_package('z', [], [])
+ y = mock_repo.add_package('y', [z], [build_only])
+ mock_repo.add_package('x', [y], [default])
def noop(*args):
pass
@@ -838,11 +837,10 @@ def test_store_different_build_deps():
default = ('build', 'link')
build_only = ('build',)
- z = MockPackage('z', [], [])
- y = MockPackage('y', [z], [build_only])
- x = MockPackage('x', [y, z], [default, build_only])
-
- mock_repo = MockPackageMultiRepo([x, y, z])
+ mock_repo = MockPackageMultiRepo()
+ z = mock_repo.add_package('z', [], [])
+ y = mock_repo.add_package('y', [z], [build_only])
+ mock_repo.add_package('x', [y, z], [default, build_only])
def noop(*args):
pass
diff --git a/lib/spack/spack/test/concretize.py b/lib/spack/spack/test/concretize.py
index 9024c99cad..232dfaeb4b 100644
--- a/lib/spack/spack/test/concretize.py
+++ b/lib/spack/spack/test/concretize.py
@@ -15,7 +15,7 @@ from spack.error import SpecError
from spack.package_prefs import PackagePrefs
from spack.spec import Spec, CompilerSpec, ConflictsInSpecError
from spack.version import ver
-from spack.test.conftest import MockPackage, MockPackageMultiRepo
+from spack.util.mock_package import MockPackageMultiRepo
import spack.compilers
import spack.platforms.test
@@ -235,10 +235,10 @@ class TestConcretize(object):
"""
default_dep = ('link', 'build')
- bazpkg = MockPackage('bazpkg', [], [])
- barpkg = MockPackage('barpkg', [bazpkg], [default_dep])
- foopkg = MockPackage('foopkg', [barpkg], [default_dep])
- mock_repo = MockPackageMultiRepo([foopkg, barpkg, bazpkg])
+ mock_repo = MockPackageMultiRepo()
+ bazpkg = mock_repo.add_package('bazpkg', [], [])
+ barpkg = mock_repo.add_package('barpkg', [bazpkg], [default_dep])
+ mock_repo.add_package('foopkg', [barpkg], [default_dep])
with spack.repo.swap(mock_repo):
spec = Spec('foopkg %clang@3.3 os=CNL target=footar' +
diff --git a/lib/spack/spack/test/conftest.py b/lib/spack/spack/test/conftest.py
index 8912c0219b..736c5a5563 100644
--- a/lib/spack/spack/test/conftest.py
+++ b/lib/spack/spack/test/conftest.py
@@ -14,7 +14,6 @@ import shutil
import tempfile
import xml.etree.ElementTree
-import ordereddict_backport
import py
import pytest
import ruamel.yaml as yaml
@@ -38,11 +37,8 @@ import spack.util.executable
import spack.util.gpg
from spack.util.pattern import Bunch
-from spack.dependency import Dependency
from spack.fetch_strategy import FetchStrategyComposite, URLFetchStrategy
from spack.fetch_strategy import FetchError
-from spack.spec import Spec
-from spack.version import Version
@pytest.fixture
@@ -1005,75 +1001,6 @@ def installation_dir_with_headers(tmpdir_factory):
##########
-# Mock packages
-##########
-
-
-class MockPackage(object):
- def __init__(self, name, dependencies, dependency_types, conditions=None,
- versions=None):
- self.name = name
- self.spec = None
- self.dependencies = ordereddict_backport.OrderedDict()
- self._installed_upstream = False
-
- assert len(dependencies) == len(dependency_types)
- for dep, dtype in zip(dependencies, dependency_types):
- d = Dependency(self, Spec(dep.name), type=dtype)
- if not conditions or dep.name not in conditions:
- self.dependencies[dep.name] = {Spec(name): d}
- else:
- dep_conditions = conditions[dep.name]
- dep_conditions = dict(
- (Spec(x), Dependency(self, Spec(y), type=dtype))
- for x, y in dep_conditions.items())
- self.dependencies[dep.name] = dep_conditions
-
- if versions:
- self.versions = versions
- else:
- versions = list(Version(x) for x in [1, 2, 3])
- self.versions = dict((x, {'preferred': False}) for x in versions)
-
- self.variants = {}
- self.provided = {}
- self.conflicts = {}
- self.patches = {}
-
- def provides(self, vname):
- return vname in self.provided
-
- @property
- def virtuals_provided(self):
- return [v.name for v, c in self.provided]
-
-
-class MockPackageMultiRepo(object):
- def __init__(self, packages):
- self.spec_to_pkg = dict((x.name, x) for x in packages)
- self.spec_to_pkg.update(
- dict(('mockrepo.' + x.name, x) for x in packages))
-
- def get(self, spec):
- if not isinstance(spec, spack.spec.Spec):
- spec = Spec(spec)
- return self.spec_to_pkg[spec.name]
-
- def get_pkg_class(self, name):
- return self.spec_to_pkg[name]
-
- def exists(self, name):
- return name in self.spec_to_pkg
-
- def is_virtual(self, name):
- return False
-
- def repo_for_pkg(self, name):
- import collections
- Repo = collections.namedtuple('Repo', ['namespace'])
- return Repo('mockrepo')
-
-##########
# Specs of various kind
##########
diff --git a/lib/spack/spack/test/database.py b/lib/spack/spack/test/database.py
index 28311c7501..70f9bffe59 100644
--- a/lib/spack/spack/test/database.py
+++ b/lib/spack/spack/test/database.py
@@ -28,7 +28,7 @@ import spack.store
import spack.database
import spack.package
import spack.spec
-from spack.test.conftest import MockPackage, MockPackageMultiRepo
+from spack.util.mock_package import MockPackageMultiRepo
from spack.util.executable import Executable
@@ -73,11 +73,11 @@ def test_installed_upstream(upstream_and_downstream_db):
downstream_db, downstream_layout = (upstream_and_downstream_db)
default = ('build', 'link')
- x = MockPackage('x', [], [])
- z = MockPackage('z', [], [])
- y = MockPackage('y', [z], [default])
- w = MockPackage('w', [x, y], [default, default])
- mock_repo = MockPackageMultiRepo([w, x, y, z])
+ mock_repo = MockPackageMultiRepo()
+ x = mock_repo.add_package('x', [], [])
+ z = mock_repo.add_package('z', [], [])
+ y = mock_repo.add_package('y', [z], [default])
+ mock_repo.add_package('w', [x, y], [default, default])
with spack.repo.swap(mock_repo):
spec = spack.spec.Spec('w')
@@ -116,9 +116,9 @@ def test_removed_upstream_dep(upstream_and_downstream_db):
downstream_db, downstream_layout = (upstream_and_downstream_db)
default = ('build', 'link')
- z = MockPackage('z', [], [])
- y = MockPackage('y', [z], [default])
- mock_repo = MockPackageMultiRepo([y, z])
+ mock_repo = MockPackageMultiRepo()
+ z = mock_repo.add_package('z', [], [])
+ mock_repo.add_package('y', [z], [default])
with spack.repo.swap(mock_repo):
spec = spack.spec.Spec('y')
@@ -150,8 +150,8 @@ def test_add_to_upstream_after_downstream(upstream_and_downstream_db):
upstream_write_db, upstream_db, upstream_layout,\
downstream_db, downstream_layout = (upstream_and_downstream_db)
- x = MockPackage('x', [], [])
- mock_repo = MockPackageMultiRepo([x])
+ mock_repo = MockPackageMultiRepo()
+ mock_repo.add_package('x', [], [])
with spack.repo.swap(mock_repo):
spec = spack.spec.Spec('x')
@@ -183,8 +183,8 @@ def test_cannot_write_upstream(tmpdir_factory, test_store, gen_mock_layout):
roots = [str(tmpdir_factory.mktemp(x)) for x in ['a', 'b']]
layouts = [gen_mock_layout(x) for x in ['/ra/', '/rb/']]
- x = MockPackage('x', [], [])
- mock_repo = MockPackageMultiRepo([x])
+ mock_repo = MockPackageMultiRepo()
+ mock_repo.add_package('x', [], [])
# Instantiate the database that will be used as the upstream DB and make
# sure it has an index file
@@ -209,11 +209,10 @@ def test_recursive_upstream_dbs(tmpdir_factory, test_store, gen_mock_layout):
layouts = [gen_mock_layout(x) for x in ['/ra/', '/rb/', '/rc/']]
default = ('build', 'link')
- z = MockPackage('z', [], [])
- y = MockPackage('y', [z], [default])
- x = MockPackage('x', [y], [default])
-
- mock_repo = MockPackageMultiRepo([x, y, z])
+ mock_repo = MockPackageMultiRepo()
+ z = mock_repo.add_package('z', [], [])
+ y = mock_repo.add_package('y', [z], [default])
+ mock_repo.add_package('x', [y], [default])
with spack.repo.swap(mock_repo):
spec = spack.spec.Spec('x')
@@ -675,7 +674,7 @@ def test_115_reindex_with_packages_not_in_repo(mutable_database):
# Dont add any package definitions to this repository, the idea is that
# packages should not have to be defined in the repository once they
# are installed
- with spack.repo.swap(MockPackageMultiRepo([])):
+ with spack.repo.swap(MockPackageMultiRepo()):
spack.store.store.reindex()
_check_db_sanity(mutable_database)
diff --git a/lib/spack/spack/test/spec_dag.py b/lib/spack/spack/test/spec_dag.py
index e031f02c25..0b638ada04 100644
--- a/lib/spack/spack/test/spec_dag.py
+++ b/lib/spack/spack/test/spec_dag.py
@@ -12,7 +12,7 @@ import spack.package
from spack.spec import Spec
from spack.dependency import all_deptypes, Dependency, canonical_deptype
-from spack.test.conftest import MockPackage, MockPackageMultiRepo
+from spack.util.mock_package import MockPackageMultiRepo
def check_links(spec_to_check):
@@ -69,12 +69,12 @@ w->y deptypes are (link, build), w->x and y->z deptypes are (test)
default = ('build', 'link')
test_only = ('test',)
- x = MockPackage('x', [], [])
- z = MockPackage('z', [], [])
- y = MockPackage('y', [z], [test_only])
- w = MockPackage('w', [x, y], [test_only, default])
+ mock_repo = MockPackageMultiRepo()
+ x = mock_repo.add_package('x', [], [])
+ z = mock_repo.add_package('z', [], [])
+ y = mock_repo.add_package('y', [z], [test_only])
+ w = mock_repo.add_package('w', [x, y], [test_only, default])
- mock_repo = MockPackageMultiRepo([w, x, y, z])
with spack.repo.swap(mock_repo):
spec = Spec('w')
spec.concretize(tests=(w.name,))
@@ -93,8 +93,9 @@ def test_installed_deps():
default = ('build', 'link')
build_only = ('build',)
- e = MockPackage('e', [], [])
- d = MockPackage('d', [], [])
+ mock_repo = MockPackageMultiRepo()
+ e = mock_repo.add_package('e', [], [])
+ d = mock_repo.add_package('d', [], [])
c_conditions = {
d.name: {
'c': 'd@2'
@@ -103,11 +104,10 @@ def test_installed_deps():
'c': 'e@2'
}
}
- c = MockPackage('c', [d, e], [build_only, default],
- conditions=c_conditions)
- b = MockPackage('b', [d, e], [default, default])
- a = MockPackage('a', [b, c], [default, default])
- mock_repo = MockPackageMultiRepo([a, b, c, d, e])
+ c = mock_repo.add_package('c', [d, e], [build_only, default],
+ conditions=c_conditions)
+ b = mock_repo.add_package('b', [d, e], [default, default])
+ mock_repo.add_package('a', [b, c], [default, default])
with spack.repo.swap(mock_repo):
c_spec = Spec('c')
@@ -133,10 +133,10 @@ def test_specify_preinstalled_dep():
"""
default = ('build', 'link')
- c = MockPackage('c', [], [])
- b = MockPackage('b', [c], [default])
- a = MockPackage('a', [b], [default])
- mock_repo = MockPackageMultiRepo([a, b, c])
+ mock_repo = MockPackageMultiRepo()
+ c = mock_repo.add_package('c', [], [])
+ b = mock_repo.add_package('b', [c], [default])
+ mock_repo.add_package('a', [b], [default])
with spack.repo.swap(mock_repo):
b_spec = Spec('b')
@@ -161,15 +161,15 @@ def test_conditional_dep_with_user_constraints():
"""
default = ('build', 'link')
- y = MockPackage('y', [], [])
+ mock_repo = MockPackageMultiRepo()
+ y = mock_repo.add_package('y', [], [])
x_on_y_conditions = {
y.name: {
'x@2:': 'y'
}
}
- x = MockPackage('x', [y], [default], conditions=x_on_y_conditions)
+ mock_repo.add_package('x', [y], [default], conditions=x_on_y_conditions)
- mock_repo = MockPackageMultiRepo([x, y])
with spack.repo.swap(mock_repo):
spec = Spec('x ^y@2')
spec.concretize()
diff --git a/lib/spack/spack/test/spec_yaml.py b/lib/spack/spack/test/spec_yaml.py
index f9b41df19a..03129a7eb9 100644
--- a/lib/spack/spack/test/spec_yaml.py
+++ b/lib/spack/spack/test/spec_yaml.py
@@ -26,7 +26,7 @@ import spack.version
from spack import repo
from spack.spec import Spec, save_dependency_spec_yamls
from spack.util.spack_yaml import syaml_dict
-from spack.test.conftest import MockPackage, MockPackageMultiRepo
+from spack.util.mock_package import MockPackageMultiRepo
def check_yaml_round_trip(spec):
@@ -301,15 +301,14 @@ def test_save_dependency_spec_yamls_subset(tmpdir, config):
default = ('build', 'link')
- g = MockPackage('g', [], [])
- f = MockPackage('f', [], [])
- e = MockPackage('e', [], [])
- d = MockPackage('d', [f, g], [default, default])
- c = MockPackage('c', [], [])
- b = MockPackage('b', [d, e], [default, default])
- a = MockPackage('a', [b, c], [default, default])
-
- mock_repo = MockPackageMultiRepo([a, b, c, d, e, f, g])
+ mock_repo = MockPackageMultiRepo()
+ g = mock_repo.add_package('g', [], [])
+ f = mock_repo.add_package('f', [], [])
+ e = mock_repo.add_package('e', [], [])
+ d = mock_repo.add_package('d', [f, g], [default, default])
+ c = mock_repo.add_package('c', [], [])
+ b = mock_repo.add_package('b', [d, e], [default, default])
+ mock_repo.add_package('a', [b, c], [default, default])
with repo.swap(mock_repo):
spec_a = Spec('a')
diff --git a/lib/spack/spack/test/util/mock_package.py b/lib/spack/spack/test/util/mock_package.py
new file mode 100644
index 0000000000..376ac581bd
--- /dev/null
+++ b/lib/spack/spack/test/util/mock_package.py
@@ -0,0 +1,43 @@
+# Copyright 2013-2020 Lawrence Livermore National Security, LLC and other
+# Spack Project Developers. See the top-level COPYRIGHT file for details.
+#
+# SPDX-License-Identifier: (Apache-2.0 OR MIT)
+
+import spack.repo
+from spack.util.mock_package import MockPackageMultiRepo
+
+
+def test_mock_package_possible_dependencies():
+ mock_repo = MockPackageMultiRepo()
+ e = mock_repo.add_package('e')
+ d = mock_repo.add_package('d', [e])
+ c = mock_repo.add_package('c', [d])
+ b = mock_repo.add_package('b', [d])
+ a = mock_repo.add_package('a', [b, c])
+
+ with spack.repo.swap(mock_repo):
+ assert set(a.possible_dependencies()) == set(['a', 'b', 'c', 'd', 'e'])
+ assert set(b.possible_dependencies()) == set(['b', 'd', 'e'])
+ assert set(c.possible_dependencies()) == set(['c', 'd', 'e'])
+ assert set(d.possible_dependencies()) == set(['d', 'e'])
+ assert set(e.possible_dependencies()) == set(['e'])
+
+ assert set(
+ a.possible_dependencies(transitive=False)) == set(['a', 'b', 'c'])
+ assert set(
+ b.possible_dependencies(transitive=False)) == set(['b', 'd'])
+ assert set(
+ c.possible_dependencies(transitive=False)) == set(['c', 'd'])
+ assert set(
+ d.possible_dependencies(transitive=False)) == set(['d', 'e'])
+ assert set(
+ e.possible_dependencies(transitive=False)) == set(['e'])
+
+
+def test_mock_repo_is_virtual():
+ mock_repo = MockPackageMultiRepo()
+
+ # current implementation is always false
+ assert mock_repo.is_virtual("foo") is False
+ assert mock_repo.is_virtual("bar") is False
+ assert mock_repo.is_virtual("baz") is False
diff --git a/lib/spack/spack/util/mock_package.py b/lib/spack/spack/util/mock_package.py
new file mode 100644
index 0000000000..3d8ae30b10
--- /dev/null
+++ b/lib/spack/spack/util/mock_package.py
@@ -0,0 +1,161 @@
+# Copyright 2013-2020 Lawrence Livermore National Security, LLC and other
+# Spack Project Developers. See the top-level COPYRIGHT file for details.
+#
+# SPDX-License-Identifier: (Apache-2.0 OR MIT)
+
+"""Infrastructure used by tests for mocking packages and repos."""
+
+import ordereddict_backport
+
+import spack.util.naming
+from spack.dependency import Dependency
+from spack.spec import Spec
+from spack.version import Version
+
+__all__ = ["MockPackageMultiRepo"]
+
+
+class MockPackageBase(object):
+ """Internal base class for mocking ``spack.package.PackageBase``.
+
+ Use ``MockPackageMultiRepo.add_package()`` to create new instances.
+
+ """
+ def __init__(self, dependencies, dependency_types,
+ conditions=None, versions=None):
+ """Instantiate a new MockPackageBase.
+
+ This is not for general use; it needs to be constructed by a
+ ``MockPackageMultiRepo``, as we need to know about *all* packages
+ to find possible depenencies.
+
+ """
+ self.spec = None
+ self._installed_upstream = False
+
+ def provides(self, vname):
+ return vname in self.provided
+
+ @property
+ def virtuals_provided(self):
+ return [v.name for v, c in self.provided]
+
+ @classmethod
+ def possible_dependencies(
+ cls, transitive=True, deptype='all', visited=None, virtuals=None):
+ visited = {} if visited is None else visited
+
+ for name, conditions in cls.dependencies.items():
+ # check whether this dependency could be of the type asked for
+ types = [dep.type for cond, dep in conditions.items()]
+ types = set.union(*types)
+ if not any(d in types for d in deptype):
+ continue
+
+ visited.setdefault(cls.name, set())
+ for dep_name in cls.dependencies:
+ if dep_name in visited:
+ continue
+
+ visited.setdefault(dep_name, set())
+
+ if not transitive:
+ continue
+
+ cls._repo.get(dep_name).possible_dependencies(
+ transitive, deptype, visited, virtuals)
+
+ return visited
+
+
+class MockPackageMultiRepo(object):
+ """Mock package repository, mimicking ``spack.repo.Repo``."""
+
+ def __init__(self):
+ self.spec_to_pkg = {}
+
+ def get(self, spec):
+ if not isinstance(spec, spack.spec.Spec):
+ spec = Spec(spec)
+ return self.spec_to_pkg[spec.name]
+
+ def get_pkg_class(self, name):
+ return self.spec_to_pkg[name]
+
+ def exists(self, name):
+ return name in self.spec_to_pkg
+
+ def is_virtual(self, name):
+ return False
+
+ def repo_for_pkg(self, name):
+ import collections
+ Repo = collections.namedtuple('Repo', ['namespace'])
+ return Repo('mockrepo')
+
+ def add_package(self, name, dependencies=None, dependency_types=None,
+ conditions=None):
+ """Factory method for creating mock packages.
+
+ This creates a new subclass of ``MockPackageBase``, ensures that its
+ ``name`` and ``__name__`` properties are set up correctly, and
+ returns a new instance.
+
+ We use a factory function here because many functions and properties
+ of packages need to be class functions.
+
+ Args:
+ name (str): name of the new package
+ dependencies (list): list of mock packages to be dependencies
+ for this new package (optional; no deps if not provided)
+ dependency_type (list): list of deptypes for each dependency
+ (optional; will be default_deptype if not provided)
+ conditions (list): condition specs for each dependency (optional)
+
+ """
+ if not dependencies:
+ dependencies = []
+
+ if not dependency_types:
+ dependency_types = [
+ spack.dependency.default_deptype] * len(dependencies)
+
+ assert len(dependencies) == len(dependency_types)
+
+ # new class for the mock package
+ class MockPackage(MockPackageBase):
+ pass
+ MockPackage.__name__ = spack.util.naming.mod_to_class(name)
+ MockPackage.name = name
+ MockPackage._repo = self
+
+ # set up dependencies
+ MockPackage.dependencies = ordereddict_backport.OrderedDict()
+ for dep, dtype in zip(dependencies, dependency_types):
+ d = Dependency(MockPackage, Spec(dep.name), type=dtype)
+ if not conditions or dep.name not in conditions:
+ MockPackage.dependencies[dep.name] = {Spec(name): d}
+ else:
+ dep_conditions = conditions[dep.name]
+ dep_conditions = dict(
+ (Spec(x), Dependency(MockPackage, Spec(y), type=dtype))
+ for x, y in dep_conditions.items())
+ MockPackage.dependencies[dep.name] = dep_conditions
+
+ # each package has some fake versions
+ versions = list(Version(x) for x in [1, 2, 3])
+ MockPackage.versions = dict(
+ (x, {'preferred': False}) for x in versions
+ )
+
+ MockPackage.variants = {}
+ MockPackage.provided = {}
+ MockPackage.conflicts = {}
+ MockPackage.patches = {}
+
+ mock_package = MockPackage(
+ dependencies, dependency_types, conditions, versions)
+ self.spec_to_pkg[name] = mock_package
+ self.spec_to_pkg["mockrepo." + name] = mock_package
+
+ return mock_package