1
0
mirror of https://github.com/django/django.git synced 2025-10-24 06:06:09 +00:00

Fixed #29721 -- Ensured migrations are applied and recorded atomically.

This commit is contained in:
Sanyam Khurana
2018-10-24 23:32:33 +05:30
committed by Tim Graham
parent 32da3cfdf9
commit c86a3d80a2
2 changed files with 32 additions and 5 deletions

View File

@@ -1,3 +1,5 @@
from unittest import mock
from django.apps.registry import apps as global_apps
from django.db import connection
from django.db.migrations.exceptions import InvalidMigrationPlan
@@ -5,7 +7,9 @@ from django.db.migrations.executor import MigrationExecutor
from django.db.migrations.graph import MigrationGraph
from django.db.migrations.recorder import MigrationRecorder
from django.db.utils import DatabaseError
from django.test import TestCase, modify_settings, override_settings
from django.test import (
TestCase, modify_settings, override_settings, skipUnlessDBFeature,
)
from .test_base import MigrationTestBase
@@ -649,6 +653,22 @@ class ExecutorTests(MigrationTestBase):
recorder.applied_migrations(),
)
# When the feature is False, the operation and the record won't be
# performed in a transaction and the test will systematically pass.
@skipUnlessDBFeature('can_rollback_ddl')
@override_settings(MIGRATION_MODULES={'migrations': 'migrations.test_migrations'})
def test_migrations_applied_and_recorded_atomically(self):
"""Migrations are applied and recorded atomically."""
executor = MigrationExecutor(connection)
with mock.patch('django.db.migrations.executor.MigrationExecutor.record_migration') as record_migration:
record_migration.side_effect = RuntimeError('Recording migration failed.')
with self.assertRaisesMessage(RuntimeError, 'Recording migration failed.'):
executor.migrate([('migrations', '0001_initial')])
# The migration isn't recorded as applied since it failed.
migration_recorder = MigrationRecorder(connection)
self.assertFalse(migration_recorder.migration_qs.filter(app='migrations', name='0001_initial').exists())
self.assertTableNotExists('migrations_author')
class FakeLoader:
def __init__(self, graph, applied):