diff options
Diffstat (limited to 'mediagoblin/tests')
-rw-r--r-- | mediagoblin/tests/test_auth.py | 4 | ||||
-rw-r--r-- | mediagoblin/tests/test_celery_setup.py | 4 | ||||
-rw-r--r-- | mediagoblin/tests/test_config.py | 2 | ||||
-rw-r--r-- | mediagoblin/tests/test_mgoblin_app.ini | 2 | ||||
-rw-r--r-- | mediagoblin/tests/test_migrations.py | 402 | ||||
-rw-r--r-- | mediagoblin/tests/test_submission.py | 157 | ||||
-rwxr-xr-x | mediagoblin/tests/test_submission/evil | bin | 0 -> 96284 bytes | |||
-rwxr-xr-x | mediagoblin/tests/test_submission/evil.jpg | bin | 0 -> 96284 bytes | |||
-rwxr-xr-x | mediagoblin/tests/test_submission/evil.png | bin | 0 -> 96284 bytes | |||
-rw-r--r-- | mediagoblin/tests/test_submission/good.jpg | bin | 0 -> 10059 bytes | |||
-rw-r--r-- | mediagoblin/tests/test_submission/good.png | bin | 0 -> 50598 bytes | |||
-rw-r--r-- | mediagoblin/tests/tools.py | 42 |
12 files changed, 602 insertions, 11 deletions
diff --git a/mediagoblin/tests/test_auth.py b/mediagoblin/tests/test_auth.py index 3a13cbb1..ad9dd35b 100644 --- a/mediagoblin/tests/test_auth.py +++ b/mediagoblin/tests/test_auth.py @@ -189,7 +189,7 @@ def test_register_views(test_app): "/auth/verify_email/?userid=%s&token=total_bs" % unicode( new_user['_id'])) context = util.TEMPLATE_TEST_CONTEXT[ - 'mediagoblin/auth/verify_email.html'] + 'mediagoblin/user_pages/user.html'] assert context['verification_successful'] == False new_user = mg_globals.database.User.find_one( {'username': 'happygirl'}) @@ -201,7 +201,7 @@ def test_register_views(test_app): util.clear_test_template_context() test_app.get("%s?%s" % (path, get_params)) context = util.TEMPLATE_TEST_CONTEXT[ - 'mediagoblin/auth/verify_email.html'] + 'mediagoblin/user_pages/user.html'] assert context['verification_successful'] == True new_user = mg_globals.database.User.find_one( {'username': 'happygirl'}) diff --git a/mediagoblin/tests/test_celery_setup.py b/mediagoblin/tests/test_celery_setup.py index 8bf97ae4..b80cab49 100644 --- a/mediagoblin/tests/test_celery_setup.py +++ b/mediagoblin/tests/test_celery_setup.py @@ -16,8 +16,8 @@ import pkg_resources -from mediagoblin import celery_setup -from mediagoblin.config import read_mediagoblin_config +from mediagoblin.init import celery as celery_setup +from mediagoblin.init.config import read_mediagoblin_config TEST_CELERY_CONF_NOSPECIALDB = pkg_resources.resource_filename( diff --git a/mediagoblin/tests/test_config.py b/mediagoblin/tests/test_config.py index 244f05e5..f9f12072 100644 --- a/mediagoblin/tests/test_config.py +++ b/mediagoblin/tests/test_config.py @@ -16,7 +16,7 @@ import pkg_resources -from mediagoblin import config +from mediagoblin.init import config CARROT_CONF_GOOD = pkg_resources.resource_filename( diff --git a/mediagoblin/tests/test_mgoblin_app.ini b/mediagoblin/tests/test_mgoblin_app.ini index e022d47b..fd0f87a4 100644 --- a/mediagoblin/tests/test_mgoblin_app.ini +++ b/mediagoblin/tests/test_mgoblin_app.ini @@ -8,7 +8,7 @@ email_debug_mode = true db_name = __mediagoblin_tests__ # Celery shouldn't be set up by the application as it's setup via -# mediagoblin.celery_setup.from_celery +# mediagoblin.init.celery.from_celery celery_setup_elsewhere = true [celery] diff --git a/mediagoblin/tests/test_migrations.py b/mediagoblin/tests/test_migrations.py new file mode 100644 index 00000000..127b90e1 --- /dev/null +++ b/mediagoblin/tests/test_migrations.py @@ -0,0 +1,402 @@ +# GNU MediaGoblin -- federated, autonomous media hosting +# Copyright (C) 2011 Free Software Foundation, Inc +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + + +from nose.tools import assert_raises +from pymongo import Connection + +from mediagoblin.tests.tools import ( + install_fixtures_simple, assert_db_meets_expected) +from mediagoblin.db.util import ( + RegisterMigration, MigrationManager, ObjectId, + MissingCurrentMigration) + +# This one will get filled with local migrations +TEST_MIGRATION_REGISTRY = {} +# this one won't get filled +TEST_EMPTY_MIGRATION_REGISTRY = {} + +MIGRATION_DB_NAME = u'__mediagoblin_test_migrations__' + + +###################### +# Fake test migrations +###################### + +@RegisterMigration(1, TEST_MIGRATION_REGISTRY) +def creature_add_magical_powers(database): + """ + Add lists of magical powers. + + This defaults to [], an empty list. Since we haven't declared any + magical powers, all existing monsters should + """ + database['creatures'].update( + {'magical_powers': {'$exists': False}}, + {'$set': {'magical_powers': []}}, + multi=True) + + +@RegisterMigration(2, TEST_MIGRATION_REGISTRY) +def creature_rename_num_legs_to_num_limbs(database): + """ + It turns out we want to track how many limbs a creature has, not + just how many legs. We don't care about the ambiguous distinction + between arms/legs currently. + """ + # $rename not available till 1.7.2+, Debian Stable only includes + # 1.4.4... we should do renames manually for now :( + + collection = database['creatures'] + target = collection.find( + {'num_legs': {'$exists': True}}) + + for document in target: + # A lame manual renaming. + document['num_limbs'] = document.pop('num_legs') + collection.save(document) + + +@RegisterMigration(3, TEST_MIGRATION_REGISTRY) +def creature_remove_is_demon(database): + """ + It turns out we don't care much about whether creatures are demons + or not. + """ + database['creatures'].update( + {'is_demon': {'$exists': True}}, + {'$unset': {'is_demon': 1}}, + multi=True) + + +@RegisterMigration(4, TEST_MIGRATION_REGISTRY) +def level_exits_dict_to_list(database): + """ + For the sake of the indexes we want to write, and because we + intend to add more flexible fields, we want to move level exits + from like: + + {'big_door': 'castle_level_id', + 'trapdoor': 'dungeon_level_id'} + + to like: + + [{'name': 'big_door', + 'exits_to': 'castle_level_id'}, + {'name': 'trapdoor', + 'exits_to': 'dungeon_level_id'}] + """ + collection = database['levels'] + target = collection.find( + {'exits': {'$type': 3}}) + + for level in target: + new_exits = [] + for exit_name, exits_to in level['exits'].items(): + new_exits.append( + {'name': exit_name, + 'exits_to': exits_to}) + + level['exits'] = new_exits + collection.save(level) + + +CENTIPEDE_OBJECTID = ObjectId() +WOLF_OBJECTID = ObjectId() +WIZARDSNAKE_OBJECTID = ObjectId() + +UNMIGRATED_DBDATA = { + 'creatures': [ + {'_id': CENTIPEDE_OBJECTID, + 'name': 'centipede', + 'num_legs': 100, + 'is_demon': False}, + {'_id': WOLF_OBJECTID, + 'name': 'wolf', + 'num_legs': 4, + 'is_demon': False}, + # don't ask me what a wizardsnake is. + {'_id': WIZARDSNAKE_OBJECTID, + 'name': 'wizardsnake', + 'num_legs': 0, + 'is_demon': True}], + 'levels': [ + {'_id': 'necroplex', + 'name': 'The Necroplex', + 'description': 'A complex full of pure deathzone.', + 'exits': { + 'deathwell': 'evilstorm', + 'portal': 'central_park'}}, + {'_id': 'evilstorm', + 'name': 'Evil Storm', + 'description': 'A storm full of pure evil.', + 'exits': {}}, # you can't escape the evilstorm + {'_id': 'central_park', + 'name': 'Central Park, NY, NY', + 'description': "New York's friendly Central Park.", + 'exits': { + 'portal': 'necroplex'}}]} + + +EXPECTED_POST_MIGRATION_UNMIGRATED_DBDATA = { + 'creatures': [ + {'_id': CENTIPEDE_OBJECTID, + 'name': 'centipede', + 'num_limbs': 100, + 'magical_powers': []}, + {'_id': WOLF_OBJECTID, + 'name': 'wolf', + 'num_limbs': 4, + # kept around namely to check that it *isn't* removed! + 'magical_powers': []}, + {'_id': WIZARDSNAKE_OBJECTID, + 'name': 'wizardsnake', + 'num_limbs': 0, + 'magical_powers': []}], + 'levels': [ + {'_id': 'necroplex', + 'name': 'The Necroplex', + 'description': 'A complex full of pure deathzone.', + 'exits': [ + {'name': 'deathwell', + 'exits_to': 'evilstorm'}, + {'name': 'portal', + 'exits_to': 'central_park'}]}, + {'_id': 'evilstorm', + 'name': 'Evil Storm', + 'description': 'A storm full of pure evil.', + 'exits': []}, # you can't escape the evilstorm + {'_id': 'central_park', + 'name': 'Central Park, NY, NY', + 'description': "New York's friendly Central Park.", + 'exits': [ + {'name': 'portal', + 'exits_to': 'necroplex'}]}]} + +# We want to make sure that if we're at migration 3, migration 3 +# doesn't get re-run. + +SEMI_MIGRATED_DBDATA = { + 'creatures': [ + {'_id': CENTIPEDE_OBJECTID, + 'name': 'centipede', + 'num_limbs': 100, + 'magical_powers': []}, + {'_id': WOLF_OBJECTID, + 'name': 'wolf', + 'num_limbs': 4, + # kept around namely to check that it *isn't* removed! + 'is_demon': False, + 'magical_powers': [ + 'ice_breath', 'death_stare']}, + {'_id': WIZARDSNAKE_OBJECTID, + 'name': 'wizardsnake', + 'num_limbs': 0, + 'magical_powers': [ + 'death_rattle', 'sneaky_stare', + 'slithery_smoke', 'treacherous_tremors'], + 'is_demon': True}], + 'levels': [ + {'_id': 'necroplex', + 'name': 'The Necroplex', + 'description': 'A complex full of pure deathzone.', + 'exits': { + 'deathwell': 'evilstorm', + 'portal': 'central_park'}}, + {'_id': 'evilstorm', + 'name': 'Evil Storm', + 'description': 'A storm full of pure evil.', + 'exits': {}}, # you can't escape the evilstorm + {'_id': 'central_park', + 'name': 'Central Park, NY, NY', + 'description': "New York's friendly Central Park.", + 'exits': { + 'portal': 'necroplex'}}]} + + +EXPECTED_POST_MIGRATION_SEMI_MIGRATED_DBDATA = { + 'creatures': [ + {'_id': CENTIPEDE_OBJECTID, + 'name': 'centipede', + 'num_limbs': 100, + 'magical_powers': []}, + {'_id': WOLF_OBJECTID, + 'name': 'wolf', + 'num_limbs': 4, + # kept around namely to check that it *isn't* removed! + 'is_demon': False, + 'magical_powers': [ + 'ice_breath', 'death_stare']}, + {'_id': WIZARDSNAKE_OBJECTID, + 'name': 'wizardsnake', + 'num_limbs': 0, + 'magical_powers': [ + 'death_rattle', 'sneaky_stare', + 'slithery_smoke', 'treacherous_tremors'], + 'is_demon': True}], + 'levels': [ + {'_id': 'necroplex', + 'name': 'The Necroplex', + 'description': 'A complex full of pure deathzone.', + 'exits': [ + {'name': 'deathwell', + 'exits_to': 'evilstorm'}, + {'name': 'portal', + 'exits_to': 'central_park'}]}, + {'_id': 'evilstorm', + 'name': 'Evil Storm', + 'description': 'A storm full of pure evil.', + 'exits': []}, # you can't escape the evilstorm + {'_id': 'central_park', + 'name': 'Central Park, NY, NY', + 'description': "New York's friendly Central Park.", + 'exits': [ + {'name': 'portal', + 'exits_to': 'necroplex'}]}]} + + +class TestMigrations(object): + def setUp(self): + # Set up the connection, drop an existing possible database + self.connection = Connection() + self.connection.drop_database(MIGRATION_DB_NAME) + self.db = Connection()[MIGRATION_DB_NAME] + self.migration_manager = MigrationManager( + self.db, TEST_MIGRATION_REGISTRY) + self.empty_migration_manager = MigrationManager( + self.db, TEST_EMPTY_MIGRATION_REGISTRY) + self.run_migrations = [] + + def tearDown(self): + self.connection.drop_database(MIGRATION_DB_NAME) + + def _record_migration(self, migration_number, migration_func): + self.run_migrations.append((migration_number, migration_func)) + + def test_migrations_registered_and_sorted(self): + """ + Make sure that migrations get registered and are sorted right + in the migration manager + """ + assert TEST_MIGRATION_REGISTRY == { + 1: creature_add_magical_powers, + 2: creature_rename_num_legs_to_num_limbs, + 3: creature_remove_is_demon, + 4: level_exits_dict_to_list} + assert self.migration_manager.sorted_migrations == [ + (1, creature_add_magical_powers), + (2, creature_rename_num_legs_to_num_limbs), + (3, creature_remove_is_demon), + (4, level_exits_dict_to_list)] + assert self.empty_migration_manager.sorted_migrations == [] + + def test_run_full_migrations(self): + """ + Make sure that running the full migration suite from 0 updates + everything + """ + self.migration_manager.set_current_migration(0) + assert self.migration_manager.database_current_migration() == 0 + install_fixtures_simple(self.db, UNMIGRATED_DBDATA) + self.migration_manager.migrate_new(post_callback=self._record_migration) + + assert self.run_migrations == [ + (1, creature_add_magical_powers), + (2, creature_rename_num_legs_to_num_limbs), + (3, creature_remove_is_demon), + (4, level_exits_dict_to_list)] + + assert_db_meets_expected( + self.db, EXPECTED_POST_MIGRATION_UNMIGRATED_DBDATA) + + # Make sure the migration is recorded correctly + assert self.migration_manager.database_current_migration() == 4 + + # run twice! It should do nothing the second time. + # ------------------------------------------------ + self.run_migrations = [] + self.migration_manager.migrate_new(post_callback=self._record_migration) + assert self.run_migrations == [] + assert_db_meets_expected( + self.db, EXPECTED_POST_MIGRATION_UNMIGRATED_DBDATA) + assert self.migration_manager.database_current_migration() == 4 + + + def test_run_partial_migrations(self): + """ + Make sure that running full migration suite from 3 only runs + last migration + """ + self.migration_manager.set_current_migration(3) + assert self.migration_manager.database_current_migration() == 3 + install_fixtures_simple(self.db, SEMI_MIGRATED_DBDATA) + self.migration_manager.migrate_new(post_callback=self._record_migration) + + assert self.run_migrations == [ + (4, level_exits_dict_to_list)] + + assert_db_meets_expected( + self.db, EXPECTED_POST_MIGRATION_SEMI_MIGRATED_DBDATA) + + # Make sure the migration is recorded correctly + assert self.migration_manager.database_current_migration() == 4 + + def test_migrations_recorded_as_latest(self): + """ + Make sure that if we don't have a migration_status + pre-recorded it's marked as the latest + """ + self.migration_manager.install_migration_version_if_missing() + assert self.migration_manager.database_current_migration() == 4 + + def test_no_migrations_recorded_as_zero(self): + """ + Make sure that if we don't have a migration_status + but there *are* no migrations that it's marked as 0 + """ + self.empty_migration_manager.install_migration_version_if_missing() + assert self.empty_migration_manager.database_current_migration() == 0 + + def test_migrations_to_run(self): + """ + Make sure we get the right list of migrations to run + """ + self.migration_manager.set_current_migration(0) + + assert self.migration_manager.migrations_to_run() == [ + (1, creature_add_magical_powers), + (2, creature_rename_num_legs_to_num_limbs), + (3, creature_remove_is_demon), + (4, level_exits_dict_to_list)] + + self.migration_manager.set_current_migration(3) + + assert self.migration_manager.migrations_to_run() == [ + (4, level_exits_dict_to_list)] + + self.migration_manager.set_current_migration(4) + + assert self.migration_manager.migrations_to_run() == [] + + + def test_no_migrations_raises_exception(self): + """ + If we don't have the current migration set in the database, + this should error out. + """ + assert_raises( + MissingCurrentMigration, + self.migration_manager.migrations_to_run) diff --git a/mediagoblin/tests/test_submission.py b/mediagoblin/tests/test_submission.py new file mode 100644 index 00000000..22b6117c --- /dev/null +++ b/mediagoblin/tests/test_submission.py @@ -0,0 +1,157 @@ +# GNU MediaGoblin -- federated, autonomous media hosting +# Copyright (C) 2011 Free Software Foundation, Inc +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +import urlparse +import pkg_resources + +from nose.tools import assert_equal + +from mediagoblin.auth import lib as auth_lib +from mediagoblin.tests.tools import setup_fresh_app, get_test_app +from mediagoblin import mg_globals +from mediagoblin import util + +GOOD_JPG = pkg_resources.resource_filename( + 'mediagoblin.tests', 'test_submission/good.jpg') +GOOD_PNG = pkg_resources.resource_filename( + 'mediagoblin.tests', 'test_submission/good.png') +EVIL_FILE = pkg_resources.resource_filename( + 'mediagoblin.tests', 'test_submission/evil') +EVIL_JPG = pkg_resources.resource_filename( + 'mediagoblin.tests', 'test_submission/evil.jpg') +EVIL_PNG = pkg_resources.resource_filename( + 'mediagoblin.tests', 'test_submission/evil.png') + + +class TestSubmission: + def setUp(self): + self.test_app = get_test_app() + + # TODO: Possibly abstract into a decorator like: + # @as_authenticated_user('chris') + test_user = mg_globals.database.User() + test_user['username'] = u'chris' + test_user['email'] = u'chris@example.com' + test_user['email_verified'] = True + test_user['status'] = u'active' + test_user['pw_hash'] = auth_lib.bcrypt_gen_password_hash('toast') + test_user.save() + + self.test_app.post( + '/auth/login/', { + 'username': u'chris', + 'password': 'toast'}) + + def test_missing_fields(self): + # Test blank form + # --------------- + util.clear_test_template_context() + response = self.test_app.post( + '/submit/', {}) + context = util.TEMPLATE_TEST_CONTEXT['mediagoblin/submit/start.html'] + form = context['submit_form'] + assert form.file.errors == [u'You must provide a file.'] + + # Test blank file + # --------------- + util.clear_test_template_context() + response = self.test_app.post( + '/submit/', { + 'title': 'test title'}) + context = util.TEMPLATE_TEST_CONTEXT['mediagoblin/submit/start.html'] + form = context['submit_form'] + assert form.file.errors == [u'You must provide a file.'] + + + def test_normal_uploads(self): + # Test JPG + # -------- + util.clear_test_template_context() + response = self.test_app.post( + '/submit/', { + 'title': 'Normal upload 1' + }, upload_files=[( + 'file', GOOD_JPG)]) + + # User should be redirected + response.follow() + assert_equal( + urlparse.urlsplit(response.location)[2], + '/u/chris/') + assert util.TEMPLATE_TEST_CONTEXT.has_key( + 'mediagoblin/user_pages/user.html') + + # Test PNG + # -------- + util.clear_test_template_context() + response = self.test_app.post( + '/submit/', { + 'title': 'Normal upload 2' + }, upload_files=[( + 'file', GOOD_PNG)]) + + response.follow() + assert_equal( + urlparse.urlsplit(response.location)[2], + '/u/chris/') + assert util.TEMPLATE_TEST_CONTEXT.has_key( + 'mediagoblin/user_pages/user.html') + + + def test_malicious_uploads(self): + # Test non-suppoerted file with non-supported extension + # ----------------------------------------------------- + util.clear_test_template_context() + response = self.test_app.post( + '/submit/', { + 'title': 'Malicious Upload 2' + }, upload_files=[( + 'file', EVIL_FILE)]) + + context = util.TEMPLATE_TEST_CONTEXT['mediagoblin/submit/start.html'] + form = context['submit_form'] + assert form.file.errors == ['The file doesn\'t seem to be an image!'] + + # NOTE: The following 2 tests will fail. These can be uncommented + # after http://bugs.foocorp.net/issues/324 is resolved and + # bad files are handled properly. + + # Test non-supported file with .jpg extension + # ------------------------------------------- + #util.clear_test_template_context() + #response = self.test_app.post( + # '/submit/', { + # 'title': 'Malicious Upload 2' + # }, upload_files=[( + # 'file', EVIL_JPG)]) + + #context = util.TEMPLATE_TEST_CONTEXT['mediagoblin/submit/start.html'] + #form = context['submit_form'] + #assert form.file.errors == ['The file doesn\'t seem to be an image!'] + + # Test non-supported file with .png extension + # ------------------------------------------- + #util.clear_test_template_context() + #response = self.test_app.post( + # '/submit/', { + # 'title': 'Malicious Upload 3' + # }, upload_files=[( + # 'file', EVIL_PNG)]) + + #context = util.TEMPLATE_TEST_CONTEXT['mediagoblin/submit/start.html'] + #form = context['submit_form'] + #assert form.file.errors == ['The file doesn\'t seem to be an image!'] + diff --git a/mediagoblin/tests/test_submission/evil b/mediagoblin/tests/test_submission/evil Binary files differnew file mode 100755 index 00000000..775da664 --- /dev/null +++ b/mediagoblin/tests/test_submission/evil diff --git a/mediagoblin/tests/test_submission/evil.jpg b/mediagoblin/tests/test_submission/evil.jpg Binary files differnew file mode 100755 index 00000000..775da664 --- /dev/null +++ b/mediagoblin/tests/test_submission/evil.jpg diff --git a/mediagoblin/tests/test_submission/evil.png b/mediagoblin/tests/test_submission/evil.png Binary files differnew file mode 100755 index 00000000..775da664 --- /dev/null +++ b/mediagoblin/tests/test_submission/evil.png diff --git a/mediagoblin/tests/test_submission/good.jpg b/mediagoblin/tests/test_submission/good.jpg Binary files differnew file mode 100644 index 00000000..936458e9 --- /dev/null +++ b/mediagoblin/tests/test_submission/good.jpg diff --git a/mediagoblin/tests/test_submission/good.png b/mediagoblin/tests/test_submission/good.png Binary files differnew file mode 100644 index 00000000..c1eadf9c --- /dev/null +++ b/mediagoblin/tests/test_submission/good.png diff --git a/mediagoblin/tests/tools.py b/mediagoblin/tests/tools.py index 64f773f0..4b61f259 100644 --- a/mediagoblin/tests/tools.py +++ b/mediagoblin/tests/tools.py @@ -22,7 +22,7 @@ from paste.deploy import loadapp from webtest import TestApp from mediagoblin import util -from mediagoblin.config import read_mediagoblin_config +from mediagoblin.init.config import read_mediagoblin_config from mediagoblin.decorators import _make_safe from mediagoblin.db.open import setup_connection_and_db_from_config @@ -42,8 +42,8 @@ USER_DEV_DIRECTORIES_TO_SETUP = [ BAD_CELERY_MESSAGE = """\ Sorry, you *absolutely* must run nosetests with the -mediagoblin.celery_setup.from_tests module. Like so: -$ CELERY_CONFIG_MODULE=mediagoblin.celery_setup.from_tests ./bin/nosetests""" +mediagoblin.init.celery.from_tests module. Like so: +$ CELERY_CONFIG_MODULE=mediagoblin.init.celery.from_tests ./bin/nosetests""" class BadCeleryEnviron(Exception): pass @@ -51,7 +51,7 @@ class BadCeleryEnviron(Exception): pass def suicide_if_bad_celery_environ(): if not os.environ.get('CELERY_CONFIG_MODULE') == \ - 'mediagoblin.celery_setup.from_tests': + 'mediagoblin.init.celery.from_tests': raise BadCeleryEnviron(BAD_CELERY_MESSAGE) @@ -59,7 +59,7 @@ def get_test_app(dump_old_app=True): suicide_if_bad_celery_environ() # Leave this imported as it sets up celery. - from mediagoblin.celery_setup import from_tests + from mediagoblin.init.celery import from_tests global MGOBLIN_APP @@ -118,3 +118,35 @@ def setup_fresh_app(func): return func(test_app, *args, **kwargs) return _make_safe(wrapper, func) + + +def install_fixtures_simple(db, fixtures): + """ + Very simply install fixtures in the database + """ + for collection_name, collection_fixtures in fixtures.iteritems(): + collection = db[collection_name] + for fixture in collection_fixtures: + collection.insert(fixture) + + +def assert_db_meets_expected(db, expected): + """ + Assert a database contains the things we expect it to. + + Objects are found via '_id', so you should make sure your document + has an _id. + + Args: + - db: pymongo or mongokit database connection + - expected: the data we expect. Formatted like: + {'collection_name': [ + {'_id': 'foo', + 'some_field': 'some_value'},]} + """ + for collection_name, collection_data in expected.iteritems(): + collection = db[collection_name] + for expected_document in collection_data: + document = collection.find_one({'_id': expected_document['_id']}) + assert document is not None # make sure it exists + assert document == expected_document # make sure it matches |