Use urljoin to create proper feed media URLs
[larjonas-mediagoblin.git] / mediagoblin / tests / test_sql_migrations.py
blob7e0569adcb349327f8943a9973f2d9fa1230d208
1 # GNU MediaGoblin -- federated, autonomous media hosting
2 # Copyright (C) 2012, 2012 MediaGoblin contributors. See AUTHORS.
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.
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.
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/>.
17 import six
18 import pytest
20 pytestmark = pytest.mark.skipif(six.PY3, reason='needs sqlalchemy.migrate')
22 import copy
24 from sqlalchemy import (
25 Table, Column, MetaData, Index,
26 Integer, Float, Unicode, UnicodeText, DateTime, Boolean,
27 ForeignKey, UniqueConstraint, PickleType, VARCHAR)
28 from sqlalchemy.orm import sessionmaker, relationship
29 from sqlalchemy.ext.declarative import declarative_base
30 from sqlalchemy.sql import select, insert
31 if six.PY2:
32 from migrate import changeset
34 from mediagoblin.db.base import GMGTableBase
35 from mediagoblin.db.migration_tools import MigrationManager, RegisterMigration
36 from mediagoblin.tools.common import CollectingPrinter
39 # This one will get filled with local migrations
40 FULL_MIGRATIONS = {}
43 #######################################################
44 # Migration set 1: Define initial models, no migrations
45 #######################################################
47 Base1 = declarative_base(cls=GMGTableBase)
49 class Creature1(Base1):
50 __tablename__ = "creature"
52 id = Column(Integer, primary_key=True)
53 name = Column(Unicode, unique=True, nullable=False, index=True)
54 num_legs = Column(Integer, nullable=False)
55 is_demon = Column(Boolean)
57 class Level1(Base1):
58 __tablename__ = "level"
60 id = Column(Unicode, primary_key=True)
61 name = Column(Unicode)
62 description = Column(Unicode)
63 exits = Column(PickleType)
65 SET1_MODELS = [Creature1, Level1]
67 FOUNDATIONS = {Creature1:[{'name':u'goblin','num_legs':2,'is_demon':False},
68 {'name':u'cerberus','num_legs':4,'is_demon':True}]
71 SET1_MIGRATIONS = {}
73 #######################################################
74 # Migration set 2: A few migrations and new model
75 #######################################################
77 Base2 = declarative_base(cls=GMGTableBase)
79 class Creature2(Base2):
80 __tablename__ = "creature"
82 id = Column(Integer, primary_key=True)
83 name = Column(Unicode, unique=True, nullable=False, index=True)
84 num_legs = Column(Integer, nullable=False)
85 magical_powers = relationship("CreaturePower2")
87 class CreaturePower2(Base2):
88 __tablename__ = "creature_power"
90 id = Column(Integer, primary_key=True)
91 creature = Column(
92 Integer, ForeignKey('creature.id'), nullable=False)
93 name = Column(Unicode)
94 description = Column(Unicode)
95 hitpower = Column(Integer, nullable=False)
97 class Level2(Base2):
98 __tablename__ = "level"
100 id = Column(Unicode, primary_key=True)
101 name = Column(Unicode)
102 description = Column(Unicode)
104 class LevelExit2(Base2):
105 __tablename__ = "level_exit"
107 id = Column(Integer, primary_key=True)
108 name = Column(Unicode)
109 from_level = Column(
110 Unicode, ForeignKey('level.id'), nullable=False)
111 to_level = Column(
112 Unicode, ForeignKey('level.id'), nullable=False)
114 SET2_MODELS = [Creature2, CreaturePower2, Level2, LevelExit2]
117 @RegisterMigration(1, FULL_MIGRATIONS)
118 def creature_remove_is_demon(db_conn):
120 Remove the is_demon field from the creature model. We don't need
123 # :( Commented out 'cuz of:
124 # http://code.google.com/p/sqlalchemy-migrate/issues/detail?id=143&thanks=143&ts=1327882242
126 # metadata = MetaData(bind=db_conn.bind)
127 # creature_table = Table(
128 # 'creature', metadata,
129 # autoload=True, autoload_with=db_conn.bind)
130 # creature_table.drop_column('is_demon')
131 pass
134 @RegisterMigration(2, FULL_MIGRATIONS)
135 def creature_powers_new_table(db_conn):
137 Add a new table for creature powers. Nothing needs to go in it
138 yet though as there wasn't anything that previously held this
139 information
141 metadata = MetaData(bind=db_conn.bind)
143 # We have to access the creature table so sqlalchemy can make the
144 # foreign key relationship
145 creature_table = Table(
146 'creature', metadata,
147 autoload=True, autoload_with=db_conn.bind)
149 creature_powers = Table(
150 'creature_power', metadata,
151 Column('id', Integer, primary_key=True),
152 Column('creature',
153 Integer, ForeignKey('creature.id'), nullable=False),
154 Column('name', Unicode),
155 Column('description', Unicode),
156 Column('hitpower', Integer, nullable=False))
157 metadata.create_all(db_conn.bind)
160 @RegisterMigration(3, FULL_MIGRATIONS)
161 def level_exits_new_table(db_conn):
163 Make a new table for level exits and move the previously pickled
164 stuff over to here (then drop the old unneeded table)
166 # First, create the table
167 # -----------------------
168 metadata = MetaData(bind=db_conn.bind)
170 # Minimal representation of level table.
171 # Not auto-introspecting here because of pickle table. I'm not
172 # sure sqlalchemy can auto-introspect pickle columns.
173 levels = Table(
174 'level', metadata,
175 Column('id', Unicode, primary_key=True),
176 Column('name', Unicode),
177 Column('description', Unicode),
178 Column('exits', PickleType))
180 level_exits = Table(
181 'level_exit', metadata,
182 Column('id', Integer, primary_key=True),
183 Column('name', Unicode),
184 Column('from_level',
185 Unicode, ForeignKey('level.id'), nullable=False),
186 Column('to_level',
187 Unicode, ForeignKey('level.id'), nullable=False))
188 metadata.create_all(db_conn.bind)
190 # And now, convert all the old exit pickles to new level exits
191 # ------------------------------------------------------------
193 # query over and insert
194 result = db_conn.execute(
195 select([levels], levels.c.exits!=None))
197 for level in result:
199 for exit_name, to_level in six.iteritems(level['exits']):
200 # Insert the level exit
201 db_conn.execute(
202 level_exits.insert().values(
203 name=exit_name,
204 from_level=level.id,
205 to_level=to_level))
207 # Finally, drop the old level exits pickle table
208 # ----------------------------------------------
209 levels.drop_column('exits')
212 # A hack! At this point we freeze-fame and get just a partial list of
213 # migrations
215 SET2_MIGRATIONS = copy.copy(FULL_MIGRATIONS)
217 #######################################################
218 # Migration set 3: Final migrations
219 #######################################################
221 Base3 = declarative_base(cls=GMGTableBase)
223 class Creature3(Base3):
224 __tablename__ = "creature"
226 id = Column(Integer, primary_key=True)
227 name = Column(Unicode, unique=True, nullable=False, index=True)
228 num_limbs= Column(Integer, nullable=False)
229 magical_powers = relationship("CreaturePower3")
231 class CreaturePower3(Base3):
232 __tablename__ = "creature_power"
234 id = Column(Integer, primary_key=True)
235 creature = Column(
236 Integer, ForeignKey('creature.id'), nullable=False, index=True)
237 name = Column(Unicode)
238 description = Column(Unicode)
239 hitpower = Column(Float, nullable=False)
241 class Level3(Base3):
242 __tablename__ = "level"
244 id = Column(Unicode, primary_key=True)
245 name = Column(Unicode)
246 description = Column(Unicode)
248 class LevelExit3(Base3):
249 __tablename__ = "level_exit"
251 id = Column(Integer, primary_key=True)
252 name = Column(Unicode)
253 from_level = Column(
254 Unicode, ForeignKey('level.id'), nullable=False, index=True)
255 to_level = Column(
256 Unicode, ForeignKey('level.id'), nullable=False, index=True)
259 SET3_MODELS = [Creature3, CreaturePower3, Level3, LevelExit3]
260 SET3_MIGRATIONS = FULL_MIGRATIONS
263 @RegisterMigration(4, FULL_MIGRATIONS)
264 def creature_num_legs_to_num_limbs(db_conn):
266 Turns out we're tracking all sorts of limbs, not "legs"
267 specifically. Humans would be 4 here, for instance. So we
268 renamed the column.
270 metadata = MetaData(bind=db_conn.bind)
271 creature_table = Table(
272 'creature', metadata,
273 autoload=True, autoload_with=db_conn.bind)
274 creature_table.c.num_legs.alter(name=u"num_limbs")
277 @RegisterMigration(5, FULL_MIGRATIONS)
278 def level_exit_index_from_and_to_level(db_conn):
280 Index the from and to levels of the level exit table.
282 metadata = MetaData(bind=db_conn.bind)
283 level_exit = Table(
284 'level_exit', metadata,
285 autoload=True, autoload_with=db_conn.bind)
286 Index('ix_level_exit_from_level',
287 level_exit.c.from_level).create(db_conn.bind)
288 Index('ix_level_exit_to_level',
289 level_exit.c.to_level).create(db_conn.bind)
292 @RegisterMigration(6, FULL_MIGRATIONS)
293 def creature_power_index_creature(db_conn):
295 Index our foreign key relationship to the creatures
297 metadata = MetaData(bind=db_conn.bind)
298 creature_power = Table(
299 'creature_power', metadata,
300 autoload=True, autoload_with=db_conn.bind)
301 Index('ix_creature_power_creature',
302 creature_power.c.creature).create(db_conn.bind)
305 @RegisterMigration(7, FULL_MIGRATIONS)
306 def creature_power_hitpower_to_float(db_conn):
308 Convert hitpower column on creature power table from integer to
309 float.
311 Turns out we want super precise values of how much hitpower there
312 really is.
314 metadata = MetaData(bind=db_conn.bind)
316 # We have to access the creature table so sqlalchemy can make the
317 # foreign key relationship
318 creature_table = Table(
319 'creature', metadata,
320 autoload=True, autoload_with=db_conn.bind)
322 creature_power = Table(
323 'creature_power', metadata,
324 Column('id', Integer, primary_key=True),
325 Column('creature', Integer,
326 ForeignKey('creature.id'), nullable=False,
327 index=True),
328 Column('name', Unicode),
329 Column('description', Unicode),
330 Column('hitpower', Integer, nullable=False))
332 creature_power.c.hitpower.alter(type=Float)
335 @RegisterMigration(8, FULL_MIGRATIONS)
336 def creature_power_name_creature_unique(db_conn):
338 Add a unique constraint to name and creature on creature_power.
340 We don't want multiple creature powers with the same name per creature!
342 # Note: We don't actually check to see if this constraint is set
343 # up because at present there's no way to do so in sqlalchemy :\
345 metadata = MetaData(bind=db_conn.bind)
347 creature_power = Table(
348 'creature_power', metadata,
349 autoload=True, autoload_with=db_conn.bind)
351 cons = changeset.constraint.UniqueConstraint(
352 'name', 'creature', table=creature_power)
354 cons.create()
357 def _insert_migration1_objects(session):
359 Test objects to insert for the first set of things
361 # Insert creatures
362 session.add_all(
363 [Creature1(name=u'centipede',
364 num_legs=100,
365 is_demon=False),
366 Creature1(name=u'wolf',
367 num_legs=4,
368 is_demon=False),
369 # don't ask me what a wizardsnake is.
370 Creature1(name=u'wizardsnake',
371 num_legs=0,
372 is_demon=True)])
374 # Insert levels
375 session.add_all(
376 [Level1(id=u'necroplex',
377 name=u'The Necroplex',
378 description=u'A complex full of pure deathzone.',
379 exits={
380 u'deathwell': u'evilstorm',
381 u'portal': u'central_park'}),
382 Level1(id=u'evilstorm',
383 name=u'Evil Storm',
384 description=u'A storm full of pure evil.',
385 exits={}), # you can't escape the evilstorm
386 Level1(id=u'central_park',
387 name=u'Central Park, NY, NY',
388 description=u"New York's friendly Central Park.",
389 exits={
390 u'portal': u'necroplex'})])
392 session.commit()
395 def _insert_migration2_objects(session):
397 Test objects to insert for the second set of things
399 # Insert creatures
400 session.add_all(
401 [Creature2(
402 name=u'centipede',
403 num_legs=100),
404 Creature2(
405 name=u'wolf',
406 num_legs=4,
407 magical_powers = [
408 CreaturePower2(
409 name=u"ice breath",
410 description=u"A blast of icy breath!",
411 hitpower=20),
412 CreaturePower2(
413 name=u"death stare",
414 description=u"A frightening stare, for sure!",
415 hitpower=45)]),
416 Creature2(
417 name=u'wizardsnake',
418 num_legs=0,
419 magical_powers=[
420 CreaturePower2(
421 name=u'death_rattle',
422 description=u'A rattle... of DEATH!',
423 hitpower=1000),
424 CreaturePower2(
425 name=u'sneaky_stare',
426 description=u"The sneakiest stare you've ever seen!",
427 hitpower=300),
428 CreaturePower2(
429 name=u'slithery_smoke',
430 description=u"A blast of slithery, slithery smoke.",
431 hitpower=10),
432 CreaturePower2(
433 name=u'treacherous_tremors',
434 description=u"The ground shakes beneath footed animals!",
435 hitpower=0)])])
437 # Insert levels
438 session.add_all(
439 [Level2(id=u'necroplex',
440 name=u'The Necroplex',
441 description=u'A complex full of pure deathzone.'),
442 Level2(id=u'evilstorm',
443 name=u'Evil Storm',
444 description=u'A storm full of pure evil.',
445 exits=[]), # you can't escape the evilstorm
446 Level2(id=u'central_park',
447 name=u'Central Park, NY, NY',
448 description=u"New York's friendly Central Park.")])
450 # necroplex exits
451 session.add_all(
452 [LevelExit2(name=u'deathwell',
453 from_level=u'necroplex',
454 to_level=u'evilstorm'),
455 LevelExit2(name=u'portal',
456 from_level=u'necroplex',
457 to_level=u'central_park')])
459 # there are no evilstorm exits because there is no exit from the
460 # evilstorm
462 # central park exits
463 session.add_all(
464 [LevelExit2(name=u'portal',
465 from_level=u'central_park',
466 to_level=u'necroplex')])
468 session.commit()
471 def _insert_migration3_objects(session):
473 Test objects to insert for the third set of things
475 # Insert creatures
476 session.add_all(
477 [Creature3(
478 name=u'centipede',
479 num_limbs=100),
480 Creature3(
481 name=u'wolf',
482 num_limbs=4,
483 magical_powers = [
484 CreaturePower3(
485 name=u"ice breath",
486 description=u"A blast of icy breath!",
487 hitpower=20.0),
488 CreaturePower3(
489 name=u"death stare",
490 description=u"A frightening stare, for sure!",
491 hitpower=45.0)]),
492 Creature3(
493 name=u'wizardsnake',
494 num_limbs=0,
495 magical_powers=[
496 CreaturePower3(
497 name=u'death_rattle',
498 description=u'A rattle... of DEATH!',
499 hitpower=1000.0),
500 CreaturePower3(
501 name=u'sneaky_stare',
502 description=u"The sneakiest stare you've ever seen!",
503 hitpower=300.0),
504 CreaturePower3(
505 name=u'slithery_smoke',
506 description=u"A blast of slithery, slithery smoke.",
507 hitpower=10.0),
508 CreaturePower3(
509 name=u'treacherous_tremors',
510 description=u"The ground shakes beneath footed animals!",
511 hitpower=0.0)])],
512 # annnnnd one more to test a floating point hitpower
513 Creature3(
514 name=u'deity',
515 numb_limbs=30,
516 magical_powers=[
517 CreaturePower3(
518 name=u'smite',
519 description=u'Smitten by holy wrath!',
520 hitpower=9999.9)]))
522 # Insert levels
523 session.add_all(
524 [Level3(id=u'necroplex',
525 name=u'The Necroplex',
526 description=u'A complex full of pure deathzone.'),
527 Level3(id=u'evilstorm',
528 name=u'Evil Storm',
529 description=u'A storm full of pure evil.',
530 exits=[]), # you can't escape the evilstorm
531 Level3(id=u'central_park',
532 name=u'Central Park, NY, NY',
533 description=u"New York's friendly Central Park.")])
535 # necroplex exits
536 session.add_all(
537 [LevelExit3(name=u'deathwell',
538 from_level=u'necroplex',
539 to_level=u'evilstorm'),
540 LevelExit3(name=u'portal',
541 from_level=u'necroplex',
542 to_level=u'central_park')])
544 # there are no evilstorm exits because there is no exit from the
545 # evilstorm
547 # central park exits
548 session.add_all(
549 [LevelExit3(name=u'portal',
550 from_level=u'central_park',
551 to_level=u'necroplex')])
553 session.commit()
555 def create_test_engine():
556 from sqlalchemy import create_engine
557 engine = create_engine('sqlite:///:memory:', echo=False)
558 Session = sessionmaker(bind=engine)
559 return engine, Session
562 def assert_col_type(column, this_class):
563 assert isinstance(column.type, this_class)
566 def _get_level3_exits(session, level):
567 return dict(
568 [(level_exit.name, level_exit.to_level)
569 for level_exit in
570 session.query(LevelExit3).filter_by(from_level=level.id)])
573 def test_set1_to_set3():
574 # Create / connect to database
575 # ----------------------------
577 engine, Session = create_test_engine()
579 # Create tables by migrating on empty initial set
580 # -----------------------------------------------
582 printer = CollectingPrinter()
583 migration_manager = MigrationManager(
584 u'__main__', SET1_MODELS, FOUNDATIONS, SET1_MIGRATIONS, Session(),
585 printer)
587 # Check latest migration and database current migration
588 assert migration_manager.latest_migration == 0
589 assert migration_manager.database_current_migration == None
591 result = migration_manager.init_or_migrate()
593 # Make sure output was "inited"
594 assert result == u'inited'
595 # Check output
596 assert printer.combined_string == (
597 "-> Initializing main mediagoblin tables... done.\n" + \
598 " + Laying foundations for Creature1 table\n" )
599 # Check version in database
600 assert migration_manager.latest_migration == 0
601 assert migration_manager.database_current_migration == 0
604 # Install the initial set
605 # -----------------------
607 _insert_migration1_objects(Session())
609 # Try to "re-migrate" with same manager settings... nothing should happen
610 migration_manager = MigrationManager(
611 u'__main__', SET1_MODELS, FOUNDATIONS, SET1_MIGRATIONS,
612 Session(), printer)
613 assert migration_manager.init_or_migrate() == None
615 # Check version in database
616 assert migration_manager.latest_migration == 0
617 assert migration_manager.database_current_migration == 0
619 # Sanity check a few things in the database...
620 metadata = MetaData(bind=engine)
622 # Check the structure of the creature table
623 creature_table = Table(
624 'creature', metadata,
625 autoload=True, autoload_with=engine)
626 assert set(creature_table.c.keys()) == set(
627 ['id', 'name', 'num_legs', 'is_demon'])
628 assert_col_type(creature_table.c.id, Integer)
629 assert_col_type(creature_table.c.name, VARCHAR)
630 assert creature_table.c.name.nullable is False
631 #assert creature_table.c.name.index is True
632 #assert creature_table.c.name.unique is True
633 assert_col_type(creature_table.c.num_legs, Integer)
634 assert creature_table.c.num_legs.nullable is False
635 assert_col_type(creature_table.c.is_demon, Boolean)
637 # Check the structure of the level table
638 level_table = Table(
639 'level', metadata,
640 autoload=True, autoload_with=engine)
641 assert set(level_table.c.keys()) == set(
642 ['id', 'name', 'description', 'exits'])
643 assert_col_type(level_table.c.id, VARCHAR)
644 assert level_table.c.id.primary_key is True
645 assert_col_type(level_table.c.name, VARCHAR)
646 assert_col_type(level_table.c.description, VARCHAR)
647 # Skipping exits... Not sure if we can detect pickletype, not a
648 # big deal regardless.
650 # Now check to see if stuff seems to be in there.
651 session = Session()
653 # Check the creation of the foundation rows on the creature table
654 creature = session.query(Creature1).filter_by(
655 name=u'goblin').one()
656 assert creature.num_legs == 2
657 assert creature.is_demon == False
659 creature = session.query(Creature1).filter_by(
660 name=u'cerberus').one()
661 assert creature.num_legs == 4
662 assert creature.is_demon == True
665 # Check the creation of the inserted rows on the creature and levels tables
667 creature = session.query(Creature1).filter_by(
668 name=u'centipede').one()
669 assert creature.num_legs == 100
670 assert creature.is_demon == False
672 creature = session.query(Creature1).filter_by(
673 name=u'wolf').one()
674 assert creature.num_legs == 4
675 assert creature.is_demon == False
677 creature = session.query(Creature1).filter_by(
678 name=u'wizardsnake').one()
679 assert creature.num_legs == 0
680 assert creature.is_demon == True
682 level = session.query(Level1).filter_by(
683 id=u'necroplex').one()
684 assert level.name == u'The Necroplex'
685 assert level.description == u'A complex full of pure deathzone.'
686 assert level.exits == {
687 'deathwell': 'evilstorm',
688 'portal': 'central_park'}
690 level = session.query(Level1).filter_by(
691 id=u'evilstorm').one()
692 assert level.name == u'Evil Storm'
693 assert level.description == u'A storm full of pure evil.'
694 assert level.exits == {} # You still can't escape the evilstorm!
696 level = session.query(Level1).filter_by(
697 id=u'central_park').one()
698 assert level.name == u'Central Park, NY, NY'
699 assert level.description == u"New York's friendly Central Park."
700 assert level.exits == {
701 'portal': 'necroplex'}
703 # Create new migration manager, but make sure the db migration
704 # isn't said to be updated yet
705 printer = CollectingPrinter()
706 migration_manager = MigrationManager(
707 u'__main__', SET3_MODELS, FOUNDATIONS, SET3_MIGRATIONS, Session(),
708 printer)
710 assert migration_manager.latest_migration == 8
711 assert migration_manager.database_current_migration == 0
713 # Migrate
714 result = migration_manager.init_or_migrate()
716 # Make sure result was "migrated"
717 assert result == u'migrated'
719 # TODO: Check output to user
720 assert printer.combined_string == """\
721 -> Updating main mediagoblin tables:
722 + Running migration 1, "creature_remove_is_demon"... done.
723 + Running migration 2, "creature_powers_new_table"... done.
724 + Running migration 3, "level_exits_new_table"... done.
725 + Running migration 4, "creature_num_legs_to_num_limbs"... done.
726 + Running migration 5, "level_exit_index_from_and_to_level"... done.
727 + Running migration 6, "creature_power_index_creature"... done.
728 + Running migration 7, "creature_power_hitpower_to_float"... done.
729 + Running migration 8, "creature_power_name_creature_unique"... done.
732 # Make sure version matches expected
733 migration_manager = MigrationManager(
734 u'__main__', SET3_MODELS, FOUNDATIONS, SET3_MIGRATIONS, Session(),
735 printer)
736 assert migration_manager.latest_migration == 8
737 assert migration_manager.database_current_migration == 8
739 # Check all things in database match expected
741 # Check the creature table
742 metadata = MetaData(bind=engine)
743 creature_table = Table(
744 'creature', metadata,
745 autoload=True, autoload_with=engine)
746 # assert set(creature_table.c.keys()) == set(
747 # ['id', 'name', 'num_limbs'])
748 assert set(creature_table.c.keys()) == set(
749 [u'id', 'name', u'num_limbs', u'is_demon'])
750 assert_col_type(creature_table.c.id, Integer)
751 assert_col_type(creature_table.c.name, VARCHAR)
752 assert creature_table.c.name.nullable is False
753 #assert creature_table.c.name.index is True
754 #assert creature_table.c.name.unique is True
755 assert_col_type(creature_table.c.num_limbs, Integer)
756 assert creature_table.c.num_limbs.nullable is False
758 # Check the CreaturePower table
759 creature_power_table = Table(
760 'creature_power', metadata,
761 autoload=True, autoload_with=engine)
762 assert set(creature_power_table.c.keys()) == set(
763 ['id', 'creature', 'name', 'description', 'hitpower'])
764 assert_col_type(creature_power_table.c.id, Integer)
765 assert_col_type(creature_power_table.c.creature, Integer)
766 assert creature_power_table.c.creature.nullable is False
767 assert_col_type(creature_power_table.c.name, VARCHAR)
768 assert_col_type(creature_power_table.c.description, VARCHAR)
769 assert_col_type(creature_power_table.c.hitpower, Float)
770 assert creature_power_table.c.hitpower.nullable is False
772 # Check the structure of the level table
773 level_table = Table(
774 'level', metadata,
775 autoload=True, autoload_with=engine)
776 assert set(level_table.c.keys()) == set(
777 ['id', 'name', 'description'])
778 assert_col_type(level_table.c.id, VARCHAR)
779 assert level_table.c.id.primary_key is True
780 assert_col_type(level_table.c.name, VARCHAR)
781 assert_col_type(level_table.c.description, VARCHAR)
783 # Check the structure of the level_exits table
784 level_exit_table = Table(
785 'level_exit', metadata,
786 autoload=True, autoload_with=engine)
787 assert set(level_exit_table.c.keys()) == set(
788 ['id', 'name', 'from_level', 'to_level'])
789 assert_col_type(level_exit_table.c.id, Integer)
790 assert_col_type(level_exit_table.c.name, VARCHAR)
791 assert_col_type(level_exit_table.c.from_level, VARCHAR)
792 assert level_exit_table.c.from_level.nullable is False
793 #assert level_exit_table.c.from_level.index is True
794 assert_col_type(level_exit_table.c.to_level, VARCHAR)
795 assert level_exit_table.c.to_level.nullable is False
796 #assert level_exit_table.c.to_level.index is True
798 # Now check to see if stuff seems to be in there.
799 session = Session()
802 # Start with making sure that the foundations did not run again
803 assert session.query(Creature3).filter_by(
804 name=u'goblin').count() == 1
805 assert session.query(Creature3).filter_by(
806 name=u'cerberus').count() == 1
808 # Then make sure the models have been migrated correctly
809 creature = session.query(Creature3).filter_by(
810 name=u'centipede').one()
811 assert creature.num_limbs == 100.0
812 assert creature.magical_powers == []
814 creature = session.query(Creature3).filter_by(
815 name=u'wolf').one()
816 assert creature.num_limbs == 4.0
817 assert creature.magical_powers == []
819 creature = session.query(Creature3).filter_by(
820 name=u'wizardsnake').one()
821 assert creature.num_limbs == 0.0
822 assert creature.magical_powers == []
824 level = session.query(Level3).filter_by(
825 id=u'necroplex').one()
826 assert level.name == u'The Necroplex'
827 assert level.description == u'A complex full of pure deathzone.'
828 level_exits = _get_level3_exits(session, level)
829 assert level_exits == {
830 u'deathwell': u'evilstorm',
831 u'portal': u'central_park'}
833 level = session.query(Level3).filter_by(
834 id=u'evilstorm').one()
835 assert level.name == u'Evil Storm'
836 assert level.description == u'A storm full of pure evil.'
837 level_exits = _get_level3_exits(session, level)
838 assert level_exits == {} # You still can't escape the evilstorm!
840 level = session.query(Level3).filter_by(
841 id=u'central_park').one()
842 assert level.name == u'Central Park, NY, NY'
843 assert level.description == u"New York's friendly Central Park."
844 level_exits = _get_level3_exits(session, level)
845 assert level_exits == {
846 'portal': 'necroplex'}
849 #def test_set2_to_set3():
850 # Create / connect to database
851 # Create tables by migrating on empty initial set
853 # Install the initial set
854 # Check version in database
855 # Sanity check a few things in the database
857 # Migrate
858 # Make sure version matches expected
859 # Check all things in database match expected
860 # pass
863 #def test_set1_to_set2_to_set3():
864 # Create / connect to database
865 # Create tables by migrating on empty initial set
867 # Install the initial set
868 # Check version in database
869 # Sanity check a few things in the database
871 # Migrate
872 # Make sure version matches expected
873 # Check all things in database match expected
875 # Migrate again
876 # Make sure version matches expected again
877 # Check all things in database match expected again
879 ##### Set2
880 # creature_table = Table(
881 # 'creature', metadata,
882 # autoload=True, autoload_with=db_conn.bind)
883 # assert set(creature_table.c.keys()) == set(
884 # ['id', 'name', 'num_legs'])
885 # assert_col_type(creature_table.c.id, Integer)
886 # assert_col_type(creature_table.c.name, VARCHAR)
887 # assert creature_table.c.name.nullable is False
888 # assert creature_table.c.name.index is True
889 # assert creature_table.c.name.unique is True
890 # assert_col_type(creature_table.c.num_legs, Integer)
891 # assert creature_table.c.num_legs.nullable is False
893 # # Check the CreaturePower table
894 # creature_power_table = Table(
895 # 'creature_power', metadata,
896 # autoload=True, autoload_with=db_conn.bind)
897 # assert set(creature_power_table.c.keys()) == set(
898 # ['id', 'creature', 'name', 'description', 'hitpower'])
899 # assert_col_type(creature_power_table.c.id, Integer)
900 # assert_col_type(creature_power_table.c.creature, Integer)
901 # assert creature_power_table.c.creature.nullable is False
902 # assert_col_type(creature_power_table.c.name, VARCHAR)
903 # assert_col_type(creature_power_table.c.description, VARCHAR)
904 # assert_col_type(creature_power_table.c.hitpower, Integer)
905 # assert creature_power_table.c.hitpower.nullable is False
907 # # Check the structure of the level table
908 # level_table = Table(
909 # 'level', metadata,
910 # autoload=True, autoload_with=db_conn.bind)
911 # assert set(level_table.c.keys()) == set(
912 # ['id', 'name', 'description'])
913 # assert_col_type(level_table.c.id, VARCHAR)
914 # assert level_table.c.id.primary_key is True
915 # assert_col_type(level_table.c.name, VARCHAR)
916 # assert_col_type(level_table.c.description, VARCHAR)
918 # # Check the structure of the level_exits table
919 # level_exit_table = Table(
920 # 'level_exit', metadata,
921 # autoload=True, autoload_with=db_conn.bind)
922 # assert set(level_exit_table.c.keys()) == set(
923 # ['id', 'name', 'from_level', 'to_level'])
924 # assert_col_type(level_exit_table.c.id, Integer)
925 # assert_col_type(level_exit_table.c.name, VARCHAR)
926 # assert_col_type(level_exit_table.c.from_level, VARCHAR)
927 # assert level_exit_table.c.from_level.nullable is False
928 # assert_col_type(level_exit_table.c.to_level, VARCHAR)
930 # pass