summaryrefslogtreecommitdiff
path: root/tests/migrations/test_executor.py
diff options
context:
space:
mode:
Diffstat (limited to 'tests/migrations/test_executor.py')
-rw-r--r--tests/migrations/test_executor.py59
1 files changed, 59 insertions, 0 deletions
diff --git a/tests/migrations/test_executor.py b/tests/migrations/test_executor.py
index 12bdabb172..32cdc5e09c 100644
--- a/tests/migrations/test_executor.py
+++ b/tests/migrations/test_executor.py
@@ -1,5 +1,6 @@
from django.apps.registry import apps as global_apps
from django.db import connection
+from django.db.migrations.exceptions import InvalidMigrationPlan
from django.db.migrations.executor import MigrationExecutor
from django.db.migrations.graph import MigrationGraph
from django.db.migrations.recorder import MigrationRecorder
@@ -145,6 +146,64 @@ class ExecutorTests(MigrationTestBase):
executor.recorder.record_unapplied("migrations", "0002_second")
executor.recorder.record_unapplied("migrations", "0001_initial")
+ @override_settings(MIGRATION_MODULES={
+ "migrations": "migrations.test_migrations",
+ "migrations2": "migrations2.test_migrations_2_no_deps",
+ })
+ def test_mixed_plan_not_supported(self):
+ """
+ Although the MigrationExecutor interfaces allows for mixed migration
+ plans (combined forwards and backwards migrations) this is not
+ supported.
+ """
+ # Prepare for mixed plan
+ executor = MigrationExecutor(connection)
+ plan = executor.migration_plan([("migrations", "0002_second")])
+ self.assertEqual(
+ plan,
+ [
+ (executor.loader.graph.nodes["migrations", "0001_initial"], False),
+ (executor.loader.graph.nodes["migrations", "0002_second"], False),
+ ],
+ )
+ executor.migrate(None, plan)
+ # Rebuild the graph to reflect the new DB state
+ executor.loader.build_graph()
+ self.assertIn(('migrations', '0001_initial'), executor.loader.applied_migrations)
+ self.assertIn(('migrations', '0002_second'), executor.loader.applied_migrations)
+ self.assertNotIn(('migrations2', '0001_initial'), executor.loader.applied_migrations)
+
+ # Generate mixed plan
+ plan = executor.migration_plan([
+ ("migrations", None),
+ ("migrations2", "0001_initial"),
+ ])
+ msg = (
+ 'Migration plans with both forwards and backwards migrations are '
+ 'not supported. Please split your migration process into separate '
+ 'plans of only forwards OR backwards migrations.'
+ )
+ with self.assertRaisesMessage(InvalidMigrationPlan, msg) as cm:
+ executor.migrate(None, plan)
+ self.assertEqual(
+ cm.exception.args[1],
+ [
+ (executor.loader.graph.nodes["migrations", "0002_second"], True),
+ (executor.loader.graph.nodes["migrations", "0001_initial"], True),
+ (executor.loader.graph.nodes["migrations2", "0001_initial"], False),
+ ],
+ )
+ # Rebuild the graph to reflect the new DB state
+ executor.loader.build_graph()
+ executor.migrate([
+ ("migrations", None),
+ ("migrations2", None),
+ ])
+ # Are the tables gone?
+ self.assertTableNotExists("migrations_author")
+ self.assertTableNotExists("migrations_book")
+ self.assertTableNotExists("migrations2_otherauthor")
+
@override_settings(MIGRATION_MODULES={"migrations": "migrations.test_migrations"})
def test_soft_apply(self):
"""