예제 #1
0
def test_init_fail_and_retry(clean_app):
    """Test replay first database init after a failure."""
    with clean_app.app_context():
        ext = clean_app.extensions['invenio-db']
        if db.engine.name == 'sqlite':
            raise pytest.skip('upgrades are not supported on sqlite.')

        # create a conflicting table.
        db.engine.execute('CREATE table b2share_community (wrong int);')
        result = upgrade_run(clean_app)
        assert result.exit_code == -1

        # remove the problematic table
        db.engine.execute('DROP table b2share_community;')
        result = upgrade_run(clean_app)
        assert result.exit_code == 0

        # check that the migration information have been saved
        migrations = Migration.query.all()
        assert len(migrations) == 1
        mig = migrations[0]
        assert mig.version == current_migration_version
        assert mig.success

    with clean_app.app_context():
        repeat_upgrade(clean_app, ext.alembic)

    with clean_app.app_context():
        validate_database_schema(clean_app, ext.alembic)
예제 #2
0
def test_init_fail_and_retry(clean_app):
    """Test replay first database init after a failure."""
    with clean_app.app_context():
        ext = clean_app.extensions['invenio-db']
        if db.engine.name == 'sqlite':
            raise pytest.skip('upgrades are not supported on sqlite.')

        # create a conflicting table.
        db.engine.execute('CREATE table b2share_community (wrong int);')
        result = upgrade_run(clean_app)
        assert result.exit_code == -1

        # remove the problematic table
        db.engine.execute('DROP table b2share_community;')
        result = upgrade_run(clean_app)
        assert result.exit_code == 0

        # check that the migration information have been saved
        migrations = Migration.query.all()
        assert len(migrations) == 1
        mig = migrations[0]
        assert mig.version == current_migration_version
        assert mig.success

    with clean_app.app_context():
        repeat_upgrade(clean_app, ext.alembic)

    with clean_app.app_context():
        validate_database_schema(clean_app, ext.alembic)
예제 #3
0
def test_failed_and_repair_upgrade_from_v2_0_0(clean_app):
    """Test upgrade from an unknown B2SHARE version."""
    with clean_app.app_context():
        ext = clean_app.extensions['invenio-db']
        if db.engine.name == 'sqlite':
            raise pytest.skip('upgrades are not supported on sqlite.')

        # bring db to v2.0.1 state
        db_create_v2_0_1()
        Migration.__table__.create(db.engine)
        db.session.commit()
        result = upgrade_run(clean_app)
        assert result.exception.__class__ == sa.exc.ProgrammingError

        Migration.__table__.drop(db.engine)
        result = upgrade_run(clean_app)
        assert result.exit_code == 0
        # Check that the resulting state is in sync with sqlalchemy's MetaData
        assert not ext.alembic.compare_metadata()

        # check that the migration information have been saved
        migrations = Migration.query.all()
        assert len(migrations) == 1
        mig = migrations[0]
        assert mig.version == current_migration_version
        assert mig.success

        repeat_upgrade(clean_app, ext.alembic)

        validate_metadata(clean_app, ext.alembic)
예제 #4
0
def test_upgrade_from_v2_0_0(clean_app):
    """Test upgrading B2Share from version 2.0.0."""
    with clean_app.app_context():
        ext = clean_app.extensions['invenio-db']
        if db.engine.name == 'sqlite':
            raise pytest.skip('upgrades are not supported on sqlite.')
        # bring db to v2.0.1 state
        db_create_v2_0_1()

        # Upgrade B2SHARE with `b2share upgrade run`
        result = upgrade_run(clean_app)
        assert result.exit_code == 0

        expected_migrations = UpgradeRecipe.build_upgrade_path(
            '2.0.0', current_migration_version)
        repeat_upgrade(clean_app, ext.alembic, len(expected_migrations))

        # check that the migration information have been saved
        migrations = Migration.query.order_by(Migration.created.asc()).all()
        assert len(migrations) == len(expected_migrations)
        assert migrations[-1].version == current_migration_version
        for mig in migrations:
            for step in mig.data['steps']:
                assert step['status'] == 'success'
            assert mig.data['error'] is None

    with clean_app.app_context():
        validate_loaded_data(clean_app, ext.alembic)
        # Check that it is possible to create a new record version after
        # the upgrade
        _create_new_record_version(clean_app)

        validate_database_schema(clean_app, ext.alembic)
