', html_module.data)
def test_course_handouts_rewrites(self):
- module_store = modulestore('direct')
+ module_store = modulestore()
# import a test course
- _, course_items = import_from_xml(module_store, 'common/test/data/', ['toy'])
+ _, course_items = import_from_xml(module_store, self.user.id, 'common/test/data/', ['toy'])
course_id = course_items[0].id
handouts_location = course_id.make_usage_key('course_info', 'handouts')
@@ -1124,35 +1124,43 @@ class ContentStoreToyCourseTest(ModuleStoreTestCase):
self.assertContains(resp, '/c4x/edX/toy/asset/handouts_sample_handout.txt')
def test_prefetch_children(self):
- module_store = modulestore('direct')
- import_from_xml(module_store, 'common/test/data/', ['toy'])
+ mongo_store = modulestore()._get_modulestore_by_type(MONGO_MODULESTORE_TYPE)
+ import_from_xml(modulestore(), self.user.id, 'common/test/data/', ['toy'])
course_id = SlashSeparatedCourseKey('edX', 'toy', '2012_Fall')
- wrapper = MongoCollectionFindWrapper(module_store.collection.find)
- module_store.collection.find = wrapper.find
- print module_store.metadata_inheritance_cache_subsystem
- print module_store.request_cache
- course = module_store.get_course(course_id, depth=2)
+ wrapper = MongoCollectionFindWrapper(mongo_store.collection.find)
+ mongo_store.collection.find = wrapper.find
- # make sure we haven't done too many round trips to DB
- # note we say 3 round trips here for 1) the course, and 2 & 3) for the chapters and sequentials
- # Because we're querying from the top of the tree, we cache information needed for inheritance,
- # so we don't need to make an extra query to compute it.
- self.assertEqual(wrapper.counter, 3)
+ # set the branch to 'publish' in order to prevent extra lookups of draft versions
+ with store_branch_setting(mongo_store, BRANCH_PUBLISHED_ONLY):
+ course = mongo_store.get_course(course_id, depth=2)
- # make sure we pre-fetched a known sequential which should be at depth=2
- self.assertTrue(course_id.make_usage_key('sequential', 'vertical_sequential') in course.system.module_data)
+ # make sure we haven't done too many round trips to DB
+ # note we say 3 round trips here for 1) the course, and 2 & 3) for the chapters and sequentials
+ # Because we're querying from the top of the tree, we cache information needed for inheritance,
+ # so we don't need to make an extra query to compute it.
+ self.assertEqual(wrapper.counter, 3)
+
+ # make sure we pre-fetched a known sequential which should be at depth=2
+ self.assertTrue(course_id.make_usage_key('sequential', 'vertical_sequential') in course.system.module_data)
+
+ # make sure we don't have a specific vertical which should be at depth=3
+ self.assertFalse(course_id.make_usage_key('vertical', 'vertical_test') in course.system.module_data)
+
+ # Now, test with the branch set to draft. We should have one extra round trip call to check for
+ # the existence of the draft versions
+ wrapper.counter = 0
+ mongo_store.get_course(course_id, depth=2)
+ self.assertEqual(wrapper.counter, 4)
- # make sure we don't have a specific vertical which should be at depth=3
- self.assertFalse(course_id.make_usage_key('vertical', 'vertical_test') in course.system.module_data)
def test_export_course_without_content_store(self):
- module_store = modulestore('direct')
+ module_store = modulestore()
content_store = contentstore()
# Create toy course
- _, course_items = import_from_xml(module_store, 'common/test/data/', ['toy'])
+ _, course_items = import_from_xml(module_store, self.user.id, 'common/test/data/', ['toy'])
course_id = course_items[0].id
root_dir = path(mkdtemp_clean())
@@ -1165,8 +1173,7 @@ class ContentStoreToyCourseTest(ModuleStoreTestCase):
delete_course(module_store, content_store, course_id, commit=True)
import_from_xml(
- module_store, root_dir, ['test_export_no_content_store'],
- draft_store=None,
+ module_store, self.user.id, root_dir, ['test_export_no_content_store'],
static_content_store=None,
target_course_id=course_id
)
@@ -1190,8 +1197,7 @@ class ContentStoreToyCourseTest(ModuleStoreTestCase):
_test_no_locations(self, resp)
-@override_settings(CONTENTSTORE=TEST_DATA_CONTENTSTORE, MODULESTORE=TEST_MODULESTORE)
-class ContentStoreTest(ModuleStoreTestCase):
+class ContentStoreTest(ContentStoreTestCase):
"""
Tests for the CMS ContentStore application.
"""
@@ -1536,7 +1542,7 @@ class ContentStoreTest(ModuleStoreTestCase):
self.assertEqual(resp.status_code, 200)
payload = parse_json(resp)
problem_loc = UsageKey.from_string(payload['locator'])
- problem = get_modulestore(problem_loc).get_item(problem_loc)
+ problem = modulestore().get_item(problem_loc)
# should be a CapaDescriptor
self.assertIsInstance(problem, CapaDescriptor, "New problem is not a CapaDescriptor")
context = problem.get_context()
@@ -1557,7 +1563,7 @@ class ContentStoreTest(ModuleStoreTestCase):
self.assertEqual(resp.status_code, 200)
_test_no_locations(self, resp)
- _, course_items = import_from_xml(modulestore('direct'), 'common/test/data/', ['simple'])
+ _, course_items = import_from_xml(modulestore(), self.user.id, 'common/test/data/', ['simple'])
course_key = course_items[0].id
resp = self._show_course_overview(course_key)
@@ -1609,11 +1615,11 @@ class ContentStoreTest(ModuleStoreTestCase):
delete_item(category='chapter', name='chapter_2')
def test_import_into_new_course_id(self):
- module_store = modulestore('direct')
+ module_store = modulestore()
target_course_id = _get_course_id(self.course_data)
_create_course(self, target_course_id, self.course_data)
- import_from_xml(module_store, 'common/test/data/', ['toy'], target_course_id=target_course_id)
+ import_from_xml(module_store, self.user.id, 'common/test/data/', ['toy'], target_course_id=target_course_id)
modules = module_store.get_items(target_course_id)
@@ -1634,7 +1640,7 @@ class ContentStoreTest(ModuleStoreTestCase):
self.assertEqual(course_module.pdf_textbooks[0]["chapters"][1]["url"], '/static/Chapter2.pdf')
def test_import_into_new_course_id_wiki_slug_renamespacing(self):
- module_store = modulestore('direct')
+ module_store = modulestore()
# If reimporting into the same course do not change the wiki_slug.
target_course_id = SlashSeparatedCourseKey('edX', 'toy', '2012_Fall')
@@ -1650,7 +1656,7 @@ class ContentStoreTest(ModuleStoreTestCase):
course_module.save()
# Import a course with wiki_slug == location.course
- import_from_xml(module_store, 'common/test/data/', ['toy'], target_course_id=target_course_id)
+ import_from_xml(module_store, self.user.id, 'common/test/data/', ['toy'], target_course_id=target_course_id)
course_module = module_store.get_course(target_course_id)
self.assertEquals(course_module.wiki_slug, 'toy')
@@ -1665,18 +1671,18 @@ class ContentStoreTest(ModuleStoreTestCase):
_create_course(self, target_course_id, course_data)
# Import a course with wiki_slug == location.course
- import_from_xml(module_store, 'common/test/data/', ['toy'], target_course_id=target_course_id)
+ import_from_xml(module_store, self.user.id, 'common/test/data/', ['toy'], target_course_id=target_course_id)
course_module = module_store.get_course(target_course_id)
self.assertEquals(course_module.wiki_slug, 'MITx.999.2013_Spring')
# Now try importing a course with wiki_slug == '{0}.{1}.{2}'.format(location.org, location.course, location.run)
- import_from_xml(module_store, 'common/test/data/', ['two_toys'], target_course_id=target_course_id)
+ import_from_xml(module_store, self.user.id, 'common/test/data/', ['two_toys'], target_course_id=target_course_id)
course_module = module_store.get_course(target_course_id)
self.assertEquals(course_module.wiki_slug, 'MITx.999.2013_Spring')
def test_import_metadata_with_attempts_empty_string(self):
- module_store = modulestore('direct')
- import_from_xml(module_store, 'common/test/data/', ['simple'])
+ module_store = modulestore()
+ import_from_xml(module_store, self.user.id, 'common/test/data/', ['simple'])
did_load_item = False
try:
course_key = SlashSeparatedCourseKey('edX', 'simple', 'problem')
@@ -1690,20 +1696,20 @@ class ContentStoreTest(ModuleStoreTestCase):
self.assertTrue(did_load_item)
def test_forum_id_generation(self):
- module_store = modulestore('direct')
+ module_store = modulestore()
course = CourseFactory.create(org='edX', course='999', display_name='Robot Super Course')
new_component_location = course.id.make_usage_key('discussion', 'new_component')
# crate a new module and add it as a child to a vertical
- module_store.create_and_save_xmodule(new_component_location)
+ module_store.create_and_save_xmodule(new_component_location, self.user.id)
new_discussion_item = module_store.get_item(new_component_location)
self.assertNotEquals(new_discussion_item.discussion_id, '$$GUID$$')
def test_metadata_inheritance(self):
- module_store = modulestore('direct')
- _, course_items = import_from_xml(module_store, 'common/test/data/', ['toy'])
+ module_store = modulestore()
+ _, course_items = import_from_xml(module_store, self.user.id, 'common/test/data/', ['toy'])
course = course_items[0]
verticals = module_store.get_items(course.id, category='vertical')
@@ -1718,13 +1724,13 @@ class ContentStoreTest(ModuleStoreTestCase):
new_component_location = course.id.make_usage_key('html', 'new_component')
# crate a new module and add it as a child to a vertical
- module_store.create_and_save_xmodule(new_component_location)
+ new_object = module_store.create_xmodule(new_component_location)
+ module_store.update_item(new_object, self.user.id, allow_not_found=True)
parent = verticals[0]
parent.children.append(new_component_location)
module_store.update_item(parent, self.user.id)
# flush the cache
- module_store.refresh_cached_metadata_inheritance_tree(new_component_location.course_key)
new_module = module_store.get_item(new_component_location)
# check for grace period definition which should be defined at the course level
@@ -1741,7 +1747,6 @@ class ContentStoreTest(ModuleStoreTestCase):
module_store.update_item(new_module, self.user.id)
# flush the cache and refetch
- module_store.refresh_cached_metadata_inheritance_tree(new_component_location.course_key)
new_module = module_store.get_item(new_component_location)
self.assertEqual(timedelta(1), new_module.graceperiod)
@@ -1759,7 +1764,7 @@ class ContentStoreTest(ModuleStoreTestCase):
self.assertGreaterEqual(len(course.checklists), 4)
# by fetching
- module_store = modulestore('direct')
+ module_store = modulestore()
fetched_course = module_store.get_item(course.location)
fetched_item = module_store.get_item(vertical.location)
self.assertIsNotNone(fetched_course.start)
@@ -1771,13 +1776,14 @@ class ContentStoreTest(ModuleStoreTestCase):
def test_image_import(self):
"""Test backwards compatibilty of course image."""
- module_store = modulestore('direct')
+ module_store = modulestore()
content_store = contentstore()
# Use conditional_and_poll, as it's got an image already
import_from_xml(
module_store,
+ self.user.id,
'common/test/data/',
['conditional_and_poll'],
static_content_store=content_store
@@ -1805,15 +1811,16 @@ class ContentStoreTest(ModuleStoreTestCase):
course_key = _get_course_id(self.course_data)
_create_course(self, course_key, self.course_data)
- course_module = modulestore('direct').get_course(course_key)
+ course_module = modulestore().get_course(course_key)
self.assertEquals(course_module.wiki_slug, 'MITx.999.2013_Spring')
-@override_settings(MODULESTORE=TEST_MODULESTORE)
-class MetadataSaveTestCase(ModuleStoreTestCase):
+class MetadataSaveTestCase(ContentStoreTestCase):
"""Test that metadata is correctly cached and decached."""
def setUp(self):
+ super(MetadataSaveTestCase, self).setUp()
+
course = CourseFactory.create(
org='edX', course='999', display_name='Robot Super Course')
@@ -1857,8 +1864,8 @@ class MetadataSaveTestCase(ModuleStoreTestCase):
delattr(self.video_descriptor, field_name)
self.assertNotIn('html5_sources', own_metadata(self.video_descriptor))
- get_modulestore(location).update_item(self.video_descriptor, '**replace_user**')
- module = get_modulestore(location).get_item(location)
+ modulestore().update_item(self.video_descriptor, self.user.id)
+ module = modulestore().get_item(location)
self.assertNotIn('html5_sources', own_metadata(module))
diff --git a/cms/djangoapps/contentstore/tests/test_course_listing.py b/cms/djangoapps/contentstore/tests/test_course_listing.py
index b0b378a21d..387b2678e5 100644
--- a/cms/djangoapps/contentstore/tests/test_course_listing.py
+++ b/cms/djangoapps/contentstore/tests/test_course_listing.py
@@ -16,7 +16,8 @@ from contentstore.tests.utils import AjaxEnabledTestClient
from student.tests.factories import UserFactory
from student.roles import CourseInstructorRole, CourseStaffRole, GlobalStaff, OrgStaffRole, OrgInstructorRole
from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase
-from xmodule.modulestore.tests.factories import CourseFactory
+from xmodule.modulestore.tests.factories import CourseFactory, check_mongo_calls
+from xmodule.modulestore import MONGO_MODULESTORE_TYPE
from opaque_keys.edx.locations import SlashSeparatedCourseKey
from xmodule.modulestore.django import modulestore
from xmodule.error_module import ErrorDescriptor
@@ -197,6 +198,14 @@ class TestCourseListing(ModuleStoreTestCase):
self.assertGreaterEqual(iteration_over_courses_time_1.elapsed, iteration_over_groups_time_1.elapsed)
self.assertGreaterEqual(iteration_over_courses_time_2.elapsed, iteration_over_groups_time_2.elapsed)
+ # Now count the db queries
+ store = modulestore()._get_modulestore_by_type(MONGO_MODULESTORE_TYPE)
+ with check_mongo_calls(store.collection, USER_COURSES_COUNT):
+ courses_list = _accessible_courses_list_from_groups(self.request)
+
+ with check_mongo_calls(store.collection, 1):
+ courses_list = _accessible_courses_list(self.request)
+
def test_get_course_list_with_same_course_id(self):
"""
Test getting courses with same id but with different name case. Then try to delete one of them and
@@ -253,18 +262,20 @@ class TestCourseListing(ModuleStoreTestCase):
Create good courses, courses that won't load, and deleted courses which still have
roles. Test course listing.
"""
+ store = modulestore()._get_modulestore_by_type(MONGO_MODULESTORE_TYPE)
+
course_location = SlashSeparatedCourseKey('testOrg', 'testCourse', 'RunBabyRun')
self._create_course_with_access_groups(course_location, self.user)
course_location = SlashSeparatedCourseKey('testOrg', 'doomedCourse', 'RunBabyRun')
self._create_course_with_access_groups(course_location, self.user)
- modulestore().delete_course(course_location)
+ store.delete_course(course_location)
course_location = SlashSeparatedCourseKey('testOrg', 'erroredCourse', 'RunBabyRun')
course = self._create_course_with_access_groups(course_location, self.user)
- course_db_record = modulestore()._find_one(course.location)
+ course_db_record = store._find_one(course.location)
course_db_record.setdefault('metadata', {}).get('tabs', []).append({"type": "wiko", "name": "Wiki" })
- modulestore().collection.update(
+ store.collection.update(
{'_id': course.location.to_deprecated_son()},
{'$set': {
'metadata.tabs': course_db_record['metadata']['tabs'],
diff --git a/cms/djangoapps/contentstore/tests/test_course_settings.py b/cms/djangoapps/contentstore/tests/test_course_settings.py
index 978209c526..8192b5fb70 100644
--- a/cms/djangoapps/contentstore/tests/test_course_settings.py
+++ b/cms/djangoapps/contentstore/tests/test_course_settings.py
@@ -11,7 +11,7 @@ from django.test.utils import override_settings
from models.settings.course_details import (CourseDetails, CourseSettingsEncoder)
from models.settings.course_grading import CourseGradingModel
-from contentstore.utils import get_modulestore, EXTRA_TAB_PANELS, reverse_course_url, reverse_usage_url
+from contentstore.utils import EXTRA_TAB_PANELS, reverse_course_url, reverse_usage_url
from xmodule.modulestore.tests.factories import CourseFactory
from models.settings.course_metadata import CourseMetadata
@@ -335,7 +335,7 @@ class CourseGradingTest(CourseTestCase):
def test_update_section_grader_type(self):
# Get the descriptor and the section_grader_type and assert they are the default values
- descriptor = get_modulestore(self.course.location).get_item(self.course.location)
+ descriptor = modulestore().get_item(self.course.location)
section_grader_type = CourseGradingModel.get_section_grader_type(self.course.location)
self.assertEqual('notgraded', section_grader_type['graderType'])
@@ -344,7 +344,7 @@ class CourseGradingTest(CourseTestCase):
# Change the default grader type to Homework, which should also mark the section as graded
CourseGradingModel.update_section_grader_type(self.course, 'Homework', self.user)
- descriptor = get_modulestore(self.course.location).get_item(self.course.location)
+ descriptor = modulestore().get_item(self.course.location)
section_grader_type = CourseGradingModel.get_section_grader_type(self.course.location)
self.assertEqual('Homework', section_grader_type['graderType'])
@@ -353,7 +353,7 @@ class CourseGradingTest(CourseTestCase):
# Change the grader type back to notgraded, which should also unmark the section as graded
CourseGradingModel.update_section_grader_type(self.course, 'notgraded', self.user)
- descriptor = get_modulestore(self.course.location).get_item(self.course.location)
+ descriptor = modulestore().get_item(self.course.location)
section_grader_type = CourseGradingModel.get_section_grader_type(self.course.location)
self.assertEqual('notgraded', section_grader_type['graderType'])
@@ -413,8 +413,7 @@ class CourseGradingTest(CourseTestCase):
Populate the course, grab a section, get the url for the assignment type access
"""
self.populate_course()
- sequential_usage_key = self.course.id.make_usage_key("sequential", None)
- sections = get_modulestore(self.course.id).get_items(sequential_usage_key)
+ sections = modulestore().get_items(self.course.id, category="sequential")
# see if test makes sense
self.assertGreater(len(sections), 0, "No sections found")
section = sections[0] # just take the first one
@@ -470,7 +469,7 @@ class CourseMetadataEditingTest(CourseTestCase):
)
self.update_check(test_model)
# try fresh fetch to ensure persistence
- fresh = modulestore('direct').get_course(self.course.id)
+ fresh = modulestore().get_course(self.course.id)
test_model = CourseMetadata.fetch(fresh)
self.update_check(test_model)
# now change some of the existing metadata
diff --git a/cms/djangoapps/contentstore/tests/test_crud.py b/cms/djangoapps/contentstore/tests/test_crud.py
index 58b0291d49..9431016b6c 100644
--- a/cms/djangoapps/contentstore/tests/test_crud.py
+++ b/cms/djangoapps/contentstore/tests/test_crud.py
@@ -1,9 +1,11 @@
import unittest
from xmodule import templates
+from xmodule.modulestore import SPLIT_MONGO_MODULESTORE_TYPE, BRANCH_NAME_DRAFT
from xmodule.modulestore.tests import persistent_factories
from xmodule.course_module import CourseDescriptor
-from xmodule.modulestore.django import modulestore, loc_mapper, clear_existing_modulestores
+from xmodule.modulestore.django import modulestore, clear_existing_modulestores, _MIXED_MODULESTORE, \
+ loc_mapper, _loc_singleton
from xmodule.seq_module import SequenceDescriptor
from xmodule.capa_module import CapaDescriptor
from opaque_keys.edx.locator import BlockUsageLocator, LocalId
@@ -19,8 +21,9 @@ class TemplateTests(unittest.TestCase):
def setUp(self):
clear_existing_modulestores() # redundant w/ cleanup but someone was getting errors
- self.addCleanup(ModuleStoreTestCase.drop_mongo_collections, 'split')
+ self.addCleanup(ModuleStoreTestCase.drop_mongo_collections, SPLIT_MONGO_MODULESTORE_TYPE)
self.addCleanup(clear_existing_modulestores)
+ self.split_store = modulestore()._get_modulestore_by_type(SPLIT_MONGO_MODULESTORE_TYPE)
def test_get_templates(self):
found = templates.all_templates()
@@ -59,7 +62,7 @@ class TemplateTests(unittest.TestCase):
)
self.assertIsInstance(test_course, CourseDescriptor)
self.assertEqual(test_course.display_name, 'fun test course')
- index_info = modulestore('split').get_course_index_info(test_course.id)
+ index_info = self.split_store.get_course_index_info(test_course.id)
self.assertEqual(index_info['org'], 'testx')
self.assertEqual(index_info['offering'], 'tempcourse')
@@ -67,7 +70,7 @@ class TemplateTests(unittest.TestCase):
parent_location=test_course.location)
self.assertIsInstance(test_chapter, SequenceDescriptor)
# refetch parent which should now point to child
- test_course = modulestore('split').get_course(test_course.id.version_agnostic())
+ test_course = self.split_store.get_course(test_course.id.version_agnostic())
self.assertIn(test_chapter.location, test_course.children)
with self.assertRaises(DuplicateCourseError):
@@ -85,7 +88,7 @@ class TemplateTests(unittest.TestCase):
display_name='fun test course', user_id='testbot'
)
- test_chapter = modulestore('split').create_xblock(
+ test_chapter = self.split_store.create_xblock(
test_course.system, 'chapter', {'display_name': 'chapter n'}, parent_xblock=test_course
)
self.assertIsInstance(test_chapter, SequenceDescriptor)
@@ -94,7 +97,7 @@ class TemplateTests(unittest.TestCase):
# test w/ a definition (e.g., a problem)
test_def_content = 'Goodbye
", {'display_name': 'Parented Html'}, 'vertical', 'Vert1', split=False) - self._create_item( - 'discussion', 'Discussion1', - "discussion discussion_category=\"Lecture 1\" discussion_id=\"a08bfd89b2aa40fa81f2c650a9332846\" discussion_target=\"Lecture 1\"/>\n", - { - "discussion_category": "Lecture 1", - "discussion_target": "Lecture 1", - "display_name": "Lecture 1 Discussion", - "discussion_id": "a08bfd89b2aa40fa81f2c650a9332846" - }, - 'vertical', 'Vert1', - split=False - ) - self._create_item('html', 'Html2', "Hellow
", {'display_name': 'Hollow Html'}, 'vertical', 'Vert1', split=False) - self._create_item( - 'discussion', 'Discussion2', - "discussion discussion_category=\"Lecture 2\" discussion_id=\"b08bfd89b2aa40fa81f2c650a9332846\" discussion_target=\"Lecture 2\"/>\n", - { - "discussion_category": "Lecture 2", - "discussion_target": "Lecture 2", - "display_name": "Lecture 2 Discussion", - "discussion_id": "b08bfd89b2aa40fa81f2c650a9332846" - }, - 'vertical', 'Vert2', - split=False - ) - self._create_item('static_tab', 'staticuno', "tab
", {'display_name': 'Tab uno'}, None, None, split=False) - self._create_item('about', 'overview', "overview
", {}, None, None, split=False) - self._create_item('course_info', 'updates', "test
Goodbye
", {'display_name': 'Parented Html'}, 'vertical', 'Vert1', split=False) + self._create_item( + 'discussion', 'Discussion1', + "discussion discussion_category=\"Lecture 1\" discussion_id=\"a08bfd89b2aa40fa81f2c650a9332846\" discussion_target=\"Lecture 1\"/>\n", + { + "discussion_category": "Lecture 1", + "discussion_target": "Lecture 1", + "display_name": "Lecture 1 Discussion", + "discussion_id": "a08bfd89b2aa40fa81f2c650a9332846" + }, + 'vertical', 'Vert1', + split=False + ) + self._create_item('html', 'Html2', "Hellow
", {'display_name': 'Hollow Html'}, 'vertical', 'Vert1', split=False) + self._create_item( + 'discussion', 'Discussion2', + "discussion discussion_category=\"Lecture 2\" discussion_id=\"b08bfd89b2aa40fa81f2c650a9332846\" discussion_target=\"Lecture 2\"/>\n", + { + "discussion_category": "Lecture 2", + "discussion_target": "Lecture 2", + "display_name": "Lecture 2 Discussion", + "discussion_id": "b08bfd89b2aa40fa81f2c650a9332846" + }, + 'vertical', 'Vert2', + split=False + ) + self._create_item('static_tab', 'staticuno', "tab
", {'display_name': 'Tab uno'}, None, None, split=False) + self._create_item('about', 'overview', "overview
", {}, None, None, split=False) + self._create_item('course_info', 'updates', "test