Added south app.
[wolnelektury.git] / apps / south / tests / logic.py
diff --git a/apps/south/tests/logic.py b/apps/south/tests/logic.py
new file mode 100644 (file)
index 0000000..dfb441e
--- /dev/null
@@ -0,0 +1,253 @@
+import unittest
+import datetime
+import sys
+import os
+
+from south import migration
+
+# Add the tests directory so fakeapp is on sys.path
+test_root = os.path.dirname(__file__)
+sys.path.append(test_root)
+
+
+class TestMigrationLogic(unittest.TestCase):
+
+    """
+    Tests if the various logic functions in migration actually work.
+    """
+
+    def create_fake_app(self, name):
+        
+        class Fake:
+            pass
+        
+        fake = Fake()
+        fake.__name__ = name
+        return fake
+
+
+    def create_test_app(self):
+        
+        class Fake:
+            pass
+        
+        fake = Fake()
+        fake.__name__ = "fakeapp.migrations"
+        fake.__file__ = os.path.join(test_root, "fakeapp", "migrations", "__init__.py")
+        return fake
+    
+    
+    def monkeypatch(self):
+        """Swaps out various Django calls for fake ones for our own nefarious purposes."""
+        
+        def new_get_apps():
+            return ['fakeapp']
+        
+        from django.db import models
+        from django.conf import settings
+        models.get_apps_old, models.get_apps = models.get_apps, new_get_apps
+        settings.INSTALLED_APPS, settings.OLD_INSTALLED_APPS = (
+            ["fakeapp"],
+            settings.INSTALLED_APPS,
+        )
+        self.redo_app_cache()
+    setUp = monkeypatch
+    
+    
+    def unmonkeypatch(self):
+        """Undoes what monkeypatch did."""
+        
+        from django.db import models
+        from django.conf import settings
+        models.get_apps = models.get_apps_old
+        settings.INSTALLED_APPS = settings.OLD_INSTALLED_APPS
+        self.redo_app_cache()
+    tearDown = unmonkeypatch
+    
+    
+    def redo_app_cache(self):
+        from django.db.models.loading import AppCache
+        a = AppCache()
+        a.loaded = False
+        a._populate()
+    
+
+    def test_get_app_name(self):
+        self.assertEqual(
+            "southtest",
+            migration.get_app_name(self.create_fake_app("southtest.migrations")),
+        )
+        self.assertEqual(
+            "baz",
+            migration.get_app_name(self.create_fake_app("foo.bar.baz.migrations")),
+        )
+    
+    
+    def test_get_migrated_apps(self):
+        
+        P1 = __import__("fakeapp.migrations", {}, {}, [''])
+        
+        self.assertEqual(
+            [P1],
+            list(migration.get_migrated_apps()),
+        )
+    
+    
+    def test_get_app(self):
+        
+        P1 = __import__("fakeapp.migrations", {}, {}, [''])
+        
+        self.assertEqual(P1, migration.get_app("fakeapp"))
+        self.assertEqual(P1, migration.get_app(self.create_fake_app("fakeapp.models")))
+    
+    
+    def test_get_app_fullname(self):
+        self.assertEqual(
+            "southtest",
+            migration.get_app_fullname(self.create_fake_app("southtest.migrations")),
+        )
+        self.assertEqual(
+            "foo.bar.baz",
+            migration.get_app_fullname(self.create_fake_app("foo.bar.baz.migrations")),
+        )
+    
+    
+    def test_get_migration_names(self):
+        
+        app = self.create_test_app()
+        
+        self.assertEqual(
+            ["0001_spam", "0002_eggs"],
+            migration.get_migration_names(app),
+        )
+    
+    
+    def test_get_migration_classes(self):
+        
+        app = self.create_test_app()
+        
+        # Can't use vanilla import, modules beginning with numbers aren't in grammar
+        M1 = __import__("fakeapp.migrations.0001_spam", {}, {}, ['Migration']).Migration
+        M2 = __import__("fakeapp.migrations.0002_eggs", {}, {}, ['Migration']).Migration
+        
+        self.assertEqual(
+            [M1, M2],
+            list(migration.get_migration_classes(app)),
+        )
+    
+    
+    def test_get_migration(self):
+        
+        app = self.create_test_app()
+        
+        # Can't use vanilla import, modules beginning with numbers aren't in grammar
+        M1 = __import__("fakeapp.migrations.0001_spam", {}, {}, ['Migration']).Migration
+        M2 = __import__("fakeapp.migrations.0002_eggs", {}, {}, ['Migration']).Migration
+        
+        self.assertEqual(M1, migration.get_migration(app, "0001_spam"))
+        self.assertEqual(M2, migration.get_migration(app, "0002_eggs"))
+        
+        self.assertRaises(ValueError, migration.get_migration, app, "0001_jam")
+    
+    
+    def test_all_migrations(self):
+        
+        app = migration.get_app("fakeapp")
+        
+        self.assertEqual(
+            {app: {
+                "0001_spam": migration.get_migration(app, "0001_spam"),
+                "0002_eggs": migration.get_migration(app, "0002_eggs"),
+            }},
+            migration.all_migrations(),
+        )
+    
+    
+    def assertListEqual(self, list1, list2):
+        list1 = list(list1)
+        list2 = list(list2)
+        list1.sort()
+        list2.sort()
+        return self.assertEqual(list1, list2)
+    
+    
+    def test_apply_migrations(self):
+        
+        app = migration.get_app("fakeapp")
+        
+        # We should start with no migrations
+        self.assertEqual(list(migration.MigrationHistory.objects.all()), [])
+        
+        # Apply them normally
+        migration.migrate_app(app, target_name=None, resolve_mode=None, fake=False, silent=True)
+        
+        # We should finish with all migrations
+        self.assertListEqual(
+            (
+                (u"fakeapp", u"0001_spam"),
+                (u"fakeapp", u"0002_eggs"),
+            ),
+            migration.MigrationHistory.objects.values_list("app_name", "migration"),
+        )
+        
+        # Now roll them backwards
+        migration.migrate_app(app, target_name="zero", resolve_mode=None, fake=False, silent=True)
+        
+        # Finish with none
+        self.assertEqual(list(migration.MigrationHistory.objects.all()), [])
+    
+    
+    def test_migration_merge_forwards(self):
+        
+        app = migration.get_app("fakeapp")
+        
+        # We should start with no migrations
+        self.assertEqual(list(migration.MigrationHistory.objects.all()), [])
+        
+        # Insert one in the wrong order
+        migration.MigrationHistory.objects.create(
+            app_name = "fakeapp",
+            migration = "0002_eggs",
+            applied = datetime.datetime.now(),
+        )
+        
+        # Did it go in?
+        self.assertListEqual(
+            (
+                (u"fakeapp", u"0002_eggs"),
+            ),
+            migration.MigrationHistory.objects.values_list("app_name", "migration"),
+        )
+        
+        # Apply them normally
+        try:
+            migration.migrate_app(app, target_name=None, resolve_mode=None, fake=False, silent=True)
+        except SystemExit:
+            pass
+        
+        # Nothing should have changed (no merge mode!)
+        self.assertListEqual(
+            (
+                (u"fakeapp", u"0002_eggs"),
+            ),
+            migration.MigrationHistory.objects.values_list("app_name", "migration"),
+        )
+        
+        # Apply with merge
+        migration.migrate_app(app, target_name=None, resolve_mode="merge", fake=False, silent=True)
+        
+        # We should finish with all migrations
+        self.assertListEqual(
+            (
+                (u"fakeapp", u"0001_spam"),
+                (u"fakeapp", u"0002_eggs"),
+            ),
+            migration.MigrationHistory.objects.values_list("app_name", "migration"),
+        )
+        
+        # Now roll them backwards
+        migration.migrate_app(app, target_name="0001", resolve_mode=None, fake=True, silent=True)
+        migration.migrate_app(app, target_name="zero", resolve_mode=None, fake=False, silent=True)
+        
+        # Finish with none
+        self.assertEqual(list(migration.MigrationHistory.objects.all()), [])
\ No newline at end of file