summaryrefslogtreecommitdiff
path: root/lib/spack/spack/test/cmd/install.py
diff options
context:
space:
mode:
Diffstat (limited to 'lib/spack/spack/test/cmd/install.py')
-rw-r--r--lib/spack/spack/test/cmd/install.py213
1 files changed, 213 insertions, 0 deletions
diff --git a/lib/spack/spack/test/cmd/install.py b/lib/spack/spack/test/cmd/install.py
new file mode 100644
index 0000000000..591bf02340
--- /dev/null
+++ b/lib/spack/spack/test/cmd/install.py
@@ -0,0 +1,213 @@
+##############################################################################
+# Copyright (c) 2013-2016, 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/llnl/spack
+# Please also see the LICENSE file 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
+##############################################################################
+import StringIO
+import argparse
+import codecs
+import collections
+import contextlib
+import unittest
+
+import llnl.util.filesystem
+import spack
+import spack.cmd
+import spack.cmd.install as install
+
+FILE_REGISTRY = collections.defaultdict(StringIO.StringIO)
+
+
+# Monkey-patch open to write module files to a StringIO instance
+@contextlib.contextmanager
+def mock_open(filename, mode, *args):
+ if not mode == 'wb':
+ message = 'test.test_install : unexpected opening mode for mock_open'
+ raise RuntimeError(message)
+
+ FILE_REGISTRY[filename] = StringIO.StringIO()
+
+ try:
+ yield FILE_REGISTRY[filename]
+ finally:
+ handle = FILE_REGISTRY[filename]
+ FILE_REGISTRY[filename] = handle.getvalue()
+ handle.close()
+
+
+class MockSpec(object):
+
+ def __init__(self, name, version, hashStr=None):
+ self._dependencies = {}
+ self.name = name
+ self.version = version
+ self.hash = hashStr if hashStr else hash((name, version))
+
+ def _deptype_norm(self, deptype):
+ if deptype is None:
+ return spack.alldeps
+ # Force deptype to be a tuple so that we can do set intersections.
+ if isinstance(deptype, str):
+ return (deptype,)
+ return deptype
+
+ def _find_deps(self, where, deptype):
+ deptype = self._deptype_norm(deptype)
+
+ return [dep.spec
+ for dep in where.values()
+ if deptype and any(d in deptype for d in dep.deptypes)]
+
+ def dependencies(self, deptype=None):
+ return self._find_deps(self._dependencies, deptype)
+
+ def dependents(self, deptype=None):
+ return self._find_deps(self._dependents, deptype)
+
+ def traverse(self, order=None):
+ for _, spec in self._dependencies.items():
+ yield spec.spec
+ yield self
+
+ def dag_hash(self):
+ return self.hash
+
+ @property
+ def short_spec(self):
+ return '-'.join([self.name, str(self.version), str(self.hash)])
+
+
+class MockPackage(object):
+
+ def __init__(self, spec, buildLogPath):
+ self.name = spec.name
+ self.spec = spec
+ self.installed = False
+ self.build_log_path = buildLogPath
+
+ def do_install(self, *args, **kwargs):
+ for x in self.spec.dependencies():
+ x.package.do_install(*args, **kwargs)
+ self.installed = True
+
+
+class MockPackageDb(object):
+
+ def __init__(self, init=None):
+ self.specToPkg = {}
+ if init:
+ self.specToPkg.update(init)
+
+ def get(self, spec):
+ return self.specToPkg[spec]
+
+
+def mock_fetch_log(path):
+ return []
+
+specX = MockSpec('X', '1.2.0')
+specY = MockSpec('Y', '2.3.8')
+specX._dependencies['Y'] = spack.DependencySpec(specY, spack.alldeps)
+pkgX = MockPackage(specX, 'logX')
+pkgY = MockPackage(specY, 'logY')
+specX.package = pkgX
+specY.package = pkgY
+
+
+# TODO: add test(s) where Y fails to install
+class InstallTestJunitLog(unittest.TestCase):
+ """Tests test-install where X->Y"""
+
+ def setUp(self):
+ super(InstallTestJunitLog, self).setUp()
+ install.PackageBase = MockPackage
+ # Monkey patch parse specs
+
+ def monkey_parse_specs(x, concretize):
+ if x == ['X']:
+ return [specX]
+ elif x == ['Y']:
+ return [specY]
+ return []
+
+ self.parse_specs = spack.cmd.parse_specs
+ spack.cmd.parse_specs = monkey_parse_specs
+
+ # Monkey patch os.mkdirp
+ self.mkdirp = llnl.util.filesystem.mkdirp
+ llnl.util.filesystem.mkdirp = lambda x: True
+
+ # Monkey patch open
+ self.codecs_open = codecs.open
+ codecs.open = mock_open
+
+ # Clean FILE_REGISTRY
+ FILE_REGISTRY.clear()
+
+ pkgX.installed = False
+ pkgY.installed = False
+
+ # Monkey patch pkgDb
+ self.saved_db = spack.repo
+ pkgDb = MockPackageDb({specX: pkgX, specY: pkgY})
+ spack.repo = pkgDb
+
+ def tearDown(self):
+ # Remove the monkey patched test_install.open
+ codecs.open = self.codecs_open
+
+ # Remove the monkey patched os.mkdir
+ llnl.util.filesystem.mkdirp = self.mkdirp
+ del self.mkdirp
+
+ # Remove the monkey patched parse_specs
+ spack.cmd.parse_specs = self.parse_specs
+ del self.parse_specs
+ super(InstallTestJunitLog, self).tearDown()
+
+ spack.repo = self.saved_db
+
+ def test_installing_both(self):
+ parser = argparse.ArgumentParser()
+ install.setup_parser(parser)
+ args = parser.parse_args(['--log-format=junit', 'X'])
+ install.install(parser, args)
+ self.assertEqual(len(FILE_REGISTRY), 1)
+ for _, content in FILE_REGISTRY.items():
+ self.assertTrue('tests="2"' in content)
+ self.assertTrue('failures="0"' in content)
+ self.assertTrue('errors="0"' in content)
+
+ def test_dependency_already_installed(self):
+ pkgX.installed = True
+ pkgY.installed = True
+ parser = argparse.ArgumentParser()
+ install.setup_parser(parser)
+ args = parser.parse_args(['--log-format=junit', 'X'])
+ install.install(parser, args)
+ self.assertEqual(len(FILE_REGISTRY), 1)
+ for _, content in FILE_REGISTRY.items():
+ self.assertTrue('tests="2"' in content)
+ self.assertTrue('failures="0"' in content)
+ self.assertTrue('errors="0"' in content)
+ self.assertEqual(
+ sum('skipped' in line for line in content.split('\n')), 2)