Ejemplo n.º 1
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
Ejemplo n.º 2
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)