예제 #5
0
def test_upgrade_from_v2_0_0(clean_app):
    """Test upgrading B2Share from version 2.0.0."""
    with clean_app.app_context():
        ext = clean_app.extensions['invenio-db']
        if db.engine.name == 'sqlite':
            raise pytest.skip('upgrades are not supported on sqlite.')
        # bring db to v2.0.1 state
        db_create_v2_0_1()

        # Upgrade B2SHARE with `b2share upgrade run`
        result = upgrade_run(clean_app)
        assert result.exit_code == 0

        expected_migrations = UpgradeRecipe.build_upgrade_path(
            '2.0.0', current_migration_version)
        repeat_upgrade(clean_app, ext.alembic, len(expected_migrations))

        # check that the migration information have been saved
        migrations = Migration.query.order_by(Migration.created.asc()).all()
        assert len(migrations) == len(expected_migrations)
        assert migrations[-1].version == current_migration_version
        for mig in migrations:
            for step in mig.data['steps']:
                assert step['status'] == 'success'
            assert mig.data['error'] is None

    with clean_app.app_context():
        validate_loaded_data(clean_app, ext.alembic)
        # Check that it is possible to create a new record version after
        # the upgrade
        _create_new_record_version(clean_app)

        validate_database_schema(clean_app, ext.alembic)
예제 #6
0
def test_upgrade_from_v2_0_0(clean_app):
    """Test upgrading B2Share from version 2.0.0."""
    with clean_app.app_context():
        ext = clean_app.extensions['invenio-db']
        if db.engine.name == 'sqlite':
            raise pytest.skip('upgrades are not supported on sqlite.')
        # bring db to v2.0.1 state
        db_create_v2_0_1()

        # Upgrade B2SHARE with `b2share upgrade run`
        result = upgrade_run(clean_app)
        assert result.exit_code == 0

        repeat_upgrade(clean_app, ext.alembic)

        # check that the migration information have been saved
        migrations = Migration.query.all()
        assert len(migrations) == 1
        mig = migrations[0]
        assert mig.version == current_migration_version
        for step in mig.data['steps']:
            assert step['status'] == 'success'
        assert mig.data['error'] is None

        validate_metadata(clean_app, ext.alembic)
예제 #7
0
def test_failed_and_repair_upgrade_from_v2_0_0(clean_app):
    """Test upgrade from an unknown B2SHARE version."""
    with clean_app.app_context():
        ext = clean_app.extensions['invenio-db']
        if db.engine.name == 'sqlite':
            raise pytest.skip('upgrades are not supported on sqlite.')

        # bring db to v2.0.1 state
        db_create_v2_0_1()
        Migration.__table__.create(db.engine)
        db.session.commit()
        result = upgrade_run(clean_app)
        assert result.exception.__class__ == sa.exc.ProgrammingError

        Migration.__table__.drop(db.engine)
        result = upgrade_run(clean_app)
        assert result.exit_code == 0
        # Check that the resulting state is in sync with sqlalchemy's MetaData
        assert not ext.alembic.compare_metadata()

        # check that the migration information have been saved
        migrations = Migration.query.all()
        assert len(migrations) == 1
        mig = migrations[0]
        assert mig.version == current_migration_version
        assert mig.success

    with clean_app.app_context():
        repeat_upgrade(clean_app, ext.alembic)

    with clean_app.app_context():
        validate_loaded_data(clean_app, ext.alembic)
        # Check that it is possible to create a new record version after
        # the upgrade
        _create_new_record_version(clean_app)
        validate_database_schema(clean_app, ext.alembic)
예제 #8
0
def test_upgrade_from_unknown_version(app):
    """Test upgrade from an unknown B2SHARE version."""
    with app.app_context():
        ext = app.extensions['invenio-db']
        if db.engine.name == 'sqlite':
            raise pytest.skip('upgrades are not supported on sqlite.')

        migration = Migration(version='unknown.version',
                              data=dict(steps=[], error=None,
                                        status='success'))
        db.session.add(migration)
        db.session.commit()

        # Upgrade B2SHARE with `b2share upgrade run`
        result = upgrade_run(app)
        assert result.exit_code == MigrationFromUnknownVersionError.exit_code

        # check that the migration information have been saved
        migrations = Migration.query.all()
        assert len(migrations) == 1
