Exemple #1
0
def test_merge_to_existing_directory(stage, link_tree):
    with working_dir(stage.path):

        touchp('dest/x')
        touchp('dest/a/b/y')

        link_tree.merge('dest')

        check_file_link('dest/1')
        check_file_link('dest/a/b/2')
        check_file_link('dest/a/b/3')
        check_file_link('dest/c/4')
        check_file_link('dest/c/d/5')
        check_file_link('dest/c/d/6')
        check_file_link('dest/c/d/e/7')

        assert os.path.isfile('dest/x')
        assert os.path.isfile('dest/a/b/y')

        link_tree.unmerge('dest')

        assert os.path.isfile('dest/x')
        assert os.path.isfile('dest/a/b/y')

        assert not os.path.isfile('dest/1')
        assert not os.path.isfile('dest/a/b/2')
        assert not os.path.isfile('dest/a/b/3')
        assert not os.path.isfile('dest/c/4')
        assert not os.path.isfile('dest/c/d/5')
        assert not os.path.isfile('dest/c/d/6')
        assert not os.path.isfile('dest/c/d/e/7')
Exemple #2
0
def test_log_install_with_build_files(install_mockery, monkeypatch):
    """Test the installer's log function when have build files."""
    config_log = 'config.log'

    # Retain the original function for use in the monkey patch that is used
    # to raise an exception under the desired condition for test coverage.
    orig_install_fn = fs.install

    def _install(src, dest):
        orig_install_fn(src, dest)
        if src.endswith(config_log):
            raise Exception('Mock log install error')

    monkeypatch.setattr(fs, 'install', _install)

    spec = Spec('trivial-install-test-package').concretized()

    # Set up mock build files and try again to include archive failure
    log_path = spec.package.log_path
    log_dir = os.path.dirname(log_path)
    fs.mkdirp(log_dir)
    with fs.working_dir(log_dir):
        fs.touch(log_path)
        fs.touch(spec.package.env_path)
        fs.touch(spec.package.env_mods_path)
        fs.touch(spec.package.configure_args_path)

    install_path = os.path.dirname(spec.package.install_log_path)
    fs.mkdirp(install_path)

    source = spec.package.stage.source_path
    config = os.path.join(source, 'config.log')
    fs.touchp(config)
    spec.package.archive_files = ['missing', '..', config]

    spack.installer.log(spec.package)

    assert os.path.exists(spec.package.install_log_path)
    assert os.path.exists(spec.package.install_env_path)
    assert os.path.exists(spec.package.install_configure_args_path)

    archive_dir = os.path.join(install_path, 'archived-files')
    source_dir = os.path.dirname(source)
    rel_config = os.path.relpath(config, source_dir)

    assert os.path.exists(os.path.join(archive_dir, rel_config))
    assert not os.path.exists(os.path.join(archive_dir, 'missing'))

    expected_errs = [
        'OUTSIDE SOURCE PATH',  # for '..'
        'FAILED TO ARCHIVE'  # for rel_config
    ]
    with open(os.path.join(archive_dir, 'errors.txt'), 'r') as fd:
        for ln, expected in zip(fd, expected_errs):
            assert expected in ln

    # Cleanup
    shutil.rmtree(log_dir)
Exemple #3
0
def setup_install_test(source_paths, install_test_root):
    """
    Set up the install test by creating sources and install test roots.

    The convention used here is to create an empty file if the path name
    ends with an extension otherwise, a directory is created.
    """
    fs.mkdirp(install_test_root)
    for path in source_paths:
        if os.path.splitext(path)[1]:
            fs.touchp(path)
        else:
            fs.mkdirp(path)
Exemple #4
0
def test_ignore(stage, link_tree):
    with working_dir(stage.path):
        touchp('source/.spec')
        touchp('dest/.spec')

        link_tree.merge('dest', ignore=lambda x: x == '.spec')
        link_tree.unmerge('dest', ignore=lambda x: x == '.spec')

        assert not os.path.exists('dest/1')
        assert not os.path.exists('dest/a')
        assert not os.path.exists('dest/c')

        assert os.path.isfile('source/.spec')
        assert os.path.isfile('dest/.spec')
Exemple #5
0
def test_ignore(stage, link_tree):
    with working_dir(stage.path):
        touchp('source/.spec')
        touchp('dest/.spec')

        link_tree.merge('dest', ignore=lambda x: x == '.spec')
        link_tree.unmerge('dest', ignore=lambda x: x == '.spec')

        assert not os.path.exists('dest/1')
        assert not os.path.exists('dest/a')
        assert not os.path.exists('dest/c')

        assert os.path.isfile('source/.spec')
        assert os.path.isfile('dest/.spec')
Exemple #6
0
def test_overwrite_install_backup_failure(temporary_store, config,
                                          mock_packages, tmpdir):
    """
    When doing an overwrite install that fails, Spack should try to recover the
    original prefix. If that fails, the spec is lost, and it should be removed
    from the database.
    """
    # Where to store the backups
    backup = str(tmpdir.mkdir("backup"))

    class InstallerThatAccidentallyDeletesTheBackupDir:
        def _install_task(self, task):
            # Remove the backup directory so that restoring goes terribly wrong
            shutil.rmtree(backup)
            raise Exception("Some fatal install error")

    class FakeDatabase:
        called = False

        def remove(self, spec):
            self.called = True

    # Get a build task. TODO: refactor this to avoid calling internal methods
    const_arg = installer_args(["b"])
    installer = create_installer(const_arg)
    installer._init_queue()
    task = installer._pop_task()

    # Make sure the install prefix exists
    installed_file = os.path.join(task.pkg.prefix, 'some_file')
    fs.touchp(installed_file)

    fake_installer = InstallerThatAccidentallyDeletesTheBackupDir()
    fake_db = FakeDatabase()
    overwrite_install = inst.OverwriteInstall(fake_installer,
                                              fake_db,
                                              task,
                                              tmp_root=backup)

    # Installation should throw the installation exception, not the backup
    # failure.
    with pytest.raises(Exception, match='Some fatal install error'):
        overwrite_install.install()

    # Make sure that `remove` was called on the database after an unsuccessful
    # attempt to restore the backup.
    assert fake_db.called
