summaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
authorPankrat <lhaehne@gmail.com>2016-01-30 21:46:28 +0100
committerTim Graham <timograham@gmail.com>2016-02-05 09:09:05 -0500
commitf91a04621ea8d7a657ff755645d823026257e898 (patch)
tree2b06f3ce1cbb8e5f04499838154cf715ff76ce5b /tests
parent0edb8a146fd6c60f4c3b1ad0a4a89963962f22af (diff)
Fixed #25833 -- Added support for non-atomic migrations.
Added the Migration.atomic attribute which can be set to False for non-atomic migrations.
Diffstat (limited to 'tests')
-rw-r--r--tests/migrations/test_commands.py13
-rw-r--r--tests/migrations/test_executor.py27
-rw-r--r--tests/migrations/test_migrations_atomic_operation/0001_initial.py25
-rw-r--r--tests/migrations/test_migrations_atomic_operation/__init__.py0
-rw-r--r--tests/migrations/test_migrations_non_atomic/0001_initial.py32
-rw-r--r--tests/migrations/test_migrations_non_atomic/__init__.py0
6 files changed, 97 insertions, 0 deletions
diff --git a/tests/migrations/test_commands.py b/tests/migrations/test_commands.py
index 4eb96de2e9..68fa658d76 100644
--- a/tests/migrations/test_commands.py
+++ b/tests/migrations/test_commands.py
@@ -362,6 +362,19 @@ class MigrateTests(MigrationTestBase):
# Cleanup by unmigrating everything
call_command("migrate", "migrations", "zero", verbosity=0)
+ @override_settings(MIGRATION_MODULES={"migrations": "migrations.test_migrations_non_atomic"})
+ def test_sqlmigrate_for_non_atomic_migration(self):
+ """
+ Transaction wrappers aren't shown for non-atomic migrations.
+ """
+ out = six.StringIO()
+ call_command("sqlmigrate", "migrations", "0001", stdout=out)
+ output = out.getvalue().lower()
+ queries = [q.strip() for q in output.splitlines()]
+ if connection.ops.start_transaction_sql():
+ self.assertNotIn(connection.ops.start_transaction_sql().lower(), queries)
+ self.assertNotIn(connection.ops.end_transaction_sql().lower(), queries)
+
@override_settings(
INSTALLED_APPS=[
"migrations.migrations_test_apps.migrated_app",
diff --git a/tests/migrations/test_executor.py b/tests/migrations/test_executor.py
index 1bbed48e3c..b51e7be90e 100644
--- a/tests/migrations/test_executor.py
+++ b/tests/migrations/test_executor.py
@@ -100,6 +100,33 @@ class ExecutorTests(MigrationTestBase):
self.assertTableNotExists("migrations_author")
self.assertTableNotExists("migrations_book")
+ @override_settings(MIGRATION_MODULES={"migrations": "migrations.test_migrations_non_atomic"})
+ def test_non_atomic_migration(self):
+ """
+ Applying a non-atomic migration works as expected.
+ """
+ executor = MigrationExecutor(connection)
+ with self.assertRaisesMessage(RuntimeError, "Abort migration"):
+ executor.migrate([("migrations", "0001_initial")])
+ self.assertTableExists("migrations_publisher")
+ migrations_apps = executor.loader.project_state(("migrations", "0001_initial")).apps
+ Publisher = migrations_apps.get_model("migrations", "Publisher")
+ self.assertTrue(Publisher.objects.exists())
+ self.assertTableNotExists("migrations_book")
+
+ @override_settings(MIGRATION_MODULES={"migrations": "migrations.test_migrations_atomic_operation"})
+ def test_atomic_operation_in_non_atomic_migration(self):
+ """
+ An atomic operation is properly rolled back inside a non-atomic
+ migration.
+ """
+ executor = MigrationExecutor(connection)
+ with self.assertRaisesMessage(RuntimeError, "Abort migration"):
+ executor.migrate([("migrations", "0001_initial")])
+ migrations_apps = executor.loader.project_state(("migrations", "0001_initial")).apps
+ Editor = migrations_apps.get_model("migrations", "Editor")
+ self.assertFalse(Editor.objects.exists())
+
@override_settings(MIGRATION_MODULES={
"migrations": "migrations.test_migrations",
"migrations2": "migrations2.test_migrations_2",
diff --git a/tests/migrations/test_migrations_atomic_operation/0001_initial.py b/tests/migrations/test_migrations_atomic_operation/0001_initial.py
new file mode 100644
index 0000000000..11bd2f7ce2
--- /dev/null
+++ b/tests/migrations/test_migrations_atomic_operation/0001_initial.py
@@ -0,0 +1,25 @@
+# -*- coding: utf-8 -*-
+from __future__ import unicode_literals
+
+from django.db import migrations, models
+
+
+def raise_error(apps, schema_editor):
+ # Test atomic operation in non-atomic migration is wrapped in transaction
+ Editor = apps.get_model('migrations', 'Editor')
+ Editor.objects.create(name='Test Editor')
+ raise RuntimeError('Abort migration')
+
+
+class Migration(migrations.Migration):
+ atomic = False
+
+ operations = [
+ migrations.CreateModel(
+ "Editor",
+ [
+ ("name", models.CharField(primary_key=True, max_length=255)),
+ ],
+ ),
+ migrations.RunPython(raise_error, atomic=True),
+ ]
diff --git a/tests/migrations/test_migrations_atomic_operation/__init__.py b/tests/migrations/test_migrations_atomic_operation/__init__.py
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/tests/migrations/test_migrations_atomic_operation/__init__.py
diff --git a/tests/migrations/test_migrations_non_atomic/0001_initial.py b/tests/migrations/test_migrations_non_atomic/0001_initial.py
new file mode 100644
index 0000000000..47a03a16f9
--- /dev/null
+++ b/tests/migrations/test_migrations_non_atomic/0001_initial.py
@@ -0,0 +1,32 @@
+# -*- coding: utf-8 -*-
+from __future__ import unicode_literals
+
+from django.db import migrations, models
+
+
+def raise_error(apps, schema_editor):
+ # Test operation in non-atomic migration is not wrapped in transaction
+ Publisher = apps.get_model('migrations', 'Publisher')
+ Publisher.objects.create(name='Test Publisher')
+ raise RuntimeError('Abort migration')
+
+
+class Migration(migrations.Migration):
+ atomic = False
+
+ operations = [
+ migrations.CreateModel(
+ "Publisher",
+ [
+ ("name", models.CharField(primary_key=True, max_length=255)),
+ ],
+ ),
+ migrations.RunPython(raise_error),
+ migrations.CreateModel(
+ "Book",
+ [
+ ("title", models.CharField(primary_key=True, max_length=255)),
+ ("publisher", models.ForeignKey("migrations.Publisher", models.SET_NULL, null=True)),
+ ],
+ ),
+ ]
diff --git a/tests/migrations/test_migrations_non_atomic/__init__.py b/tests/migrations/test_migrations_non_atomic/__init__.py
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/tests/migrations/test_migrations_non_atomic/__init__.py