예제 #9
0
def test_init_upgrade(clean_app):
    """Test database upgrade from a clean state."""
    with clean_app.app_context():
        ext = clean_app.extensions['invenio-db']
        if db.engine.name == 'sqlite':
            raise pytest.skip('upgrades are not supported on sqlite.')

        result = upgrade_run(clean_app)
        assert result.exit_code == 0

        # check that the migration information have been saved
        migrations = Migration.query.all()
        assert len(migrations) == 1
        mig = migrations[0]
        assert mig.version == current_migration_version
        assert mig.success

        repeat_upgrade(clean_app, ext.alembic)

        validate_metadata(clean_app, ext.alembic)
예제 #10
0
def test_upgrade_from_unknown_version(app):
    """Test upgrade from an unknown B2SHARE version."""
    with app.app_context():
        ext = app.extensions['invenio-db']
        if db.engine.name == 'sqlite':
            raise pytest.skip('upgrades are not supported on sqlite.')

        migration = Migration(
            version = 'unknown.version',
            data = dict(steps=[], error=None, status='success')
        )
        db.session.add(migration)
        db.session.commit()

        # Upgrade B2SHARE with `b2share upgrade run`
        result = upgrade_run(app)
        assert result.exit_code == MigrationFromUnknownVersionError.exit_code

        # check that the migration information have been saved
        migrations = Migration.query.all();
        assert len(migrations) == 1
예제 #11
0
def test_init_upgrade(clean_app):
    """Test database upgrade from a clean state."""
    with clean_app.app_context():
        ext = clean_app.extensions['invenio-db']
        if db.engine.name == 'sqlite':
            raise pytest.skip('upgrades are not supported on sqlite.')

        result = upgrade_run(clean_app)
        assert result.exit_code == 0

        # check that the migration information have been saved
        migrations = Migration.query.all();
        assert len(migrations) == 1
        mig = migrations[0]
        assert mig.version == current_migration_version
        assert mig.success

    with clean_app.app_context():
        repeat_upgrade(clean_app, ext.alembic)

    with clean_app.app_context():
        validate_database_schema(clean_app, ext.alembic)
예제 #12
0
def test_failed_and_repair_upgrade_from_v2_0_0(clean_app):
    """Test upgrade from an unknown B2SHARE version."""

    def failing_step(alembic, verbose):
        """Failing step used to make the upgrade fail."""
        raise Exception('This error is on purpose')

    with clean_app.app_context():
        expected_migrations = UpgradeRecipe.build_upgrade_path(
            '2.0.0', current_migration_version)
        ext = clean_app.extensions['invenio-db']
        if db.engine.name == 'sqlite':
            raise pytest.skip('upgrades are not supported on sqlite.')

        # bring db to v2.0.1 state
        db_create_v2_0_1()
        # Add a table which shouldn't exist in 2.0.1 version. This will
        # Make the 2.0.0->2.1.0 migration fail.
        Migration.__table__.create(db.engine)
        db.session.commit()
        result = upgrade_run(clean_app)
        assert result.exception.__class__ == sa.exc.ProgrammingError

        # Drop the problematic table
        Migration.__table__.drop(db.engine)

        # Fail every other migration one by one. Fixing the previous one at
        # each iteration.
        expected_number_of_migrations = 0
        first_loop = True
        for migration_idx  in range(len(expected_migrations)):
            migration = expected_migrations[migration_idx]
            # Add a failing step to the migration
            migration.step()(failing_step)
            # Run again a failing upgrade.
            result = upgrade_run(clean_app)
            assert result.exit_code == -1
            # This time the upgrade succeeded partially, the db schema is migrated
            # But not the records.
            migrations = Migration.query.order_by(
                Migration.updated.asc()).all()
            # The first failing migration is expected to save only one
            # "Migration" row in the database, every other migration should
            # have 2 migrations (the successful previous migration and the
            # next failing one).
            if first_loop:
                expected_number_of_migrations += 1
                first_loop = False
            else:
                expected_number_of_migrations += 2

            assert len(migrations) == expected_number_of_migrations
            number_of_migrations = len(migrations)
            last_migration = migrations[-1]
            assert last_migration.version == migration.dst_version
            assert not last_migration.success
            # Remove the failing migration step
            migration.remove_step(failing_step)
        # Migrate successfully
        result = upgrade_run(clean_app)
        assert result.exit_code == 0
        # Check that the resulting state is in sync with sqlalchemy's MetaData
        assert not ext.alembic.compare_metadata()

        # check that the migration information have been saved
        migrations = Migration.query.order_by(Migration.created.asc()).all()
        # Failed release + total succeeded releases
        expected_number_of_migrations += 1
        assert len(migrations) == expected_number_of_migrations
        # Check that every migration ran successfully
        assert [mig.version for mig in migrations if mig.success] == \
            [mig.dst_version for mig in expected_migrations]

    with clean_app.app_context():
        repeat_upgrade(clean_app, ext.alembic, expected_number_of_migrations)

    with clean_app.app_context():
        validate_loaded_data(clean_app, ext.alembic)
        # Check that it is possible to create a new record version after
        # the upgrade
        _create_new_record_version(clean_app)
        validate_database_schema(clean_app, ext.alembic)
