Commit 040f9622 by cahrens

Update for split modulestore as default.

parent f5d3d605
......@@ -16,7 +16,6 @@ from xmodule.modulestore import ModuleStoreEnum
from xmodule.modulestore.django import modulestore
from xmodule.contentstore.django import contentstore
from xmodule.modulestore.tests.factories import check_exact_number_of_calls, check_number_of_calls
from opaque_keys.edx.locations import SlashSeparatedCourseKey, AssetLocation
from xmodule.modulestore.xml_importer import import_from_xml
from xmodule.exceptions import NotFoundError
from uuid import uuid4
......@@ -40,12 +39,13 @@ class ContentStoreImportTest(ModuleStoreTestCase):
self.client = Client()
self.client.login(username=self.user.username, password=password)
def load_test_import_course(self, target_course_id=None, create_new_course_if_not_present=False):
def load_test_import_course(self, target_course_id=None, create_course_if_not_present=True, module_store=None):
'''
Load the standard course used to test imports
(for do_import_static=False behavior).
'''
content_store = contentstore()
if module_store is None:
module_store = modulestore()
import_from_xml(
module_store,
......@@ -56,7 +56,7 @@ class ContentStoreImportTest(ModuleStoreTestCase):
do_import_static=False,
verbose=True,
target_course_id=target_course_id,
create_course_if_not_present=create_new_course_if_not_present,
create_course_if_not_present=create_course_if_not_present,
)
course_id = module_store.make_course_key('edX', 'test_import_course', '2012_Fall')
course = module_store.get_course(course_id)
......@@ -84,13 +84,14 @@ class ContentStoreImportTest(ModuleStoreTestCase):
# Test that importing course with unicode 'id' and 'display name' doesn't give UnicodeEncodeError
"""
module_store = modulestore()
course_id = SlashSeparatedCourseKey(u'Юникода', u'unicode_course', u'échantillon')
course_id = module_store.make_course_key(u'Юникода', u'unicode_course', u'échantillon')
import_from_xml(
module_store,
self.user.id,
TEST_DATA_DIR,
['2014_Uni'],
target_course_id=course_id
target_course_id=course_id,
create_course_if_not_present=True
)
course = module_store.get_course(course_id)
......@@ -113,9 +114,7 @@ class ContentStoreImportTest(ModuleStoreTestCase):
content = None
try:
location = AssetLocation.from_deprecated_string(
'/c4x/edX/test_import_course/asset/should_be_imported.html'
)
location = course.id.make_asset_key('asset', 'should_be_imported.html')
content = content_store.find(location)
except NotFoundError:
pass
......@@ -133,9 +132,13 @@ class ContentStoreImportTest(ModuleStoreTestCase):
content_store = contentstore()
module_store = modulestore()
import_from_xml(module_store, self.user.id, TEST_DATA_DIR, ['toy'], static_content_store=content_store, do_import_static=False, verbose=True)
import_from_xml(
module_store, self.user.id, TEST_DATA_DIR, ['toy'],
static_content_store=content_store, do_import_static=False,
create_course_if_not_present=True, verbose=True
)
course = module_store.get_course(SlashSeparatedCourseKey('edX', 'toy', '2012_Fall'))
course = module_store.get_course(module_store.make_course_key('edX', 'toy', '2012_Fall'))
# make sure we have NO assets in our contentstore
all_assets, count = content_store.get_all_content_for_course(course.id)
......@@ -144,7 +147,10 @@ class ContentStoreImportTest(ModuleStoreTestCase):
def test_no_static_link_rewrites_on_import(self):
module_store = modulestore()
courses = import_from_xml(module_store, self.user.id, TEST_DATA_DIR, ['toy'], do_import_static=False, verbose=True)
courses = import_from_xml(
module_store, self.user.id, TEST_DATA_DIR, ['toy'], do_import_static=False, verbose=True,
create_course_if_not_present=True
)
course_key = courses[0].id
handouts = module_store.get_item(course_key.make_usage_key('course_info', 'handouts'))
......@@ -171,17 +177,19 @@ class ContentStoreImportTest(ModuleStoreTestCase):
# NOTE: On Jenkins, with memcache enabled, the number of calls here is only 1.
# Locally, without memcache, the number of calls is actually 2 (once more during the publish step)
with check_number_of_calls(store, '_compute_metadata_inheritance_tree', 2):
self.load_test_import_course()
self.load_test_import_course(create_course_if_not_present=False, module_store=store)
@ddt.data(ModuleStoreEnum.Type.mongo, ModuleStoreEnum.Type.split)
def test_reimport(self, default_ms_type):
with modulestore().default_store(default_ms_type):
__, __, course = self.load_test_import_course(create_new_course_if_not_present=True)
__, __, course = self.load_test_import_course(create_course_if_not_present=True)
self.load_test_import_course(target_course_id=course.id)
def test_rewrite_reference_list(self):
module_store = modulestore()
target_course_id = SlashSeparatedCourseKey('testX', 'conditional_copy', 'copy_run')
# This test fails with split modulestore (the HTML component is not in "different_course_id" namespace).
# More investigation needs to be done.
module_store = modulestore()._get_modulestore_by_type(ModuleStoreEnum.Type.mongo)
target_course_id = module_store.make_course_key('testX', 'conditional_copy', 'copy_run')
import_from_xml(
module_store,
self.user.id,
......@@ -193,7 +201,7 @@ class ContentStoreImportTest(ModuleStoreTestCase):
target_course_id.make_usage_key('conditional', 'condone')
)
self.assertIsNotNone(conditional_module)
different_course_id = SlashSeparatedCourseKey('edX', 'different_course', None)
different_course_id = module_store.make_course_key('edX', 'different_course', None)
self.assertListEqual(
[
target_course_id.make_usage_key('problem', 'choiceprob'),
......@@ -211,13 +219,14 @@ class ContentStoreImportTest(ModuleStoreTestCase):
def test_rewrite_reference(self):
module_store = modulestore()
target_course_id = SlashSeparatedCourseKey('testX', 'peergrading_copy', 'copy_run')
target_course_id = module_store.make_course_key('testX', 'peergrading_copy', 'copy_run')
import_from_xml(
module_store,
self.user.id,
TEST_DATA_DIR,
['open_ended'],
target_course_id=target_course_id
target_course_id=target_course_id,
create_course_if_not_present=True
)
peergrading_module = module_store.get_item(
target_course_id.make_usage_key('peergrading', 'PeerGradingLinked')
......@@ -252,13 +261,14 @@ class ContentStoreImportTest(ModuleStoreTestCase):
def _verify_split_test_import(self, target_course_name, source_course_name, split_test_name, groups_to_verticals):
module_store = modulestore()
target_course_id = SlashSeparatedCourseKey('testX', target_course_name, 'copy_run')
target_course_id = module_store.make_course_key('testX', target_course_name, 'copy_run')
import_from_xml(
module_store,
self.user.id,
TEST_DATA_DIR,
[source_course_name],
target_course_id=target_course_id
target_course_id=target_course_id,
create_course_if_not_present=True
)
split_test_module = module_store.get_item(
target_course_id.make_usage_key('split_test', split_test_name)
......
......@@ -13,7 +13,9 @@ class DraftReorderTestCase(ModuleStoreTestCase):
def test_order(self):
store = modulestore()
course_items = import_from_xml(store, self.user.id, TEST_DATA_DIR, ['import_draft_order'])
course_items = import_from_xml(
store, self.user.id, TEST_DATA_DIR, ['import_draft_order'], create_course_if_not_present=True
)
course_key = course_items[0].id
sequential = store.get_item(course_key.make_usage_key('sequential', '0f4f7649b10141b0bdc9922dcf94515a'))
verticals = sequential.children
......
......@@ -7,7 +7,6 @@ from django.contrib.auth.models import User
from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase
from contentstore.tests.utils import AjaxEnabledTestClient
from opaque_keys.edx.locations import SlashSeparatedCourseKey
from contentstore.utils import reverse_url, reverse_course_url
from student.roles import CourseInstructorRole, CourseStaffRole, OrgStaffRole, OrgInstructorRole
from student import auth
......@@ -29,7 +28,7 @@ class TestCourseAccess(ModuleStoreTestCase):
self.client.login(username=self.user.username, password=user_password)
# create a course via the view handler which has a different strategy for permissions than the factory
self.course_key = SlashSeparatedCourseKey('myu', 'mydept.mycourse', 'myrun')
self.course_key = self.store.make_course_key('myu', 'mydept.mycourse', 'myrun')
course_url = reverse_url('course_handler')
self.client.ajax_post(
course_url,
......@@ -101,7 +100,7 @@ class TestCourseAccess(ModuleStoreTestCase):
self.assertContains(response, user.email)
# test copying course permissions
copy_course_key = SlashSeparatedCourseKey('copyu', 'copydept.mycourse', 'myrun')
copy_course_key = self.store.make_course_key('copyu', 'copydept.mycourse', 'myrun')
for role in [CourseInstructorRole, CourseStaffRole, OrgStaffRole, OrgInstructorRole]:
if (role is OrgStaffRole) or (role is OrgInstructorRole):
auth.add_users(
......
......@@ -6,7 +6,6 @@ from contentstore.tests.utils import AjaxEnabledTestClient
from contentstore.utils import delete_course_and_groups, reverse_url
from courseware.tests.factories import UserFactory
from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase
from opaque_keys.edx.locations import SlashSeparatedCourseKey
from student.models import CourseEnrollment
......@@ -26,7 +25,7 @@ class TestUsersDefaultRole(ModuleStoreTestCase):
self.client.login(username=self.user.username, password='test')
# create a course via the view handler to create course
self.course_key = SlashSeparatedCourseKey('Org_1', 'Course_1', 'Run_1')
self.course_key = self.store.make_course_key('Org_1', 'Course_1', 'Run_1')
self._create_course_with_given_location(self.course_key)
def _create_course_with_given_location(self, course_key):
......
......@@ -27,16 +27,18 @@ class AuthoringMixinTestCase(ModuleStoreTestCase):
parent_location=chapter.location,
display_name='Test Sequential'
)
self.vertical = ItemFactory.create(
vertical = ItemFactory.create(
category='vertical',
parent_location=sequential.location,
display_name='Test Vertical'
)
self.video = ItemFactory.create(
video = ItemFactory.create(
category='video',
parent_location=self.vertical.location,
parent_location=vertical.location,
display_name='Test Vertical'
)
self.vertical_location = vertical.location
self.video_location = video.location
self.pet_groups = [Group(1, 'Cat Lovers'), Group(2, 'Dog Lovers')]
def create_content_groups(self, content_groups):
......@@ -54,68 +56,72 @@ class AuthoringMixinTestCase(ModuleStoreTestCase):
self.course.user_partitions = [self.content_partition]
self.store.update_item(self.course, self.user.id)
def set_staff_only(self, item):
def set_staff_only(self, item_location):
"""Make an item visible to staff only."""
item = self.store.get_item(item_location)
item.visible_to_staff_only = True
self.store.update_item(item, self.user.id)
def set_group_access(self, item, group_ids):
def set_group_access(self, item_location, group_ids):
"""
Set group_access for the specified item to the specified group
ids within the content partition.
"""
item = self.store.get_item(item_location)
item.group_access[self.content_partition.id] = group_ids # pylint: disable=no-member
self.store.update_item(item, self.user.id)
def verify_visibility_view_contains(self, item, substrings):
def verify_visibility_view_contains(self, item_location, substrings):
"""
Verify that an item's visibility view returns an html string
containing all the expected substrings.
"""
item = self.store.get_item(item_location)
html = item.visibility_view().body_html()
for string in substrings:
self.assertIn(string, html)
def test_html_no_partition(self):
self.verify_visibility_view_contains(self.video, 'No content groups exist')
self.verify_visibility_view_contains(self.video_location, 'No content groups exist')
def test_html_empty_partition(self):
self.create_content_groups([])
self.verify_visibility_view_contains(self.video, 'No content groups exist')
self.verify_visibility_view_contains(self.video_location, 'No content groups exist')
def test_html_populated_partition(self):
self.create_content_groups(self.pet_groups)
self.verify_visibility_view_contains(self.video, ['Cat Lovers', 'Dog Lovers'])
self.verify_visibility_view_contains(self.video_location, ['Cat Lovers', 'Dog Lovers'])
def test_html_no_partition_staff_locked(self):
self.set_staff_only(self.vertical)
self.verify_visibility_view_contains(self.video, ['No content groups exist'])
self.set_staff_only(self.vertical_location)
self.verify_visibility_view_contains(self.video_location, ['No content groups exist'])
def test_html_empty_partition_staff_locked(self):
self.create_content_groups([])
self.set_staff_only(self.vertical)
self.verify_visibility_view_contains(self.video, 'No content groups exist')
self.set_staff_only(self.vertical_location)
self.verify_visibility_view_contains(self.video_location, 'No content groups exist')
def test_html_populated_partition_staff_locked(self):
self.create_content_groups(self.pet_groups)
self.set_staff_only(self.vertical)
self.set_staff_only(self.vertical_location)
self.verify_visibility_view_contains(
self.video, ['The Unit this component is contained in is hidden from students.', 'Cat Lovers', 'Dog Lovers']
self.video_location,
['The Unit this component is contained in is hidden from students.', 'Cat Lovers', 'Dog Lovers']
)
def test_html_false_content_group(self):
self.create_content_groups(self.pet_groups)
self.set_group_access(self.video, ['false_group_id'])
self.set_group_access(self.video_location, ['false_group_id'])
self.verify_visibility_view_contains(
self.video, ['Cat Lovers', 'Dog Lovers', 'Content group no longer exists.']
self.video_location, ['Cat Lovers', 'Dog Lovers', 'Content group no longer exists.']
)
def test_html_false_content_group_staff_locked(self):
self.create_content_groups(self.pet_groups)
self.set_staff_only(self.vertical)
self.set_group_access(self.video, ['false_group_id'])
self.set_staff_only(self.vertical_location)
self.set_group_access(self.video_location, ['false_group_id'])
self.verify_visibility_view_contains(
self.video,
self.video_location,
[
'Cat Lovers',
'Dog Lovers',
......
......@@ -10,13 +10,11 @@ from student.roles import GlobalStaff
from xmodule.modulestore import ModuleStoreEnum
from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase
from xmodule.modulestore.tests.factories import CourseFactory
from opaque_keys.edx.locations import SlashSeparatedCourseKey
from xmodule.modulestore.django import modulestore
from xmodule.error_module import ErrorDescriptor
from django.test.client import Client
from student.models import CourseEnrollment
from student.views import get_course_enrollment_pairs
from opaque_keys.edx.keys import CourseKey
from util.milestones_helpers import (
get_pre_requisite_courses_not_completed,
set_prerequisite_courses,
......@@ -42,7 +40,7 @@ class TestCourseListing(ModuleStoreTestCase):
self.client = Client()
self.client.login(username=self.teacher.username, password='test')
def _create_course_with_access_groups(self, course_location, metadata=None):
def _create_course_with_access_groups(self, course_location, metadata=None, default_store=None):
"""
Create dummy course with 'CourseFactory' and enroll the student
"""
......@@ -51,7 +49,8 @@ class TestCourseListing(ModuleStoreTestCase):
org=course_location.org,
number=course_location.course,
run=course_location.run,
metadata=metadata
metadata=metadata,
default_store=default_store
)
CourseEnrollment.enroll(self.student, course.id)
......@@ -70,7 +69,7 @@ class TestCourseListing(ModuleStoreTestCase):
"""
Test getting courses
"""
course_location = SlashSeparatedCourseKey('Org1', 'Course1', 'Run1')
course_location = self.store.make_course_key('Org1', 'Course1', 'Run1')
self._create_course_with_access_groups(course_location)
# get dashboard
......@@ -87,8 +86,10 @@ class TestCourseListing(ModuleStoreTestCase):
"""
Test the course list for regular staff when get_course returns an ErrorDescriptor
"""
course_key = SlashSeparatedCourseKey('Org1', 'Course1', 'Run1')
self._create_course_with_access_groups(course_key)
# pylint: disable=protected-access
mongo_store = modulestore()._get_modulestore_by_type(ModuleStoreEnum.Type.mongo)
course_key = mongo_store.make_course_key('Org1', 'Course1', 'Run1')
self._create_course_with_access_groups(course_key, default_store=ModuleStoreEnum.Type.mongo)
with patch('xmodule.modulestore.mongo.base.MongoKeyValueStore', Mock(side_effect=Exception)):
self.assertIsInstance(modulestore().get_course(course_key), ErrorDescriptor)
......@@ -104,15 +105,15 @@ class TestCourseListing(ModuleStoreTestCase):
"""
mongo_store = modulestore()._get_modulestore_by_type(ModuleStoreEnum.Type.mongo)
good_location = SlashSeparatedCourseKey('testOrg', 'testCourse', 'RunBabyRun')
self._create_course_with_access_groups(good_location)
good_location = mongo_store.make_course_key('testOrg', 'testCourse', 'RunBabyRun')
self._create_course_with_access_groups(good_location, default_store=ModuleStoreEnum.Type.mongo)
course_location = SlashSeparatedCourseKey('testOrg', 'doomedCourse', 'RunBabyRun')
self._create_course_with_access_groups(course_location)
course_location = mongo_store.make_course_key('testOrg', 'doomedCourse', 'RunBabyRun')
self._create_course_with_access_groups(course_location, default_store=ModuleStoreEnum.Type.mongo)
mongo_store.delete_course(course_location, ModuleStoreEnum.UserID.test)
course_location = SlashSeparatedCourseKey('testOrg', 'erroredCourse', 'RunBabyRun')
course = self._create_course_with_access_groups(course_location)
course_location = mongo_store.make_course_key('testOrg', 'erroredCourse', 'RunBabyRun')
course = self._create_course_with_access_groups(course_location, default_store=ModuleStoreEnum.Type.mongo)
course_db_record = mongo_store._find_one(course.location)
course_db_record.setdefault('metadata', {}).get('tabs', []).append({
"type": "wiko",
......@@ -137,18 +138,18 @@ class TestCourseListing(ModuleStoreTestCase):
Checks course where pre-requisite course is set has appropriate info.
"""
seed_milestone_relationship_types()
course_location2 = CourseKey.from_string('Org1/Course2/Run2')
course_location2 = self.store.make_course_key('Org1', 'Course2', 'Run2')
self._create_course_with_access_groups(course_location2)
pre_requisite_course_location = CourseKey.from_string('Org1/Course3/Run3')
pre_requisite_course_location = self.store.make_course_key('Org1', 'Course3', 'Run3')
self._create_course_with_access_groups(pre_requisite_course_location)
pre_requisite_course_location2 = CourseKey.from_string('Org1/Course4/Run4')
pre_requisite_course_location2 = self.store.make_course_key('Org1', 'Course4', 'Run4')
self._create_course_with_access_groups(pre_requisite_course_location2)
# create a course with pre_requisite_courses
pre_requisite_courses = [
unicode(pre_requisite_course_location),
unicode(pre_requisite_course_location2),
]
course_location = CourseKey.from_string('Org1/Course1/Run1')
course_location = self.store.make_course_key('Org1', 'Course1', 'Run1')
self._create_course_with_access_groups(course_location, {
'pre_requisite_courses': pre_requisite_courses
})
......
......@@ -43,9 +43,9 @@ class CoursesTest(ModuleStoreTestCase):
org='org', number='num', display_name='name'
)
cms_url = u"//{}/course/org/num/name".format(CMS_BASE_TEST)
cms_url = u"//{}/course/{}".format(CMS_BASE_TEST, unicode(self.course.id))
self.assertEqual(cms_url, get_cms_course_link(self.course))
cms_url = u"//{}/course/i4x://org/num/course/name".format(CMS_BASE_TEST)
cms_url = u"//{}/course/{}".format(CMS_BASE_TEST, unicode(self.course.location))
self.assertEqual(cms_url, get_cms_block_link(self.course, 'course'))
......
......@@ -8,7 +8,6 @@ from django.core.urlresolvers import reverse
from mock import patch
from student.roles import CourseSalesAdminRole
from student.tests.factories import UserFactory, CourseModeFactory
from opaque_keys.edx.locations import SlashSeparatedCourseKey
from shoppingcart.models import (
CourseRegistrationCode, RegistrationCodeRedemption, Order,
Invoice, Coupon, CourseRegCodeItem, CouponRedemption, CourseRegistrationCodeInvoiceItem
......@@ -33,7 +32,7 @@ class TestAnalyticsBasic(ModuleStoreTestCase):
def setUp(self):
super(TestAnalyticsBasic, self).setUp()
self.course_key = SlashSeparatedCourseKey('robot', 'course', 'id')
self.course_key = self.store.make_course_key('robot', 'course', 'id')
self.users = tuple(UserFactory() for _ in xrange(30))
self.ces = tuple(CourseEnrollment.enroll(user, self.course_key)
for user in self.users)
......@@ -80,7 +79,7 @@ class TestAnalyticsBasic(ModuleStoreTestCase):
self.assertIn(userreport['meta.company'], ["Open edX Inc {}".format(user.id) for user in self.users])
def test_enrolled_students_features_keys_cohorted(self):
course = CourseFactory.create(course_key=self.course_key)
course = CourseFactory.create(org="test", course="course1", display_name="run1")
course.cohort_config = {'cohorted': True, 'auto_cohort': True, 'auto_cohort_groups': ['cohort']}
self.store.update_item(course, self.instructor.id)
cohort = CohortFactory.create(name='cohort', course_id=course.id)
......
......@@ -120,6 +120,11 @@ class TestHandouts(MobileAPITestCase, MobileAuthTestMixin, MobileEnrolledCourseA
def setUp(self):
super(TestHandouts, self).setUp()
# Deleting handouts fails with split modulestore because the handout has no parent.
# This needs further investigation to determine if it is a bug in the split modulestore.
# pylint: disable=protected-access
self.store = modulestore()._get_modulestore_by_type(ModuleStoreEnum.Type.mongo)
# use toy course with handouts, and make it mobile_available
course_items = import_from_xml(self.store, self.user.id, settings.COMMON_TEST_DATA_ROOT, ['toy'])
self.course = course_items[0]
......
......@@ -35,7 +35,7 @@ class MobileAPITestCase(ModuleStoreTestCase, APITestCase):
"""
def setUp(self):
super(MobileAPITestCase, self).setUp()
self.course = CourseFactory.create(mobile_available=True)
self.course = CourseFactory.create(mobile_available=True, static_asset_path="needed_for_split")
self.user = UserFactory.create()
self.password = 'test'
self.username = self.user.username
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment