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)
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)
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)
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)
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)
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)
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)
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)