예제 #13
0
def test_failed_and_repair_upgrade_from_v2_0_0(clean_app):
    """Test upgrade from an unknown B2SHARE version."""
    def failing_step(alembic, verbose):
        """Failing step used to make the upgrade fail."""
        raise Exception('This error is on purpose')

    with clean_app.app_context():
        expected_migrations = UpgradeRecipe.build_upgrade_path(
            '2.0.0', current_migration_version)
        ext = clean_app.extensions['invenio-db']
        if db.engine.name == 'sqlite':
            raise pytest.skip('upgrades are not supported on sqlite.')

        # bring db to v2.0.1 state
        db_create_v2_0_1()
        # Add a table which shouldn't exist in 2.0.1 version. This will
        # Make the 2.0.0->2.1.0 migration fail.
        Migration.__table__.create(db.engine)
        db.session.commit()
        result = upgrade_run(clean_app)
        assert result.exception.__class__ == sa.exc.ProgrammingError

        # Drop the problematic table
        Migration.__table__.drop(db.engine)

        # Fail every other migration one by one. Fixing the previous one at
        # each iteration.
        expected_number_of_migrations = 0
        first_loop = True
        for migration_idx in range(len(expected_migrations)):
            migration = expected_migrations[migration_idx]
            # Add a failing step to the migration
            migration.step()(failing_step)
            # Run again a failing upgrade.
            result = upgrade_run(clean_app)
            assert result.exit_code == -1
            # This time the upgrade succeeded partially, the db schema is migrated
            # But not the records.
            migrations = Migration.query.order_by(
                Migration.updated.asc()).all()
            # The first failing migration is expected to save only one
            # "Migration" row in the database, every other migration should
            # have 2 migrations (the successful previous migration and the
            # next failing one).
            if first_loop:
                expected_number_of_migrations += 1
                first_loop = False
            else:
                expected_number_of_migrations += 2

            assert len(migrations) == expected_number_of_migrations
            number_of_migrations = len(migrations)
            last_migration = migrations[-1]
            assert last_migration.version == migration.dst_version
            assert not last_migration.success
            # Remove the failing migration step
            migration.remove_step(failing_step)
        # Migrate successfully
        result = upgrade_run(clean_app)
        assert result.exit_code == 0
        # Check that the resulting state is in sync with sqlalchemy's MetaData
        assert not ext.alembic.compare_metadata()

        # check that the migration information have been saved
        migrations = Migration.query.order_by(Migration.created.asc()).all()
        # Failed release + total succeeded releases
        expected_number_of_migrations += 1
        assert len(migrations) == expected_number_of_migrations
        # Check that every migration ran successfully
        assert [mig.version for mig in migrations if mig.success] == \
            [mig.dst_version for mig in expected_migrations]

    with clean_app.app_context():
        repeat_upgrade(clean_app, ext.alembic, expected_number_of_migrations)

    with clean_app.app_context():
        validate_loaded_data(clean_app, ext.alembic)
        # Check that it is possible to create a new record version after
        # the upgrade
        _create_new_record_version(clean_app)
        validate_database_schema(clean_app, ext.alembic)