2013-09-06 04:51:31 +08:00
|
|
|
from unittest import skipIf
|
|
|
|
|
2013-12-23 23:01:13 +08:00
|
|
|
from django.test import TestCase, override_settings
|
2014-04-30 22:53:20 +08:00
|
|
|
from django.db import connection, connections
|
2013-07-23 02:43:58 +08:00
|
|
|
from django.db.migrations.loader import MigrationLoader, AmbiguityError
|
2013-05-18 19:49:56 +08:00
|
|
|
from django.db.migrations.recorder import MigrationRecorder
|
2014-06-17 03:59:24 +08:00
|
|
|
from django.test import modify_settings
|
2013-09-06 04:51:31 +08:00
|
|
|
from django.utils import six
|
2013-05-18 19:49:56 +08:00
|
|
|
|
|
|
|
|
|
|
|
class RecorderTests(TestCase):
|
|
|
|
"""
|
2013-05-30 00:47:10 +08:00
|
|
|
Tests recording migrations as applied or not.
|
2013-05-18 19:49:56 +08:00
|
|
|
"""
|
|
|
|
|
|
|
|
def test_apply(self):
|
|
|
|
"""
|
|
|
|
Tests marking migrations as applied/unapplied.
|
|
|
|
"""
|
|
|
|
recorder = MigrationRecorder(connection)
|
|
|
|
self.assertEqual(
|
2014-05-30 07:43:49 +08:00
|
|
|
set((x, y) for (x, y) in recorder.applied_migrations() if x == "myapp"),
|
2013-05-18 19:49:56 +08:00
|
|
|
set(),
|
|
|
|
)
|
|
|
|
recorder.record_applied("myapp", "0432_ponies")
|
|
|
|
self.assertEqual(
|
2014-05-30 07:43:49 +08:00
|
|
|
set((x, y) for (x, y) in recorder.applied_migrations() if x == "myapp"),
|
2013-05-18 19:49:56 +08:00
|
|
|
set([("myapp", "0432_ponies")]),
|
|
|
|
)
|
2014-04-30 22:53:20 +08:00
|
|
|
# That should not affect records of another database
|
|
|
|
recorder_other = MigrationRecorder(connections['other'])
|
|
|
|
self.assertEqual(
|
2014-05-30 07:43:49 +08:00
|
|
|
set((x, y) for (x, y) in recorder_other.applied_migrations() if x == "myapp"),
|
2014-04-30 22:53:20 +08:00
|
|
|
set(),
|
|
|
|
)
|
2013-05-18 19:49:56 +08:00
|
|
|
recorder.record_unapplied("myapp", "0432_ponies")
|
|
|
|
self.assertEqual(
|
2014-05-30 07:43:49 +08:00
|
|
|
set((x, y) for (x, y) in recorder.applied_migrations() if x == "myapp"),
|
2013-05-18 19:49:56 +08:00
|
|
|
set(),
|
|
|
|
)
|
2013-05-30 00:47:10 +08:00
|
|
|
|
|
|
|
|
2013-06-19 22:36:02 +08:00
|
|
|
class LoaderTests(TestCase):
|
2013-05-30 00:47:10 +08:00
|
|
|
"""
|
|
|
|
Tests the disk and database loader, and running through migrations
|
|
|
|
in memory.
|
|
|
|
"""
|
|
|
|
|
2013-06-19 22:36:02 +08:00
|
|
|
@override_settings(MIGRATION_MODULES={"migrations": "migrations.test_migrations"})
|
2014-06-17 03:59:24 +08:00
|
|
|
@modify_settings(INSTALLED_APPS={'append': 'basic'})
|
2013-05-30 00:47:10 +08:00
|
|
|
def test_load(self):
|
|
|
|
"""
|
|
|
|
Makes sure the loader can load the migrations for the test apps,
|
2013-12-24 19:25:17 +08:00
|
|
|
and then render them out to a new Apps.
|
2013-05-30 00:47:10 +08:00
|
|
|
"""
|
|
|
|
# Load and test the plan
|
|
|
|
migration_loader = MigrationLoader(connection)
|
|
|
|
self.assertEqual(
|
|
|
|
migration_loader.graph.forwards_plan(("migrations", "0002_second")),
|
2014-01-08 21:00:12 +08:00
|
|
|
[
|
|
|
|
("migrations", "0001_initial"),
|
|
|
|
("migrations", "0002_second"),
|
|
|
|
],
|
2013-05-30 00:47:10 +08:00
|
|
|
)
|
|
|
|
# Now render it out!
|
2014-05-01 03:25:12 +08:00
|
|
|
project_state = migration_loader.project_state(("migrations", "0002_second"))
|
2013-05-30 00:47:10 +08:00
|
|
|
self.assertEqual(len(project_state.models), 2)
|
|
|
|
|
|
|
|
author_state = project_state.models["migrations", "author"]
|
|
|
|
self.assertEqual(
|
|
|
|
[x for x, y in author_state.fields],
|
2013-05-31 01:08:58 +08:00
|
|
|
["id", "name", "slug", "age", "rating"]
|
2013-05-30 00:47:10 +08:00
|
|
|
)
|
|
|
|
|
|
|
|
book_state = project_state.models["migrations", "book"]
|
|
|
|
self.assertEqual(
|
|
|
|
[x for x, y in book_state.fields],
|
|
|
|
["id", "author"]
|
|
|
|
)
|
2013-07-23 02:43:58 +08:00
|
|
|
|
2014-05-01 03:25:12 +08:00
|
|
|
# Ensure we've included unmigrated apps in there too
|
2014-06-17 03:59:24 +08:00
|
|
|
self.assertIn("basic", project_state.real_apps)
|
2014-05-01 03:25:12 +08:00
|
|
|
|
2014-01-08 21:00:12 +08:00
|
|
|
@override_settings(MIGRATION_MODULES={"migrations": "migrations.test_migrations_unmigdep"})
|
|
|
|
def test_load_unmigrated_dependency(self):
|
|
|
|
"""
|
|
|
|
Makes sure the loader can load migrations with a dependency on an unmigrated app.
|
|
|
|
"""
|
|
|
|
# Load and test the plan
|
|
|
|
migration_loader = MigrationLoader(connection)
|
|
|
|
self.assertEqual(
|
|
|
|
migration_loader.graph.forwards_plan(("migrations", "0001_initial")),
|
|
|
|
[
|
2014-06-17 06:49:37 +08:00
|
|
|
('contenttypes', '0001_initial'),
|
|
|
|
('auth', '0001_initial'),
|
2014-01-08 21:00:12 +08:00
|
|
|
("migrations", "0001_initial"),
|
|
|
|
],
|
|
|
|
)
|
|
|
|
# Now render it out!
|
2014-05-01 03:25:12 +08:00
|
|
|
project_state = migration_loader.project_state(("migrations", "0001_initial"))
|
2014-01-09 05:20:29 +08:00
|
|
|
self.assertEqual(len([m for a, m in project_state.models if a == "migrations"]), 1)
|
2014-01-08 21:00:12 +08:00
|
|
|
|
|
|
|
book_state = project_state.models["migrations", "book"]
|
|
|
|
self.assertEqual(
|
|
|
|
[x for x, y in book_state.fields],
|
|
|
|
["id", "user"]
|
|
|
|
)
|
|
|
|
|
2014-05-29 18:30:47 +08:00
|
|
|
@override_settings(MIGRATION_MODULES={"migrations": "migrations.test_migrations_run_before"})
|
|
|
|
def test_run_before(self):
|
|
|
|
"""
|
|
|
|
Makes sure the loader uses Migration.run_before.
|
|
|
|
"""
|
|
|
|
# Load and test the plan
|
|
|
|
migration_loader = MigrationLoader(connection)
|
|
|
|
self.assertEqual(
|
|
|
|
migration_loader.graph.forwards_plan(("migrations", "0002_second")),
|
|
|
|
[
|
|
|
|
("migrations", "0001_initial"),
|
|
|
|
("migrations", "0003_third"),
|
|
|
|
("migrations", "0002_second"),
|
|
|
|
],
|
|
|
|
)
|
|
|
|
|
2014-06-18 13:12:31 +08:00
|
|
|
@modify_settings(INSTALLED_APPS={'append': 'basic'})
|
|
|
|
@override_settings(MIGRATION_MODULES={
|
|
|
|
"migrations": "migrations.test_migrations_latest",
|
|
|
|
"basic": "migrations.test_migrations_latest_basic",
|
|
|
|
})
|
|
|
|
def test_latest(self):
|
|
|
|
"""
|
|
|
|
Makes sure that __latest__ works correctly.
|
|
|
|
"""
|
|
|
|
# Load and test the plan
|
|
|
|
migration_loader = MigrationLoader(connection)
|
|
|
|
self.assertEqual(
|
|
|
|
migration_loader.graph.forwards_plan(("migrations", "0001_initial")),
|
|
|
|
[
|
|
|
|
("basic", "0001_initial"),
|
|
|
|
("basic", "0002_second"),
|
|
|
|
("migrations", "0001_initial"),
|
|
|
|
],
|
|
|
|
)
|
|
|
|
|
2014-06-18 14:27:03 +08:00
|
|
|
@override_settings(MIGRATION_MODULES={
|
|
|
|
"migrations": "migrations.test_migrations_first",
|
|
|
|
"migrations2": "migrations2.test_migrations_2_first",
|
|
|
|
})
|
|
|
|
@modify_settings(INSTALLED_APPS={'append': 'migrations2'})
|
|
|
|
def test_first(self):
|
|
|
|
"""
|
|
|
|
Makes sure the '__first__' migrations build correctly.
|
|
|
|
"""
|
|
|
|
migration_loader = MigrationLoader(connection)
|
|
|
|
self.assertEqual(
|
|
|
|
migration_loader.graph.forwards_plan(("migrations", "second")),
|
|
|
|
[
|
|
|
|
("migrations", "thefirst"),
|
|
|
|
("migrations2", "0001_initial"),
|
|
|
|
("migrations2", "0002_second"),
|
|
|
|
("migrations", "second"),
|
|
|
|
],
|
|
|
|
)
|
|
|
|
|
2013-07-23 02:43:58 +08:00
|
|
|
@override_settings(MIGRATION_MODULES={"migrations": "migrations.test_migrations"})
|
|
|
|
def test_name_match(self):
|
|
|
|
"Tests prefix name matching"
|
|
|
|
migration_loader = MigrationLoader(connection)
|
|
|
|
self.assertEqual(
|
|
|
|
migration_loader.get_migration_by_prefix("migrations", "0001").name,
|
|
|
|
"0001_initial",
|
|
|
|
)
|
|
|
|
with self.assertRaises(AmbiguityError):
|
|
|
|
migration_loader.get_migration_by_prefix("migrations", "0")
|
|
|
|
with self.assertRaises(KeyError):
|
|
|
|
migration_loader.get_migration_by_prefix("migrations", "blarg")
|
2013-09-06 04:51:11 +08:00
|
|
|
|
|
|
|
def test_load_import_error(self):
|
|
|
|
with override_settings(MIGRATION_MODULES={"migrations": "migrations.faulty_migrations.import_error"}):
|
|
|
|
with self.assertRaises(ImportError):
|
2013-10-24 05:56:54 +08:00
|
|
|
MigrationLoader(connection)
|
2013-09-06 04:51:31 +08:00
|
|
|
|
|
|
|
def test_load_module_file(self):
|
|
|
|
with override_settings(MIGRATION_MODULES={"migrations": "migrations.faulty_migrations.file"}):
|
2013-10-24 05:56:54 +08:00
|
|
|
MigrationLoader(connection)
|
2013-09-06 04:51:31 +08:00
|
|
|
|
|
|
|
@skipIf(six.PY2, "PY2 doesn't load empty dirs.")
|
|
|
|
def test_load_empty_dir(self):
|
|
|
|
with override_settings(MIGRATION_MODULES={"migrations": "migrations.faulty_migrations.namespace"}):
|
2013-10-24 05:56:54 +08:00
|
|
|
MigrationLoader(connection)
|
|
|
|
|
|
|
|
@override_settings(MIGRATION_MODULES={"migrations": "migrations.test_migrations_squashed"})
|
|
|
|
def test_loading_squashed(self):
|
|
|
|
"Tests loading a squashed migration"
|
|
|
|
migration_loader = MigrationLoader(connection)
|
|
|
|
recorder = MigrationRecorder(connection)
|
|
|
|
# Loading with nothing applied should just give us the one node
|
|
|
|
self.assertEqual(
|
2014-05-30 07:43:49 +08:00
|
|
|
len([x for x in migration_loader.graph.nodes if x[0] == "migrations"]),
|
2013-10-24 05:56:54 +08:00
|
|
|
1,
|
|
|
|
)
|
|
|
|
# However, fake-apply one migration and it should now use the old two
|
|
|
|
recorder.record_applied("migrations", "0001_initial")
|
|
|
|
migration_loader.build_graph()
|
|
|
|
self.assertEqual(
|
2014-05-30 07:43:49 +08:00
|
|
|
len([x for x in migration_loader.graph.nodes if x[0] == "migrations"]),
|
2013-10-24 05:56:54 +08:00
|
|
|
2,
|
|
|
|
)
|
|
|
|
recorder.flush()
|