Merged with branch 1.0.
[wolnelektury.git] / apps / south / tests / logic.py
1 import unittest
2 import datetime
3 import sys
4 import os
5
6 from south import migration
7
8 # Add the tests directory so fakeapp is on sys.path
9 test_root = os.path.dirname(__file__)
10 sys.path.append(test_root)
11
12
13 class TestMigrationLogic(unittest.TestCase):
14
15     """
16     Tests if the various logic functions in migration actually work.
17     """
18
19     def create_fake_app(self, name):
20         
21         class Fake:
22             pass
23         
24         fake = Fake()
25         fake.__name__ = name
26         return fake
27
28
29     def create_test_app(self):
30         
31         class Fake:
32             pass
33         
34         fake = Fake()
35         fake.__name__ = "fakeapp.migrations"
36         fake.__file__ = os.path.join(test_root, "fakeapp", "migrations", "__init__.py")
37         return fake
38     
39     
40     def monkeypatch(self):
41         """Swaps out various Django calls for fake ones for our own nefarious purposes."""
42         
43         def new_get_apps():
44             return ['fakeapp']
45         
46         from django.db import models
47         from django.conf import settings
48         models.get_apps_old, models.get_apps = models.get_apps, new_get_apps
49         settings.INSTALLED_APPS, settings.OLD_INSTALLED_APPS = (
50             ["fakeapp"],
51             settings.INSTALLED_APPS,
52         )
53         self.redo_app_cache()
54     setUp = monkeypatch
55     
56     
57     def unmonkeypatch(self):
58         """Undoes what monkeypatch did."""
59         
60         from django.db import models
61         from django.conf import settings
62         models.get_apps = models.get_apps_old
63         settings.INSTALLED_APPS = settings.OLD_INSTALLED_APPS
64         self.redo_app_cache()
65     tearDown = unmonkeypatch
66     
67     
68     def redo_app_cache(self):
69         from django.db.models.loading import AppCache
70         a = AppCache()
71         a.loaded = False
72         a._populate()
73     
74
75     def test_get_app_name(self):
76         self.assertEqual(
77             "southtest",
78             migration.get_app_name(self.create_fake_app("southtest.migrations")),
79         )
80         self.assertEqual(
81             "baz",
82             migration.get_app_name(self.create_fake_app("foo.bar.baz.migrations")),
83         )
84     
85     
86     def test_get_migrated_apps(self):
87         
88         P1 = __import__("fakeapp.migrations", {}, {}, [''])
89         
90         self.assertEqual(
91             [P1],
92             list(migration.get_migrated_apps()),
93         )
94     
95     
96     def test_get_app(self):
97         
98         P1 = __import__("fakeapp.migrations", {}, {}, [''])
99         
100         self.assertEqual(P1, migration.get_app("fakeapp"))
101         self.assertEqual(P1, migration.get_app(self.create_fake_app("fakeapp.models")))
102     
103     
104     def test_get_app_fullname(self):
105         self.assertEqual(
106             "southtest",
107             migration.get_app_fullname(self.create_fake_app("southtest.migrations")),
108         )
109         self.assertEqual(
110             "foo.bar.baz",
111             migration.get_app_fullname(self.create_fake_app("foo.bar.baz.migrations")),
112         )
113     
114     
115     def test_get_migration_names(self):
116         
117         app = self.create_test_app()
118         
119         self.assertEqual(
120             ["0001_spam", "0002_eggs"],
121             migration.get_migration_names(app),
122         )
123     
124     
125     def test_get_migration_classes(self):
126         
127         app = self.create_test_app()
128         
129         # Can't use vanilla import, modules beginning with numbers aren't in grammar
130         M1 = __import__("fakeapp.migrations.0001_spam", {}, {}, ['Migration']).Migration
131         M2 = __import__("fakeapp.migrations.0002_eggs", {}, {}, ['Migration']).Migration
132         
133         self.assertEqual(
134             [M1, M2],
135             list(migration.get_migration_classes(app)),
136         )
137     
138     
139     def test_get_migration(self):
140         
141         app = self.create_test_app()
142         
143         # Can't use vanilla import, modules beginning with numbers aren't in grammar
144         M1 = __import__("fakeapp.migrations.0001_spam", {}, {}, ['Migration']).Migration
145         M2 = __import__("fakeapp.migrations.0002_eggs", {}, {}, ['Migration']).Migration
146         
147         self.assertEqual(M1, migration.get_migration(app, "0001_spam"))
148         self.assertEqual(M2, migration.get_migration(app, "0002_eggs"))
149         
150         self.assertRaises(ValueError, migration.get_migration, app, "0001_jam")
151     
152     
153     def test_all_migrations(self):
154         
155         app = migration.get_app("fakeapp")
156         
157         self.assertEqual(
158             {app: {
159                 "0001_spam": migration.get_migration(app, "0001_spam"),
160                 "0002_eggs": migration.get_migration(app, "0002_eggs"),
161             }},
162             migration.all_migrations(),
163         )
164     
165     
166     def assertListEqual(self, list1, list2):
167         list1 = list(list1)
168         list2 = list(list2)
169         list1.sort()
170         list2.sort()
171         return self.assertEqual(list1, list2)
172     
173     
174     def test_apply_migrations(self):
175         
176         app = migration.get_app("fakeapp")
177         
178         # We should start with no migrations
179         self.assertEqual(list(migration.MigrationHistory.objects.all()), [])
180         
181         # Apply them normally
182         migration.migrate_app(app, target_name=None, resolve_mode=None, fake=False, silent=True)
183         
184         # We should finish with all migrations
185         self.assertListEqual(
186             (
187                 (u"fakeapp", u"0001_spam"),
188                 (u"fakeapp", u"0002_eggs"),
189             ),
190             migration.MigrationHistory.objects.values_list("app_name", "migration"),
191         )
192         
193         # Now roll them backwards
194         migration.migrate_app(app, target_name="zero", resolve_mode=None, fake=False, silent=True)
195         
196         # Finish with none
197         self.assertEqual(list(migration.MigrationHistory.objects.all()), [])
198     
199     
200     def test_migration_merge_forwards(self):
201         
202         app = migration.get_app("fakeapp")
203         
204         # We should start with no migrations
205         self.assertEqual(list(migration.MigrationHistory.objects.all()), [])
206         
207         # Insert one in the wrong order
208         migration.MigrationHistory.objects.create(
209             app_name = "fakeapp",
210             migration = "0002_eggs",
211             applied = datetime.datetime.now(),
212         )
213         
214         # Did it go in?
215         self.assertListEqual(
216             (
217                 (u"fakeapp", u"0002_eggs"),
218             ),
219             migration.MigrationHistory.objects.values_list("app_name", "migration"),
220         )
221         
222         # Apply them normally
223         try:
224             migration.migrate_app(app, target_name=None, resolve_mode=None, fake=False, silent=True)
225         except SystemExit:
226             pass
227         
228         # Nothing should have changed (no merge mode!)
229         self.assertListEqual(
230             (
231                 (u"fakeapp", u"0002_eggs"),
232             ),
233             migration.MigrationHistory.objects.values_list("app_name", "migration"),
234         )
235         
236         # Apply with merge
237         migration.migrate_app(app, target_name=None, resolve_mode="merge", fake=False, silent=True)
238         
239         # We should finish with all migrations
240         self.assertListEqual(
241             (
242                 (u"fakeapp", u"0001_spam"),
243                 (u"fakeapp", u"0002_eggs"),
244             ),
245             migration.MigrationHistory.objects.values_list("app_name", "migration"),
246         )
247         
248         # Now roll them backwards
249         migration.migrate_app(app, target_name="0001", resolve_mode=None, fake=True, silent=True)
250         migration.migrate_app(app, target_name="zero", resolve_mode=None, fake=False, silent=True)
251         
252         # Finish with none
253         self.assertEqual(list(migration.MigrationHistory.objects.all()), [])