From 48d5281e3a9142ded1e67983a22dce3f5777e1b4 Mon Sep 17 00:00:00 2001 From: Todd Gamblin Date: Sun, 10 Aug 2014 18:00:20 -0700 Subject: [PATCH] Test cases pass; Spack supports Python 2.6! --- bin/spack | 4 +- lib/spack/spack/stage.py | 3 +- lib/spack/spack/test/__init__.py | 4 +- lib/spack/spack/test/concretize.py | 24 ++-- lib/spack/spack/test/mock_packages_test.py | 3 +- lib/spack/spack/test/spec_dag.py | 46 ++++---- lib/spack/spack/test/stage.py | 122 +++++++++++---------- 7 files changed, 104 insertions(+), 102 deletions(-) diff --git a/bin/spack b/bin/spack index 0af8d62b5e..679ca9f1be 100755 --- a/bin/spack +++ b/bin/spack @@ -24,8 +24,8 @@ # Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ############################################################################## import sys -if not sys.version_info[:2] >= (2,7): - sys.exit("Spack requires Python 2.7. Version was %s." % sys.version_info) +if not sys.version_info[:2] >= (2,6): + sys.exit("Spack requires Python 2.6. Version was %s." % sys.version_info) import os diff --git a/lib/spack/spack/stage.py b/lib/spack/spack/stage.py index 839555d630..3dac798396 100644 --- a/lib/spack/spack/stage.py +++ b/lib/spack/spack/stage.py @@ -120,8 +120,7 @@ def _need_to_create_path(self): if spack.use_tmp_stage: # If we're using a tmp dir, it's a link, and it points at the right spot, # then keep it. - if (os.path.commonprefix((real_path, real_tmp)) == real_tmp - and os.path.exists(real_path)): + if (real_path.startswith(real_tmp) and os.path.exists(real_path)): return False else: # otherwise, just unlink it and start over. diff --git a/lib/spack/spack/test/__init__.py b/lib/spack/spack/test/__init__.py index 4479c45d77..8ddc7f227d 100644 --- a/lib/spack/spack/test/__init__.py +++ b/lib/spack/spack/test/__init__.py @@ -72,7 +72,7 @@ def run(names, verbose=False): runner = unittest.TextTestRunner(verbosity=verbosity) - testsRun = errors = failures = skipped = 0 + testsRun = errors = failures = 0 for test in names: module = 'spack.test.' + test print module @@ -83,12 +83,10 @@ def run(names, verbose=False): testsRun += result.testsRun errors += len(result.errors) failures += len(result.failures) - skipped += len(result.skipped) succeeded = not errors and not failures tty.msg("Tests Complete.", "%5d tests run" % testsRun, - "%5d skipped" % skipped, "%5d failures" % failures, "%5d errors" % errors) diff --git a/lib/spack/spack/test/concretize.py b/lib/spack/spack/test/concretize.py index 6ad2ef29d8..a7f4812c8c 100644 --- a/lib/spack/spack/test/concretize.py +++ b/lib/spack/spack/test/concretize.py @@ -134,29 +134,29 @@ def test_concretize_with_provides_when(self): def test_virtual_is_fully_expanded_for_callpath(self): # force dependence on fake "zmpi" by asking for MPI 10.0 spec = Spec('callpath ^mpi@10.0') - self.assertIn('mpi', spec.dependencies) - self.assertNotIn('fake', spec) + self.assertTrue('mpi' in spec.dependencies) + self.assertFalse('fake' in spec) spec.concretize() - self.assertIn('zmpi', spec.dependencies) - self.assertNotIn('mpi', spec) - self.assertIn('fake', spec.dependencies['zmpi']) + self.assertTrue('zmpi' in spec.dependencies) + self.assertFalse('mpi' in spec) + self.assertTrue('fake' in spec.dependencies['zmpi']) def test_virtual_is_fully_expanded_for_mpileaks(self): spec = Spec('mpileaks ^mpi@10.0') - self.assertIn('mpi', spec.dependencies) - self.assertNotIn('fake', spec) + self.assertTrue('mpi' in spec.dependencies) + self.assertFalse('fake' in spec) spec.concretize() - self.assertIn('zmpi', spec.dependencies) - self.assertIn('callpath', spec.dependencies) - self.assertIn('zmpi', spec.dependencies['callpath'].dependencies) - self.assertIn('fake', spec.dependencies['callpath'].dependencies['zmpi'].dependencies) + self.assertTrue('zmpi' in spec.dependencies) + self.assertTrue('callpath' in spec.dependencies) + self.assertTrue('zmpi' in spec.dependencies['callpath'].dependencies) + self.assertTrue('fake' in spec.dependencies['callpath'].dependencies['zmpi'].dependencies) - self.assertNotIn('mpi', spec) + self.assertFalse('mpi' in spec) def test_my_dep_depends_on_provider_of_my_virtual_dep(self): diff --git a/lib/spack/spack/test/mock_packages_test.py b/lib/spack/spack/test/mock_packages_test.py index adde70ff6c..e948376039 100644 --- a/lib/spack/spack/test/mock_packages_test.py +++ b/lib/spack/spack/test/mock_packages_test.py @@ -39,7 +39,6 @@ def set_pkg_dep(pkg, spec): class MockPackagesTest(unittest.TestCase): - @classmethod def setUp(self): # Use the mock packages database for these tests. This allows # us to set up contrived packages that don't interfere with @@ -52,7 +51,7 @@ def setUp(self): 'site' : spack.mock_site_config, 'user' : spack.mock_user_config } - @classmethod + def tearDown(self): """Restore the real packages path after any test.""" spack.db = self.real_db diff --git a/lib/spack/spack/test/spec_dag.py b/lib/spack/spack/test/spec_dag.py index 322f34cf02..fb67aa8a8d 100644 --- a/lib/spack/spack/test/spec_dag.py +++ b/lib/spack/spack/test/spec_dag.py @@ -57,10 +57,10 @@ def test_preorder_node_traversal(self): pairs = zip([0,1,2,3,4,2,3], names) traversal = dag.traverse() - self.assertListEqual([x.name for x in traversal], names) + self.assertEqual([x.name for x in traversal], names) traversal = dag.traverse(depth=True) - self.assertListEqual([(x, y.name) for x,y in traversal], pairs) + self.assertEqual([(x, y.name) for x,y in traversal], pairs) def test_preorder_edge_traversal(self): @@ -72,10 +72,10 @@ def test_preorder_edge_traversal(self): pairs = zip([0,1,2,3,4,3,2,3,1], names) traversal = dag.traverse(cover='edges') - self.assertListEqual([x.name for x in traversal], names) + self.assertEqual([x.name for x in traversal], names) traversal = dag.traverse(cover='edges', depth=True) - self.assertListEqual([(x, y.name) for x,y in traversal], pairs) + self.assertEqual([(x, y.name) for x,y in traversal], pairs) def test_preorder_path_traversal(self): @@ -87,10 +87,10 @@ def test_preorder_path_traversal(self): pairs = zip([0,1,2,3,4,3,2,3,1,2], names) traversal = dag.traverse(cover='paths') - self.assertListEqual([x.name for x in traversal], names) + self.assertEqual([x.name for x in traversal], names) traversal = dag.traverse(cover='paths', depth=True) - self.assertListEqual([(x, y.name) for x,y in traversal], pairs) + self.assertEqual([(x, y.name) for x,y in traversal], pairs) def test_postorder_node_traversal(self): @@ -102,10 +102,10 @@ def test_postorder_node_traversal(self): pairs = zip([4,3,2,3,2,1,0], names) traversal = dag.traverse(order='post') - self.assertListEqual([x.name for x in traversal], names) + self.assertEqual([x.name for x in traversal], names) traversal = dag.traverse(depth=True, order='post') - self.assertListEqual([(x, y.name) for x,y in traversal], pairs) + self.assertEqual([(x, y.name) for x,y in traversal], pairs) def test_postorder_edge_traversal(self): @@ -117,10 +117,10 @@ def test_postorder_edge_traversal(self): pairs = zip([4,3,3,2,3,2,1,1,0], names) traversal = dag.traverse(cover='edges', order='post') - self.assertListEqual([x.name for x in traversal], names) + self.assertEqual([x.name for x in traversal], names) traversal = dag.traverse(cover='edges', depth=True, order='post') - self.assertListEqual([(x, y.name) for x,y in traversal], pairs) + self.assertEqual([(x, y.name) for x,y in traversal], pairs) def test_postorder_path_traversal(self): @@ -132,10 +132,10 @@ def test_postorder_path_traversal(self): pairs = zip([4,3,3,2,3,2,1,2,1,0], names) traversal = dag.traverse(cover='paths', order='post') - self.assertListEqual([x.name for x in traversal], names) + self.assertEqual([x.name for x in traversal], names) traversal = dag.traverse(cover='paths', depth=True, order='post') - self.assertListEqual([(x, y.name) for x,y in traversal], pairs) + self.assertEqual([(x, y.name) for x,y in traversal], pairs) def test_conflicting_spec_constraints(self): @@ -199,13 +199,13 @@ def test_normalize_with_virtual_spec(self): def check_links(self, spec_to_check): for spec in spec_to_check.traverse(): for dependent in spec.dependents.values(): - self.assertIn( - spec.name, dependent.dependencies, + self.assertTrue( + spec.name in dependent.dependencies, "%s not in dependencies of %s" % (spec.name, dependent.name)) for dependency in spec.dependencies.values(): - self.assertIn( - spec.name, dependency.dependents, + self.assertTrue( + spec.name in dependency.dependents, "%s not in dependents of %s" % (spec.name, dependency.name)) @@ -385,13 +385,13 @@ def test_normalize_with_virtual_package(self): def test_contains(self): spec = Spec('mpileaks ^mpi ^libelf@1.8.11 ^libdwarf') - self.assertIn(Spec('mpi'), spec) - self.assertIn(Spec('libelf'), spec) - self.assertIn(Spec('libelf@1.8.11'), spec) - self.assertNotIn(Spec('libelf@1.8.12'), spec) - self.assertIn(Spec('libdwarf'), spec) - self.assertNotIn(Spec('libgoblin'), spec) - self.assertIn(Spec('mpileaks'), spec) + self.assertTrue(Spec('mpi') in spec) + self.assertTrue(Spec('libelf') in spec) + self.assertTrue(Spec('libelf@1.8.11') in spec) + self.assertFalse(Spec('libelf@1.8.12') in spec) + self.assertTrue(Spec('libdwarf') in spec) + self.assertFalse(Spec('libgoblin') in spec) + self.assertTrue(Spec('mpileaks') in spec) def test_copy_simple(self): diff --git a/lib/spack/spack/test/stage.py b/lib/spack/spack/test/stage.py index 08899f9810..a412549dc7 100644 --- a/lib/spack/spack/test/stage.py +++ b/lib/spack/spack/test/stage.py @@ -51,28 +51,20 @@ stage_name = 'spack-test-stage' -class with_tmp(object): - """Decorator that executes a function with or without spack set to use - a temp dir. Spack allows builds to happen directly in the - stage directory or in a tmp dir and symlinked into the stage - directory, so this lets us use the same test in both cases. +@contextmanager +def use_tmp(use_tmp): + """Allow some test code to be executed with spack.use_tmp_stage + set to a certain value. Context manager makes sure it's reset + on failure. """ - def __init__(self, use_tmp): - self.use_tmp = use_tmp - - def __call__(self, fun): - use_tmp = self.use_tmp - def new_test_function(self): - old_tmp = spack.use_tmp_stage - spack.use_tmp_stage = use_tmp - fun(self) - spack.use_tmp_stage = old_tmp - return new_test_function + old_tmp = spack.use_tmp_stage + spack.use_tmp_stage = use_tmp + yield + spack.use_tmp_stage = old_tmp class StageTest(unittest.TestCase): - @classmethod - def setUpClass(cls): + def setUp(self): """This sets up a mock archive to fetch, and a mock temp space for use by the Stage class. It doesn't actually create the Stage -- that is done by individual tests. @@ -92,52 +84,58 @@ def setUpClass(cls): tar('czf', archive_name, archive_dir) # Make spack use the test environment for tmp stuff. - cls.old_tmp_dirs = spack.tmp_dirs + self.old_tmp_dirs = spack.tmp_dirs spack.tmp_dirs = [test_tmp_path] + # record this since this test changes to directories that will + # be removed. + self.working_dir = os.getcwd() - @classmethod - def tearDownClass(cls): + + def tearDown(self): """Blows away the test environment directory.""" shutil.rmtree(test_files_dir) + # chdir back to original working dir + os.chdir(self.working_dir) + # restore spack's original tmp environment - spack.tmp_dirs = cls.old_tmp_dirs + spack.tmp_dirs = self.old_tmp_dirs def get_stage_path(self, stage, stage_name): - """Figure out based on a stage and an intended name where it should - be living. This depends on whether it's named or not. + """Figure out where a stage should be living. This depends on + whether it's named. """ - if stage_name: + if stage_name is not None: # If it is a named stage, we know where the stage should be - stage_path = join_path(spack.stage_path, stage_name) + return join_path(spack.stage_path, stage_name) else: # If it's unnamed, ensure that we ran mkdtemp in the right spot. - stage_path = stage.path - self.assertIsNotNone(stage_path) - self.assertEqual( - os.path.commonprefix((stage_path, spack.stage_path)), - spack.stage_path) - return stage_path + self.assertTrue(stage.path is not None) + self.assertTrue(stage.path.startswith(spack.stage_path)) + return stage.path def check_setup(self, stage, stage_name): """Figure out whether a stage was set up correctly.""" stage_path = self.get_stage_path(stage, stage_name) + + # Ensure stage was created in the spack stage directory self.assertTrue(os.path.isdir(stage_path)) if spack.use_tmp_stage: - # Make sure everything was created and linked correctly for - # a tmp stage. + # Check that the stage dir is really a symlink. self.assertTrue(os.path.islink(stage_path)) + # Make sure it points to a valid directory target = os.path.realpath(stage_path) self.assertTrue(os.path.isdir(target)) self.assertFalse(os.path.islink(target)) - self.assertEqual( - os.path.commonprefix((target, test_tmp_path)), - test_tmp_path) + + # Make sure the directory is in the place we asked it to + # be (see setUp and tearDown) + self.assertTrue(target.startswith(test_tmp_path)) else: # Make sure the stage path is NOT a link for a non-tmp stage @@ -146,15 +144,15 @@ def check_setup(self, stage, stage_name): def check_fetch(self, stage, stage_name): stage_path = self.get_stage_path(stage, stage_name) - self.assertIn(archive_name, os.listdir(stage_path)) + self.assertTrue(archive_name in os.listdir(stage_path)) self.assertEqual(join_path(stage_path, archive_name), stage.archive_file) def check_expand_archive(self, stage, stage_name): stage_path = self.get_stage_path(stage, stage_name) - self.assertIn(archive_name, os.listdir(stage_path)) - self.assertIn(archive_dir, os.listdir(stage_path)) + self.assertTrue(archive_name in os.listdir(stage_path)) + self.assertTrue(archive_dir in os.listdir(stage_path)) self.assertEqual( join_path(stage_path, archive_dir), @@ -192,32 +190,40 @@ def check_destroy(self, stage, stage_name): self.assertFalse(os.path.exists(target)) - def checkSetupAndDestroy(self, stage_name=None): - stage = Stage(archive_url, name=stage_name) - self.check_setup(stage, stage_name) - - stage.destroy() - self.check_destroy(stage, stage_name) - - - @with_tmp(True) def test_setup_and_destroy_name_with_tmp(self): - self.checkSetupAndDestroy(stage_name) + with use_tmp(True): + stage = Stage(archive_url, name=stage_name) + self.check_setup(stage, stage_name) + + stage.destroy() + self.check_destroy(stage, stage_name) - @with_tmp(False) def test_setup_and_destroy_name_without_tmp(self): - self.checkSetupAndDestroy(stage_name) + with use_tmp(False): + stage = Stage(archive_url, name=stage_name) + self.check_setup(stage, stage_name) + + stage.destroy() + self.check_destroy(stage, stage_name) - @with_tmp(True) def test_setup_and_destroy_no_name_with_tmp(self): - self.checkSetupAndDestroy(None) + with use_tmp(True): + stage = Stage(archive_url) + self.check_setup(stage, None) + + stage.destroy() + self.check_destroy(stage, None) - @with_tmp(False) def test_setup_and_destroy_no_name_without_tmp(self): - self.checkSetupAndDestroy(None) + with use_tmp(False): + stage = Stage(archive_url) + self.check_setup(stage, None) + + stage.destroy() + self.check_destroy(stage, None) def test_chdir(self): @@ -286,7 +292,7 @@ def test_restage(self): with closing(open('foobar', 'w')) as file: file.write("this file is to be destroyed.") - self.assertIn('foobar', os.listdir(stage.expanded_archive_path)) + self.assertTrue('foobar' in os.listdir(stage.expanded_archive_path)) # Make sure the file is not there after restage. stage.restage() @@ -295,7 +301,7 @@ def test_restage(self): stage.chdir_to_archive() self.check_chdir_to_archive(stage, stage_name) - self.assertNotIn('foobar', os.listdir(stage.expanded_archive_path)) + self.assertFalse('foobar' in os.listdir(stage.expanded_archive_path)) stage.destroy() self.check_destroy(stage, stage_name)