def test_order_migrations_error_on_unclear_start_migration(self): first = migration.Migration('1', None) second = migration.Migration('3', '2') migrations = [first, second] manager = migration_manager.MigrationManager(self.TEST_MIGRATIONS_DIR) with self.assertRaisesRegex(error.SpannerError, 'no valid previous'): manager._order_migrations(migrations)
def test_order_migrations_error_on_unclear_start_migration(self): first = migration.Migration("1", None, "1") second = migration.Migration("3", "2", "3") migrations = [first, second] manager = migration_manager.MigrationManager(self.TEST_MIGRATIONS_DIR) with self.assertRaisesRegex(error.SpannerError, "no valid previous"): manager._order_migrations(migrations)
def test_order_migrations_error_on_circular_dependency(self): first = migration.Migration("1", "3", "1") second = migration.Migration("2", "1", "2") third = migration.Migration("3", "2", "3") migrations = [third, first, second] manager = migration_manager.MigrationManager(self.TEST_MIGRATIONS_DIR) with self.assertRaisesRegex(error.SpannerError, "No valid migration"): manager._order_migrations(migrations)
def test_order_migrations_error_on_circular_dependency(self): first = migration.Migration('1', '3') second = migration.Migration('2', '1') third = migration.Migration('3', '2') migrations = [third, first, second] manager = migration_manager.MigrationManager(self.TEST_MIGRATIONS_DIR) with self.assertRaisesRegex(error.SpannerError, 'No valid migration'): manager._order_migrations(migrations)
def test_order_migrations_error_on_unclear_successor(self): first = migration.Migration('1', None) second = migration.Migration('2', '1') third = migration.Migration('3', '1') migrations = [third, first, second] manager = migration_manager.MigrationManager(self.TEST_MIGRATIONS_DIR) with self.assertRaisesRegex(error.SpannerError, 'unclear successor'): manager._order_migrations(migrations)
def test_order_migrations_with_no_none(self): first = migration.Migration('2', '1') second = migration.Migration('3', '2') third = migration.Migration('4', '3') migrations = [third, first, second] expected_order = [first, second, third] manager = migration_manager.MigrationManager(self.TEST_MIGRATIONS_DIR) self.assertEqual(manager._order_migrations(migrations), expected_order)
def test_order_migrations_error_on_unclear_successor(self): first = migration.Migration("1", None, "1") second = migration.Migration("2", "1", "2") third = migration.Migration("3", "1", "3") migrations = [third, first, second] manager = migration_manager.MigrationManager(self.TEST_MIGRATIONS_DIR) with self.assertRaisesRegex(error.SpannerError, "unclear successor"): manager._order_migrations(migrations)
def test_order_migrations_with_no_none(self): first = migration.Migration("2", "1", "2") second = migration.Migration("3", "2", "3") third = migration.Migration("4", "3", "4") migrations = [third, first, second] expected_order = [first, second, third] manager = migration_manager.MigrationManager(self.TEST_MIGRATIONS_DIR) self.assertEqual(manager._order_migrations(migrations), expected_order)
def test_migrate(self): connection = mock.Mock() executor = migration_executor.MigrationExecutor(connection) first = migration.Migration('1', None) second = migration.Migration('2', '1') third = migration.Migration('3', '2') with mock.patch.object(executor, 'migrations') as migrations: migrations.return_value = [first, second, third] migrated = {'1': True, '2': False, '3': False} with mock.patch.object(executor, '_migration_status_map', migrated): executor.migrate() self.assertEqual(migrated, {'1': True, '2': True, '3': True})
def test_rollback(self): connection = mock.Mock() executor = migration_executor.MigrationExecutor( connection, self.TEST_MIGRATIONS_DIR ) first = migration.Migration("1", None, "1") second = migration.Migration("2", "1", "2") third = migration.Migration("3", "2", "3") with mock.patch.object(executor, "migrations") as migrations: migrations.return_value = [first, second, third] migrated = {"1": True, "2": False, "3": False} with mock.patch.object(executor, "_migration_status_map", migrated): executor.rollback("1") self.assertEqual(migrated, {"1": False, "2": False, "3": False})
def test_filter_migrations_error_on_bad_last_migration(self): connection = mock.Mock() executor = migration_executor.MigrationExecutor(connection) first = migration.Migration('1', None) second = migration.Migration('2', '1') third = migration.Migration('3', '2') migrations = [first, second, third] migrated = {'1': True, '2': False, '3': False} with mock.patch.object(executor, '_migration_status_map', migrated): with self.assertRaises(error.SpannerError): executor._filter_migrations(migrations, False, '1') with self.assertRaises(error.SpannerError): executor._filter_migrations(migrations, False, '4')
def _migration_from_file(self, filename: str) -> migration.Migration: """Loads a single migration from the given filename in the base dir.""" module_name = re.sub(r"\W", "_", filename) path = os.path.join(self.basedir, filename) if self._pkg_name is not None: # Prepend package name to module name to import full module name module_name = "{}.{}".format(self._pkg_name, module_name) spec = importlib.util.spec_from_file_location(module_name, path) module = importlib.util.module_from_spec(spec) spec.loader.exec_module(module) module_doc = module.__doc__.split("\n") if not module_doc: description = "<unknown>" else: description = module_doc[0] try: result = migration.Migration( module.migration_id, module.prev_migration_id, description, getattr(module, "upgrade", None), getattr(module, "downgrade", None), ) except AttributeError: raise error.SpannerError("{} has no migration id".format(path)) return result
def test_filter_migrations_error_on_bad_last_migration(self): connection = mock.Mock() executor = migration_executor.MigrationExecutor( connection, self.TEST_MIGRATIONS_DIR ) first = migration.Migration("1", None, "1") second = migration.Migration("2", "1", "2") third = migration.Migration("3", "2", "3") migrations = [first, second, third] migrated = {"1": True, "2": False, "3": False} with mock.patch.object(executor, "_migration_status_map", migrated): with self.assertRaises(error.SpannerError): executor._filter_migrations(migrations, False, "1") with self.assertRaises(error.SpannerError): executor._filter_migrations(migrations, False, "4")
def test_show_migrations(self): connection = mock.Mock() executor = migration_executor.MigrationExecutor( connection, self.TEST_MIGRATIONS_DIR ) first = migration.Migration("abcdef", None, "1") second = migration.Migration("012345", "abcdef", "2") third = migration.Migration("6abcde", "012345", "3") with mock.patch.object(executor, "migrations") as migrations: migrations.return_value = [first, second, third] migrated = {"abcdef": True, "012345": False, "6abcde": False} with mock.patch.object(executor, "_migration_status_map", migrated): with mock.patch("sys.stdout", new_callable=StringIO) as mock_stdout: executor.show_migrations() self.assertEqual( "[ ] 6abcde, 3\n[ ] 012345, 2\n[X] abcdef, 1\n", mock_stdout.getvalue(), )
def test_validate_migrations(self): connection = mock.Mock() executor = migration_executor.MigrationExecutor( connection, self.TEST_MIGRATIONS_DIR) first = migration.Migration('1', None) second = migration.Migration('2', '1') third = migration.Migration('3', '2') with mock.patch.object(executor, 'migrations') as migrations: migrations.return_value = [first, second, third] migrated = {'1': True, '2': False, '3': False} with mock.patch.object(executor, '_migration_status_map', migrated): executor._validate_migrations() migrated = {'1': False, '2': False, '3': False} with mock.patch.object(executor, '_migration_status_map', migrated): executor._validate_migrations()
def test_filter_migrations(self): connection = mock.Mock() executor = migration_executor.MigrationExecutor(connection) first = migration.Migration('1', None) second = migration.Migration('2', '1') third = migration.Migration('3', '2') migrations = [first, second, third] migrated = {'1': True, '2': False, '3': False} with mock.patch.object(executor, '_migration_status_map', migrated): filtered = executor._filter_migrations(migrations, False, None) self.assertEqual(filtered, [second, third]) filtered = executor._filter_migrations(migrations, False, '2') self.assertEqual(filtered, [second]) filtered = executor._filter_migrations(reversed(migrations), True, '1') self.assertEqual(filtered, [first])
def test_filter_migrations(self): connection = mock.Mock() executor = migration_executor.MigrationExecutor( connection, self.TEST_MIGRATIONS_DIR ) first = migration.Migration("1", None, "1") second = migration.Migration("2", "1", "2") third = migration.Migration("3", "2", "3") migrations = [first, second, third] migrated = {"1": True, "2": False, "3": False} with mock.patch.object(executor, "_migration_status_map", migrated): filtered = executor._filter_migrations(migrations, False, None) self.assertEqual(filtered, [second, third]) filtered = executor._filter_migrations(migrations, False, "2") self.assertEqual(filtered, [second]) filtered = executor._filter_migrations(reversed(migrations), True, "1") self.assertEqual(filtered, [first])
def test_validate_migrations_error_on_unmigrated_after_migrated(self): connection = mock.Mock() executor = migration_executor.MigrationExecutor( connection, self.TEST_MIGRATIONS_DIR ) first = migration.Migration("1", None, "1") second = migration.Migration("2", "1", "2") third = migration.Migration("3", "2", "3") with mock.patch.object(executor, "migrations") as migrations: migrations.return_value = [first, second, third] migrated = {"1": False, "2": True, "3": False} with mock.patch.object(executor, "_migration_status_map", migrated): with self.assertRaises(error.SpannerError): executor._validate_migrations() migrated = {"1": False, "2": False, "3": True} with mock.patch.object(executor, "_migration_status_map", migrated): with self.assertRaises(error.SpannerError): executor._validate_migrations()
def test_validate_migrations_error_on_unmigrated_after_migrated(self): connection = mock.Mock() executor = migration_executor.MigrationExecutor(connection) first = migration.Migration('1', None) second = migration.Migration('2', '1') third = migration.Migration('3', '2') with mock.patch.object(executor, 'migrations') as migrations: migrations.return_value = [first, second, third] migrated = {'1': False, '2': True, '3': False} with mock.patch.object(executor, '_migration_status_map', migrated): with self.assertRaises(error.SpannerError): executor._validate_migrations() migrated = {'1': False, '2': False, '3': True} with mock.patch.object(executor, '_migration_status_map', migrated): with self.assertRaises(error.SpannerError): executor._validate_migrations()
def _migration_from_file(self, filename: str) -> migration.Migration: """Loads a single migration from the given filename in the base dir.""" module_name = re.sub(r'\W', '_', filename) path = os.path.join(self.basedir, filename) spec = importlib.util.spec_from_file_location(module_name, path) module = importlib.util.module_from_spec(spec) spec.loader.exec_module(module) try: result = migration.Migration(module.migration_id, module.prev_migration_id, getattr(module, 'upgrade', None), getattr(module, 'downgrade', None)) except AttributeError: raise error.SpannerError('{} has no migration id'.format(path)) return result
def test_validate_migrations_error_on_unmigrated_first(self): connection = mock.Mock() executor = migration_executor.MigrationExecutor(connection) first = migration.Migration('2', '1') with mock.patch.object(executor, 'migrations') as migrations: migrations.return_value = [first] migrated = {'1': False} with mock.patch.object(executor, '_migration_status_map', migrated): with self.assertRaises(error.SpannerError): executor._validate_migrations() migrated = {} with mock.patch.object(executor, '_migration_status_map', migrated): with self.assertRaises(error.SpannerError): executor._validate_migrations()