test_migrations.py w/ migrate'able fixtures and some migration scaffolding
[mediagoblin.git] / mediagoblin / tests / test_migrations.py
1 # GNU MediaGoblin -- federated, autonomous media hosting
2 # Copyright (C) 2011 Free Software Foundation, Inc
3 #
4 # This program is free software: you can redistribute it and/or modify
5 # it under the terms of the GNU Affero General Public License as published by
6 # the Free Software Foundation, either version 3 of the License, or
7 # (at your option) any later version.
8 #
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU Affero General Public License for more details.
13 #
14 # You should have received a copy of the GNU Affero General Public License
15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
16
17
18 from pymongo import Connection
19
20 from mediagoblin.db.util import RegisterMigration, MigrationManager
21
22 # This one will get filled with local migrations
23 TEST_MIGRATION_REGISTRY = {}
24 # this one won't get filled
25 TEST_EMPTY_MIGRATION_REGISTRY = {}
26
27 MIGRATION_DB_NAME = u'__mediagoblin_test_migrations__'
28
29
30 ######################
31 # Fake test migrations
32 ######################
33
34 @RegisterMigration(1, TEST_MIGRATION_REGISTRY)
35 def creature_add_magical_powers(database):
36 """
37 Add lists of magical powers.
38
39 This defaults to [], an empty list. Since we haven't declared any
40 magical powers, all existing monsters should
41 """
42 pass
43
44
45 @RegisterMigration(2, TEST_MIGRATION_REGISTRY)
46 def creature_rename_num_legs_to_num_limbs(database):
47 """
48 It turns out we want to track how many limbs a creature has, not
49 just how many legs. We don't care about the ambiguous distinction
50 between arms/legs currently.
51 """
52 pass
53
54
55 @RegisterMigration(3, TEST_MIGRATION_REGISTRY)
56 def creature_remove_is_demon(database):
57 """
58 It turns out we don't care much about whether creatures are demons
59 or not.
60 """
61 pass
62
63
64 @RegisterMigration(4, TEST_MIGRATION_REGISTRY)
65 def level_exits_dict_to_list(database):
66 """
67 For the sake of the indexes we want to write, and because we
68 intend to add more flexible fields, we want to move level exits
69 from like:
70
71 {'big_door': 'castle_level_id',
72 'trapdoor': 'dungeon_level_id'}
73
74 to like:
75
76 [{'name': 'big_door',
77 'exits_to': 'castle_level_id'},
78 {'name': 'trapdoor',
79 'exits_to': 'dungeon_level_id'}]
80 """
81 pass
82
83
84 UNMIGRATED_DBDATA = {
85 'creatures': [
86 {'name': 'centipede',
87 'num_legs': 100,
88 'is_demon': False},
89 {'name': 'wolf',
90 'num_legs': 4,
91 'is_demon': False},
92 # don't ask me what a wizardsnake is.
93 {'name': 'wizardsnake',
94 'num_legs': 0,
95 'is_demon': True}],
96 'levels': [
97 {'_id': 'necroplex',
98 'name': 'The Necroplex',
99 'description': 'A complex full of pure deathzone.',
100 'exits': {
101 'deathwell': 'evilstorm',
102 'portal': 'central_park'}},
103 {'_id': 'evilstorm',
104 'name': 'Evil Storm',
105 'description': 'A storm full of pure evil.',
106 'exits': {}}, # you can't escape the evilstorm
107 {'_id': 'central_park',
108 'name': 'Central Park, NY, NY',
109 'description': "New York's friendly Central Park.",
110 'exits': {
111 'portal': 'necroplex'}}]}
112
113
114 # We want to make sure that if we're at migration 3, migration 3
115 # doesn't get re-run.
116
117 SEMI_MIGRATED_DBDATA = {
118 'creatures': [
119 {'name': 'centipede',
120 'num_limbs': 100,
121 'magical_powers': []},
122 {'name': 'wolf',
123 'num_limbs': 4,
124 # kept around namely to check that it *isn't* removed!
125 'is_demon': False,
126 'magical_powers': [
127 'ice_breath', 'death_stare']},
128 {'name': 'wizardsnake',
129 'num_limbs': 0,
130 'magical_powers': [
131 'death_rattle', 'sneaky_stare',
132 'slithery_smoke', 'treacherous_tremors'],
133 'is_demon': True}],
134 'levels': [
135 {'_id': 'necroplex',
136 'name': 'The Necroplex',
137 'description': 'A complex full of pure deathzone.',
138 'exits': [
139 {'name': 'deathwell',
140 'exits_to': 'evilstorm'},
141 {'name': 'portal',
142 'exits_to': 'central_park'}]},
143 {'_id': 'evilstorm',
144 'name': 'Evil Storm',
145 'description': 'A storm full of pure evil.',
146 'exits': []}, # you can't escape the evilstorm
147 {'_id': 'central_park',
148 'name': 'Central Park, NY, NY',
149 'description': "New York's friendly Central Park.",
150 'exits': [
151 {'name': 'portal',
152 'exits_to': 'necroplex'}]}]}
153
154
155 class TestMigrations(object):
156 def setUp(self):
157 # Set up the connection, drop an existing possible database
158 self.connection = Connection()
159 self.connection.drop_database(MIGRATION_DB_NAME)
160 self.db = Connection()[MIGRATION_DB_NAME]
161 self.migration_manager = MigrationManager(
162 self.db, TEST_MIGRATION_REGISTRY)
163
164 def tearDown(self):
165 self.connection.drop_database(MIGRATION_DB_NAME)
166