Exemple #7
0
def test_overwrite_install_backup_success(temporary_store, config,
                                          mock_packages, tmpdir):
    """
    When doing an overwrite install that fails, Spack should restore the backup
    of the original prefix, and leave the original spec marked installed.
    """
    # Where to store the backups
    backup = str(tmpdir.mkdir("backup"))

    # Get a build task. TODO: refactor this to avoid calling internal methods
    const_arg = installer_args(["b"])
    installer = create_installer(const_arg)
    installer._init_queue()
    task = installer._pop_task()

    # Make sure the install prefix exists with some trivial file
    installed_file = os.path.join(task.pkg.prefix, 'some_file')
    fs.touchp(installed_file)

    class InstallerThatWipesThePrefixDir:
        def _install_task(self, task):
            shutil.rmtree(task.pkg.prefix, ignore_errors=True)
            fs.mkdirp(task.pkg.prefix)
            raise Exception("Some fatal install error")

    class FakeDatabase:
        called = False

        def remove(self, spec):
            self.called = True

    fake_installer = InstallerThatWipesThePrefixDir()
    fake_db = FakeDatabase()
    overwrite_install = inst.OverwriteInstall(fake_installer,
                                              fake_db,
                                              task,
                                              tmp_root=backup)

    # Installation should throw the installation exception, not the backup
    # failure.
    with pytest.raises(Exception, match='Some fatal install error'):
        overwrite_install.install()

    # Make sure the package is not marked uninstalled and the original dir
    # is back.
    assert not fake_db.called
    assert os.path.exists(installed_file)
Exemple #8
0
def test_cache_init_entry_fails(file_cache):
    """Test init_entry failures."""
    relpath = fs.join_path('test-dir', 'read-only-file.txt')
    cachefile = file_cache.cache_path(relpath)
    fs.touchp(cachefile)

    # Ensure directory causes exception
    with pytest.raises(CacheError, match='not a file'):
        file_cache.init_entry(os.path.dirname(relpath))

    # Ensure non-readable file causes exception
    os.chmod(cachefile, 0o200)
    with pytest.raises(CacheError, match='Cannot access cache file'):
        file_cache.init_entry(relpath)

    # Ensure read-only parent causes exception
    relpath = fs.join_path('test-dir', 'another-file.txxt')
    cachefile = file_cache.cache_path(relpath)
    os.chmod(os.path.dirname(cachefile), 0o400)
    with pytest.raises(CacheError, match='Cannot access cache dir'):
        file_cache.init_entry(relpath)
Exemple #9
0
def stage():
    """Creates a stage with the directory structure for the tests."""
    s = Stage('link-tree-test')
    s.create()

    with working_dir(s.path):
        touchp('source/1')
        touchp('source/a/b/2')
        touchp('source/a/b/3')
        touchp('source/c/4')
        touchp('source/c/d/5')
        touchp('source/c/d/6')
        touchp('source/c/d/e/7')

    yield s

    s.destroy()
def stage(tmpdir_factory):
    """Creates a stage with the directory structure for the tests."""

    s = tmpdir_factory.mktemp('filesystem_test')

    with s.as_cwd():
        # Create source file hierarchy
        fs.touchp('source/1')
        fs.touchp('source/a/b/2')
        fs.touchp('source/a/b/3')
        fs.touchp('source/c/4')
        fs.touchp('source/c/d/5')
        fs.touchp('source/c/d/6')
        fs.touchp('source/c/d/e/7')
        fs.touchp('source/g/h/i/8')
        fs.touchp('source/g/h/i/9')
        fs.touchp('source/g/i/j/10')

        # Create symlinks
        symlink(os.path.abspath('source/1'), 'source/2')
        symlink('b/2', 'source/a/b2')
        symlink('a/b', 'source/f')

        # Create destination directory
        fs.mkdirp('dest')

    yield s
Exemple #11
0
def stage(tmpdir_factory):
    """Creates a stage with the directory structure for the tests."""

    s = tmpdir_factory.mktemp('filesystem_test')

    with s.as_cwd():
        # Create source file hierarchy
        fs.touchp('source/1')
        fs.touchp('source/a/b/2')
        fs.touchp('source/a/b/3')
        fs.touchp('source/c/4')
        fs.touchp('source/c/d/5')
        fs.touchp('source/c/d/6')
        fs.touchp('source/c/d/e/7')

        # Create symlinks
        os.symlink(os.path.abspath('source/1'), 'source/2')
        os.symlink('b/2', 'source/a/b2')
        os.symlink('a/b', 'source/f')

        # Create destination directory
        fs.mkdirp('dest')

    yield s
Exemple #12
0
def stage():
    """Creates a stage with the directory structure for the tests."""
    s = Stage('link-tree-test')
    s.create()

    with working_dir(s.path):
        touchp('source/1')
        touchp('source/a/b/2')
        touchp('source/a/b/3')
        touchp('source/c/4')
        touchp('source/c/d/5')
        touchp('source/c/d/6')
        touchp('source/c/d/e/7')

    yield s

    s.destroy()