diff options
| author | Simon Charette <charette.s@gmail.com> | 2017-01-30 13:43:20 -0500 |
|---|---|---|
| committer | Tim Graham <timograham@gmail.com> | 2018-07-11 10:49:50 -0400 |
| commit | a97845a823c86b1d6e65af70fbce64e6e747e081 (patch) | |
| tree | 5fc2832f178a9aefb945f13b28239aa37dd1a46f /tests | |
| parent | d3a935f01f6cb36d21b09d81c5f022a3a5116ab0 (diff) | |
Fixed #27768 -- Allowed migration optimization of CreateModel order.
Thanks Ed Morley from Mozilla for the tests.
Diffstat (limited to 'tests')
| -rw-r--r-- | tests/migrations/test_autodetector.py | 18 | ||||
| -rw-r--r-- | tests/migrations/test_optimizer.py | 87 |
2 files changed, 89 insertions, 16 deletions
diff --git a/tests/migrations/test_autodetector.py b/tests/migrations/test_autodetector.py index 5ad32e610c..34c9dac989 100644 --- a/tests/migrations/test_autodetector.py +++ b/tests/migrations/test_autodetector.py @@ -1150,10 +1150,9 @@ class AutodetectorTests(TestCase): changes = self.get_changes([], [self.author_with_publisher, self.publisher]) # Right number/type of migrations? self.assertNumberMigrations(changes, 'testapp', 1) - self.assertOperationTypes(changes, 'testapp', 0, ["CreateModel", "CreateModel", "AddField"]) - self.assertOperationAttributes(changes, "testapp", 0, 0, name="Author") - self.assertOperationAttributes(changes, "testapp", 0, 1, name="Publisher") - self.assertOperationAttributes(changes, "testapp", 0, 2, name="publisher") + self.assertOperationTypes(changes, 'testapp', 0, ["CreateModel", "CreateModel"]) + self.assertOperationAttributes(changes, "testapp", 0, 0, name="Publisher") + self.assertOperationAttributes(changes, "testapp", 0, 1, name="Author") self.assertMigrationDependencies(changes, 'testapp', 0, []) def test_circular_fk_dependency(self): @@ -1907,13 +1906,12 @@ class AutodetectorTests(TestCase): # Right number/type of migrations? self.assertNumberMigrations(changes, "testapp", 1) self.assertOperationTypes(changes, "testapp", 0, [ - "CreateModel", "CreateModel", "CreateModel", "AddField", "AddField" + 'CreateModel', 'CreateModel', 'CreateModel', 'AddField', ]) - self.assertOperationAttributes(changes, 'testapp', 0, 0, name="Author") - self.assertOperationAttributes(changes, 'testapp', 0, 1, name="Contract") - self.assertOperationAttributes(changes, 'testapp', 0, 2, name="Publisher") - self.assertOperationAttributes(changes, 'testapp', 0, 3, model_name='contract', name='publisher') - self.assertOperationAttributes(changes, 'testapp', 0, 4, model_name='author', name='publishers') + self.assertOperationAttributes(changes, 'testapp', 0, 0, name='Author') + self.assertOperationAttributes(changes, 'testapp', 0, 1, name='Publisher') + self.assertOperationAttributes(changes, 'testapp', 0, 2, name='Contract') + self.assertOperationAttributes(changes, 'testapp', 0, 3, model_name='author', name='publishers') def test_many_to_many_removed_before_through_model(self): """ diff --git a/tests/migrations/test_optimizer.py b/tests/migrations/test_optimizer.py index 7a1876a508..6c1c5f5c6b 100644 --- a/tests/migrations/test_optimizer.py +++ b/tests/migrations/test_optimizer.py @@ -300,16 +300,91 @@ class OptimizerTests(SimpleTestCase): ], ) - def test_create_model_add_field_not_through_fk(self): + def test_create_model_reordering(self): """ - AddField should NOT optimize into CreateModel if it's an FK to a model - that's between them. + AddField optimizes into CreateModel if it's a FK to a model that's + between them (and there's no FK in the other direction), by changing + the order of the CreateModel operations. + """ + self.assertOptimizesTo( + [ + migrations.CreateModel('Foo', [('name', models.CharField(max_length=255))]), + migrations.CreateModel('Link', [('url', models.TextField())]), + migrations.AddField('Foo', 'link', models.ForeignKey('migrations.Link', models.CASCADE)), + ], + [ + migrations.CreateModel('Link', [('url', models.TextField())]), + migrations.CreateModel('Foo', [ + ('name', models.CharField(max_length=255)), + ('link', models.ForeignKey('migrations.Link', models.CASCADE)) + ]), + ], + ) + + def test_create_model_reordering_circular_fk(self): + """ + CreateModel reordering behavior doesn't result in an infinite loop if + there are FKs in both directions. + """ + self.assertOptimizesTo( + [ + migrations.CreateModel('Bar', [('url', models.TextField())]), + migrations.CreateModel('Foo', [('name', models.CharField(max_length=255))]), + migrations.AddField('Bar', 'foo_fk', models.ForeignKey('migrations.Foo', models.CASCADE)), + migrations.AddField('Foo', 'bar_fk', models.ForeignKey('migrations.Bar', models.CASCADE)), + ], + [ + migrations.CreateModel('Foo', [('name', models.CharField(max_length=255))]), + migrations.CreateModel('Bar', [ + ('url', models.TextField()), + ('foo_fk', models.ForeignKey('migrations.Foo', models.CASCADE)), + ]), + migrations.AddField('Foo', 'bar_fk', models.ForeignKey('migrations.Foo', models.CASCADE)), + ], + ) + + def test_create_model_no_reordering_for_unrelated_fk(self): + """ + CreateModel order remains unchanged if the later AddField operation + isn't a FK between them. """ self.assertDoesNotOptimize( [ - migrations.CreateModel("Foo", [("name", models.CharField(max_length=255))]), - migrations.CreateModel("Link", [("url", models.TextField())]), - migrations.AddField("Foo", "link", models.ForeignKey("migrations.Link", models.CASCADE)), + migrations.CreateModel('Foo', [('name', models.CharField(max_length=255))]), + migrations.CreateModel('Link', [('url', models.TextField())]), + migrations.AddField('Other', 'link', models.ForeignKey('migrations.Link', models.CASCADE)), + ], + ) + + def test_create_model_no_reordering_of_inherited_model(self): + """ + A CreateModel that inherits from another isn't reordered to avoid + moving it earlier than its parent CreateModel operation. + """ + self.assertOptimizesTo( + [ + migrations.CreateModel('Other', [('foo', models.CharField(max_length=255))]), + migrations.CreateModel('ParentModel', [('bar', models.CharField(max_length=255))]), + migrations.CreateModel( + 'ChildModel', + [('baz', models.CharField(max_length=255))], + bases=('migrations.parentmodel',), + ), + migrations.AddField('Other', 'fk', models.ForeignKey('migrations.ChildModel', models.CASCADE)), + ], + [ + migrations.CreateModel('ParentModel', [('bar', models.CharField(max_length=255))]), + migrations.CreateModel( + 'ChildModel', + [('baz', models.CharField(max_length=255))], + bases=('migrations.parentmodel',), + ), + migrations.CreateModel( + 'Other', [ + ('foo', models.CharField(max_length=255)), + ('fk', models.ForeignKey('migrations.ChildModel', models.CASCADE)), + ] + ), ], ) |
