diff --git a/cms/djangoapps/contentstore/tests/test_crud.py b/cms/djangoapps/contentstore/tests/test_crud.py
index f843c71758..8ecb40f60f 100644
--- a/cms/djangoapps/contentstore/tests/test_crud.py
+++ b/cms/djangoapps/contentstore/tests/test_crud.py
@@ -1,5 +1,4 @@
import unittest
-from django.conf import settings
from xmodule import templates
from xmodule.modulestore.tests import persistent_factories
@@ -10,8 +9,6 @@ from xmodule.capa_module import CapaDescriptor
from xmodule.modulestore.locator import CourseLocator, BlockUsageLocator, LocalId
from xmodule.modulestore.exceptions import ItemNotFoundError, DuplicateCourseError
from xmodule.html_module import HtmlDescriptor
-from xmodule.modulestore import inheritance
-from xblock.core import XBlock
from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase
@@ -81,25 +78,25 @@ class TemplateTests(unittest.TestCase):
def test_temporary_xblocks(self):
"""
- Test using load_from_json to create non persisted xblocks
+ Test create_xblock to create non persisted xblocks
"""
test_course = persistent_factories.PersistentCourseFactory.create(
- course_id='testx.tempcourse', org='testx',
+ course_id='testx.tempcourse', org='testx',
display_name='fun test course', user_id='testbot'
)
- test_chapter = self.load_from_json({'category': 'chapter',
- 'fields': {'display_name': 'chapter n'}},
- test_course.system, parent_xblock=test_course)
+ test_chapter = modulestore('split').create_xblock(
+ test_course.system, 'chapter', {'display_name': 'chapter n'}, parent_xblock=test_course
+ )
self.assertIsInstance(test_chapter, SequenceDescriptor)
self.assertEqual(test_chapter.display_name, 'chapter n')
self.assertIn(test_chapter, test_course.get_children())
# test w/ a definition (e.g., a problem)
test_def_content = 'boo'
- test_problem = self.load_from_json({'category': 'problem',
- 'fields': {'data': test_def_content}},
- test_course.system, parent_xblock=test_chapter)
+ test_problem = modulestore('split').create_xblock(
+ test_course.system, 'problem', {'data': test_def_content}, parent_xblock=test_chapter
+ )
self.assertIsInstance(test_problem, CapaDescriptor)
self.assertEqual(test_problem.data, test_def_content)
self.assertIn(test_problem, test_chapter.get_children())
@@ -114,18 +111,19 @@ class TemplateTests(unittest.TestCase):
course_id='testx.tempcourse', org='testx',
display_name='fun test course', user_id='testbot'
)
- test_chapter = self.load_from_json({'category': 'chapter',
- 'fields': {'display_name': 'chapter n'}},
- test_course.system, parent_xblock=test_course)
+ test_chapter = modulestore('split').create_xblock(
+ test_course.system, 'chapter', {'display_name': 'chapter n'}, parent_xblock=test_course
+ )
+ self.assertEqual(test_chapter.display_name, 'chapter n')
test_def_content = 'boo'
# create child
- new_block = self.load_from_json({
- 'category': 'problem',
- 'fields': {
+ new_block = modulestore('split').create_xblock(
+ test_course.system,
+ 'problem',
+ fields={
'data': test_def_content,
'display_name': 'problem'
- }},
- test_course.system,
+ },
parent_xblock=test_chapter
)
self.assertIsNotNone(new_block.definition_locator)
@@ -242,44 +240,3 @@ class TemplateTests(unittest.TestCase):
mapper = loc_mapper()
self.assertEqual(modulestore('split').loc_mapper, mapper)
- # ================================= JSON PARSING ===========================
- # These are example methods for creating xmodules in memory w/o persisting them.
- # They were in x_module but since xblock is not planning to support them but will
- # allow apps to use this type of thing, I put it here.
- @staticmethod
- def load_from_json(json_data, system, default_class=None, parent_xblock=None):
- """
- This method instantiates the correct subclass of XModuleDescriptor based
- on the contents of json_data. It does not persist it and can create one which
- has no usage id.
-
- parent_xblock is used to compute inherited metadata as well as to append the new xblock.
-
- json_data:
- - 'location' : must have this field
- - 'category': the xmodule category (required or location must be a Location)
- - 'metadata': a dict of locally set metadata (not inherited)
- - 'children': a list of children's usage_ids w/in this course
- - 'definition':
- - '_id' (optional): the usage_id of this. Will generate one if not given one.
- """
- class_ = XBlock.load_class(
- json_data.get('category', json_data.get('location', {}).get('category')),
- default_class,
- select=settings.XBLOCK_SELECT_FUNCTION
- )
- usage_id = json_data.get('_id', None)
- if not '_inherited_settings' in json_data and parent_xblock is not None:
- json_data['_inherited_settings'] = parent_xblock.xblock_kvs.inherited_settings.copy()
- json_fields = json_data.get('fields', {})
- for field_name in inheritance.InheritanceMixin.fields:
- if field_name in json_fields:
- json_data['_inherited_settings'][field_name] = json_fields[field_name]
-
- new_block = system.xblock_from_json(class_, usage_id, json_data)
- if parent_xblock is not None:
- parent_xblock.children.append(new_block.scope_ids.usage_id)
- # decache pending children field settings
- parent_xblock.save()
- return new_block
-
diff --git a/common/lib/xmodule/xmodule/modulestore/locator.py b/common/lib/xmodule/xmodule/modulestore/locator.py
index 5ed8f0689a..a51ac765e1 100644
--- a/common/lib/xmodule/xmodule/modulestore/locator.py
+++ b/common/lib/xmodule/xmodule/modulestore/locator.py
@@ -22,12 +22,14 @@ log = logging.getLogger(__name__)
class LocalId(object):
"""
- Class for local ids for non-persisted xblocks
-
- Should be hashable and distinguishable, but nothing else
+ Class for local ids for non-persisted xblocks (which can have hardcoded block_ids if necessary)
"""
+ def __init__(self, block_id=None):
+ self.block_id = block_id
+ super(LocalId, self).__init__()
+
def __str__(self):
- return "localid_{}".format(id(self))
+ return "localid_{}".format(self.block_id or id(self))
class Locator(object):
diff --git a/common/lib/xmodule/xmodule/modulestore/split_mongo/split.py b/common/lib/xmodule/xmodule/modulestore/split_mongo/split.py
index 8785b00015..10e9185dee 100644
--- a/common/lib/xmodule/xmodule/modulestore/split_mongo/split.py
+++ b/common/lib/xmodule/xmodule/modulestore/split_mongo/split.py
@@ -953,7 +953,7 @@ class SplitMongoModuleStore(ModuleStoreWriteBase):
# check children
original_entry = self._get_block_from_structure(original_structure, descriptor.location.block_id)
is_updated = is_updated or (
- descriptor.has_children and original_entry['fields']['children'] != descriptor.children
+ descriptor.has_children and original_entry['fields'].get('children', []) != descriptor.children
)
# check metadata
if not is_updated:
@@ -992,6 +992,40 @@ class SplitMongoModuleStore(ModuleStoreWriteBase):
# nothing changed, just return the one sent in
return descriptor
+ def create_xblock(self, runtime, category, fields=None, block_id=None, definition_id=None, parent_xblock=None):
+ """
+ This method instantiates the correct subclass of XModuleDescriptor based
+ on the contents of json_data. It does not persist it and can create one which
+ has no usage id.
+
+ parent_xblock is used to compute inherited metadata as well as to append the new xblock.
+
+ json_data:
+ - 'category': the xmodule category
+ - 'fields': a dict of locally set fields (not inherited) in json format not pythonic typed format!
+ - 'definition': the object id of the existing definition
+ """
+ xblock_class = runtime.load_block_type(category)
+ json_data = {
+ 'category': category,
+ 'fields': fields or {},
+ }
+ if definition_id is not None:
+ json_data['definition'] = definition_id
+ if parent_xblock is not None:
+ json_data['_inherited_settings'] = parent_xblock.xblock_kvs.inherited_settings.copy()
+ if fields is not None:
+ for field_name in inheritance.InheritanceMixin.fields:
+ if field_name in fields:
+ json_data['_inherited_settings'][field_name] = fields[field_name]
+
+ new_block = runtime.xblock_from_json(xblock_class, block_id, json_data)
+ if parent_xblock is not None:
+ parent_xblock.children.append(new_block.scope_ids.usage_id)
+ # decache pending children field settings
+ parent_xblock.save()
+ return new_block
+
def persist_xblock_dag(self, xblock, user_id, force=False):
"""
create or update the xblock and all of its children. The xblock's location must specify a course.
@@ -1050,8 +1084,10 @@ class SplitMongoModuleStore(ModuleStoreWriteBase):
# generate an id
is_new = True
is_updated = True
- block_id = self._generate_block_id(structure_blocks, xblock.category)
- encoded_block_id = block_id
+ block_id = getattr(xblock.scope_ids.usage_id.block_id, 'block_id', None)
+ if block_id is None:
+ block_id = self._generate_block_id(structure_blocks, xblock.category)
+ encoded_block_id = LocMapperStore.encode_key_for_mongo(block_id)
xblock.scope_ids.usage_id.block_id = block_id
else:
is_new = False
diff --git a/common/lib/xmodule/xmodule/modulestore/tests/test_split_modulestore.py b/common/lib/xmodule/xmodule/modulestore/tests/test_split_modulestore.py
index 82336faa36..91437bd804 100644
--- a/common/lib/xmodule/xmodule/modulestore/tests/test_split_modulestore.py
+++ b/common/lib/xmodule/xmodule/modulestore/tests/test_split_modulestore.py
@@ -1,26 +1,24 @@
-'''
-Created on Mar 25, 2013
-
-@author: dmitchell
-'''
+"""
+ Test split modulestore w/o using any django stuff.
+"""
import datetime
-import subprocess
import unittest
import uuid
from importlib import import_module
-
-from xblock.fields import Scope
-from xmodule.course_module import CourseDescriptor
-from xmodule.modulestore.exceptions import InsufficientSpecificationError, ItemNotFoundError, VersionConflictError, \
- DuplicateItemError, DuplicateCourseError
-from xmodule.modulestore.locator import CourseLocator, BlockUsageLocator, VersionTree, DefinitionLocator
-from xmodule.modulestore.inheritance import InheritanceMixin
-from xmodule.x_module import XModuleMixin
-from pytz import UTC
from path import path
import re
import random
+from xblock.fields import Scope
+from xmodule.course_module import CourseDescriptor
+from xmodule.modulestore.exceptions import (InsufficientSpecificationError, ItemNotFoundError, VersionConflictError,
+ DuplicateItemError, DuplicateCourseError)
+from xmodule.modulestore.locator import CourseLocator, BlockUsageLocator, VersionTree, LocalId
+from xmodule.modulestore.inheritance import InheritanceMixin
+from xmodule.x_module import XModuleMixin
+from xmodule.fields import Date, Timedelta
+from bson.objectid import ObjectId
+
class SplitModuleTest(unittest.TestCase):
'''
@@ -52,52 +50,442 @@ class SplitModuleTest(unittest.TestCase):
modulestore = None
- # These version_guids correspond to values hard-coded in fixture files
- # used for these tests. The files live in mitx/fixtures/splitmongo_json/*
-
- GUID_D0 = "1d00000000000000dddd0000" # v12345d
- GUID_D1 = "1d00000000000000dddd1111" # v12345d1
- GUID_D2 = "1d00000000000000dddd2222" # v23456d
- GUID_D3 = "1d00000000000000dddd3333" # v12345d0
- GUID_D4 = "1d00000000000000dddd4444" # v23456d0
- GUID_D5 = "1d00000000000000dddd5555" # v345679d
- GUID_P = "1d00000000000000eeee0000" # v23456p
-
+ _date_field = Date()
+ _time_delta_field = Timedelta()
+ COURSE_CONTENT = {
+ "testx.GreekHero": {
+ "org": "testx",
+ "root_block_id": "head12345",
+ "user_id": "test@edx.org",
+ "fields": {
+ "tabs": [
+ {
+ "type": "courseware"
+ },
+ {
+ "type": "course_info",
+ "name": "Course Info"
+ },
+ {
+ "type": "discussion",
+ "name": "Discussion"
+ },
+ {
+ "type": "wiki",
+ "name": "Wiki"
+ }
+ ],
+ "start": _date_field.from_json("2013-02-14T05:00"),
+ "display_name": "The Ancient Greek Hero",
+ "grading_policy": {
+ "GRADER": [
+ {
+ "min_count": 5,
+ "weight": 0.15,
+ "type": "Homework",
+ "drop_count": 1,
+ "short_label": "HWa"
+ },
+ {
+ "short_label": "",
+ "min_count": 2,
+ "type": "Lab",
+ "drop_count": 0,
+ "weight": 0.15
+ },
+ {
+ "short_label": "Midterm",
+ "min_count": 1,
+ "type": "Midterm Exam",
+ "drop_count": 0,
+ "weight": 0.3
+ },
+ {
+ "short_label": "Final",
+ "min_count": 1,
+ "type": "Final Exam",
+ "drop_count": 0,
+ "weight": 0.4
+ }
+ ],
+ "GRADE_CUTOFFS": {
+ "Pass": 0.75
+ },
+ },
+ },
+ "revisions": [{
+ "user_id": "testassist@edx.org",
+ "update": {
+ "head12345": {
+ "end": _date_field.from_json("2013-04-13T04:30"),
+ "tabs": [
+ {
+ "type": "courseware"
+ },
+ {
+ "type": "course_info",
+ "name": "Course Info"
+ },
+ {
+ "type": "discussion",
+ "name": "Discussion"
+ },
+ {
+ "type": "wiki",
+ "name": "Wiki"
+ },
+ {
+ "type": "static_tab",
+ "name": "Syllabus",
+ "url_slug": "01356a17b5924b17a04b7fc2426a3798"
+ },
+ {
+ "type": "static_tab",
+ "name": "Advice for Students",
+ "url_slug": "57e9991c0d794ff58f7defae3e042e39"
+ }
+ ],
+ "graceperiod": _time_delta_field.from_json("2 hours 0 minutes 0 seconds"),
+ "grading_policy": {
+ "GRADER": [
+ {
+ "min_count": 5,
+ "weight": 0.15,
+ "type": "Homework",
+ "drop_count": 1,
+ "short_label": "HWa"
+ },
+ {
+ "short_label": "",
+ "min_count": 12,
+ "type": "Lab",
+ "drop_count": 2,
+ "weight": 0.15
+ },
+ {
+ "short_label": "Midterm",
+ "min_count": 1,
+ "type": "Midterm Exam",
+ "drop_count": 0,
+ "weight": 0.3
+ },
+ {
+ "short_label": "Final",
+ "min_count": 1,
+ "type": "Final Exam",
+ "drop_count": 0,
+ "weight": 0.4
+ }
+ ],
+ "GRADE_CUTOFFS": {
+ "Pass": 0.55
+ }
+ },
+ }}
+ },
+ {"user_id": "testassist@edx.org",
+ "update":
+ {"head12345": {
+ "end": _date_field.from_json("2013-06-13T04:30"),
+ "grading_policy": {
+ "GRADER": [
+ {
+ "min_count": 4,
+ "weight": 0.15,
+ "type": "Homework",
+ "drop_count": 2,
+ "short_label": "HWa"
+ },
+ {
+ "short_label": "",
+ "min_count": 12,
+ "type": "Lab",
+ "drop_count": 2,
+ "weight": 0.15
+ },
+ {
+ "short_label": "Midterm",
+ "min_count": 1,
+ "type": "Midterm Exam",
+ "drop_count": 0,
+ "weight": 0.3
+ },
+ {
+ "short_label": "Final",
+ "min_count": 1,
+ "type": "Final Exam",
+ "drop_count": 0,
+ "weight": 0.4
+ }
+ ],
+ "GRADE_CUTOFFS": {
+ "Pass": 0.45
+ }
+ },
+ "enrollment_start": _date_field.from_json("2013-01-01T05:00"),
+ "enrollment_end": _date_field.from_json("2013-03-02T05:00"),
+ "advertised_start": "Fall 2013",
+ }},
+ "create": [
+ {
+ "id": "chapter1",
+ "parent": "head12345",
+ "category": "chapter",
+ "fields": {
+ "display_name": "Hercules"
+ },
+ },
+ {
+ "id": "chapter2",
+ "parent": "head12345",
+ "category": "chapter",
+ "fields": {
+ "display_name": "Hera heckles Hercules"
+ },
+ },
+ {
+ "id": "chapter3",
+ "parent": "head12345",
+ "category": "chapter",
+ "fields": {
+ "display_name": "Hera cuckolds Zeus"
+ },
+ },
+ {
+ "id": "problem1",
+ "parent": "chapter3",
+ "category": "problem",
+ "fields": {
+ "display_name": "Problem 3.1",
+ "graceperiod": "4 hours 0 minutes 0 seconds"
+ },
+ },
+ {
+ "id": "problem3_2",
+ "parent": "chapter3",
+ "category": "problem",
+ "fields": {
+ "display_name": "Problem 3.2"
+ },
+ }
+ ]
+ },
+ ]
+ },
+ "testx.wonderful": {
+ "org": "testx",
+ "root_block_id": "head23456",
+ "user_id": "test@edx.org",
+ "fields": {
+ "tabs": [
+ {
+ "type": "courseware"
+ },
+ {
+ "type": "course_info",
+ "name": "Course Info"
+ },
+ {
+ "type": "discussion",
+ "name": "Discussion"
+ },
+ {
+ "type": "wiki",
+ "name": "Wiki"
+ }
+ ],
+ "start": _date_field.from_json("2013-02-14T05:00"),
+ "display_name": "A wonderful course",
+ "grading_policy": {
+ "GRADER": [
+ {
+ "min_count": 14,
+ "weight": 0.25,
+ "type": "Homework",
+ "drop_count": 1,
+ "short_label": "HWa"
+ },
+ {
+ "short_label": "",
+ "min_count": 12,
+ "type": "Lab",
+ "drop_count": 2,
+ "weight": 0.25
+ },
+ {
+ "short_label": "Midterm",
+ "min_count": 1,
+ "type": "Midterm Exam",
+ "drop_count": 0,
+ "weight": 0.2
+ },
+ {
+ "short_label": "Final",
+ "min_count": 1,
+ "type": "Final Exam",
+ "drop_count": 0,
+ "weight": 0.3
+ }
+ ],
+ "GRADE_CUTOFFS": {
+ "Pass": 0.95
+ }
+ },
+ },
+ "revisions": [{
+ "user_id": "test@edx.org",
+ "update": {
+ "head23456": {
+ "display_name": "The most wonderful course",
+ "grading_policy": {
+ "GRADER": [
+ {
+ "min_count": 14,
+ "weight": 0.25,
+ "type": "Homework",
+ "drop_count": 1,
+ "short_label": "HWa"
+ },
+ {
+ "short_label": "",
+ "min_count": 12,
+ "type": "Lab",
+ "drop_count": 2,
+ "weight": 0.25
+ },
+ {
+ "short_label": "Midterm",
+ "min_count": 1,
+ "type": "Midterm Exam",
+ "drop_count": 0,
+ "weight": 0.2
+ },
+ {
+ "short_label": "Final",
+ "min_count": 1,
+ "type": "Final Exam",
+ "drop_count": 0,
+ "weight": 0.3
+ }
+ ],
+ "GRADE_CUTOFFS": {
+ "Pass": 0.45
+ }
+ },
+ }
+ }
+ }
+ ]
+ },
+ "guestx.contender": {
+ "org": "guestx",
+ "root_block_id": "head345679",
+ "user_id": "test@guestx.edu",
+ "fields": {
+ "tabs": [
+ {
+ "type": "courseware"
+ },
+ {
+ "type": "course_info",
+ "name": "Course Info"
+ },
+ {
+ "type": "discussion",
+ "name": "Discussion"
+ },
+ {
+ "type": "wiki",
+ "name": "Wiki"
+ }
+ ],
+ "start": _date_field.from_json("2013-03-14T05:00"),
+ "display_name": "Yet another contender",
+ "grading_policy": {
+ "GRADER": [
+ {
+ "min_count": 4,
+ "weight": 0.25,
+ "type": "Homework",
+ "drop_count": 0,
+ "short_label": "HW"
+ },
+ {
+ "short_label": "Midterm",
+ "min_count": 1,
+ "type": "Midterm Exam",
+ "drop_count": 0,
+ "weight": 0.4
+ },
+ {
+ "short_label": "Final",
+ "min_count": 1,
+ "type": "Final Exam",
+ "drop_count": 0,
+ "weight": 0.35
+ }
+ ],
+ "GRADE_CUTOFFS": {
+ "Pass": 0.25
+ }
+ },
+ }
+ },
+ }
@staticmethod
def bootstrapDB():
'''
- Loads the initial data into the db ensuring the collection name is
- unique.
+ Sets up the initial data into the db
'''
- collection_prefix = SplitModuleTest.MODULESTORE['DOC_STORE_CONFIG']['collection'] + '.'
- dbname = SplitModuleTest.MODULESTORE['DOC_STORE_CONFIG']['db']
- processes = [
- subprocess.Popen([
- 'mongoimport', '-d', dbname, '-c',
- collection_prefix + collection, '--jsonArray',
- '--file',
- SplitModuleTest.COMMON_ROOT + '/test/data/splitmongo_json/' + collection + '.json'
- ],
- stdout=subprocess.PIPE,
- stderr=subprocess.PIPE,
+ split_store = modulestore()
+ for course_id, course_spec in SplitModuleTest.COURSE_CONTENT.iteritems():
+ course = split_store.create_course(
+ course_id, course_spec['org'], course_spec['user_id'],
+ fields=course_spec['fields'],
+ root_block_id=course_spec['root_block_id']
)
- for collection in ('active_versions', 'structures', 'definitions')]
- for p in processes:
- stdout, stderr = p.communicate()
- if p.returncode != 0:
- print "Couldn't run mongoimport:"
- print stdout
- print stderr
- raise Exception("DB did not init correctly")
+ for revision in course_spec.get('revisions', []):
+ for block_id, fields in revision.get('update', {}).iteritems():
+ # cheat since course is most frequent
+ if course.location.block_id == block_id:
+ block = course
+ else:
+ block_usage = BlockUsageLocator.make_relative(course.location, block_id)
+ block = split_store.get_instance(course.location.package_id, block_usage)
+ for key, value in fields.iteritems():
+ setattr(block, key, value)
+ # create new blocks into dag: parent must already exist; thus, order is important
+ new_ele_dict = {}
+ for spec in revision.get('create', []):
+ if spec['parent'] in new_ele_dict:
+ parent = new_ele_dict.get(spec['parent'])
+ elif spec['parent'] == course.location.block_id:
+ parent = course
+ else:
+ block_usage = BlockUsageLocator.make_relative(course.location, spec['parent'])
+ parent = split_store.get_instance(course.location.package_id, block_usage)
+ block_id = LocalId(spec['id'])
+ child = split_store.create_xblock(
+ course.runtime, spec['category'], spec['fields'], block_id, parent_xblock=parent
+ )
+ new_ele_dict[spec['id']] = child
+ course = split_store.persist_xblock_dag(course, revision['user_id'])
+ # publish "testx.wonderful"
+ to_publish = BlockUsageLocator(package_id="testx.wonderful", branch="draft", block_id="head23456")
+ destination = CourseLocator(package_id="testx.wonderful", branch="published")
+ split_store.xblock_publish("test@edx.org", to_publish, destination, [to_publish.block_id], None)
- @classmethod
- def tearDownClass(cls):
+ def tearDown(self):
+ """
+ Clear persistence between each test.
+ """
collection_prefix = SplitModuleTest.MODULESTORE['DOC_STORE_CONFIG']['collection'] + '.'
if SplitModuleTest.modulestore:
for collection in ('active_versions', 'structures', 'definitions'):
modulestore().db.drop_collection(collection_prefix + collection)
# drop the modulestore to force re init
SplitModuleTest.modulestore = None
+ super(SplitModuleTest, self).tearDown()
def findByIdInResult(self, collection, _id):
"""
@@ -120,11 +508,7 @@ class SplitModuleCourseTests(SplitModuleTest):
self.assertEqual(len(courses), 3, "Wrong number of courses")
# check metadata -- NOTE no promised order
course = self.findByIdInResult(courses, "head12345")
- self.assertEqual(course.location.package_id, "GreekHero")
- self.assertEqual(
- str(course.location.version_guid), self.GUID_D0,
- "course version mismatch"
- )
+ self.assertEqual(course.location.package_id, "testx.GreekHero")
self.assertEqual(course.category, 'course', 'wrong category')
self.assertEqual(len(course.tabs), 6, "wrong number of tabs")
self.assertEqual(
@@ -135,13 +519,9 @@ class SplitModuleCourseTests(SplitModuleTest):
course.advertised_start, "Fall 2013",
"advertised_start"
)
- self.assertEqual(
- len(course.children), 3,
- "children")
- self.assertEqual(str(course.definition_locator.definition_id), "ad00000000000000dddd0000")
+ self.assertEqual(len(course.children), 3, "children")
# check dates and graders--forces loading of descriptor
self.assertEqual(course.edited_by, "testassist@edx.org")
- self.assertEqual(str(course.previous_version), self.GUID_D1)
self.assertDictEqual(course.grade_cutoffs, {"Pass": 0.45})
def test_branch_requests(self):
@@ -151,9 +531,7 @@ class SplitModuleCourseTests(SplitModuleTest):
self.assertEqual(len(courses_published), 1, len(courses_published))
course = self.findByIdInResult(courses_published, "head23456")
self.assertIsNotNone(course, "published courses")
- self.assertEqual(course.location.package_id, "wonderful")
- self.assertEqual(str(course.location.version_guid), self.GUID_P,
- course.location.version_guid)
+ self.assertEqual(course.location.package_id, "testx.wonderful")
self.assertEqual(course.category, 'course', 'wrong category')
self.assertEqual(len(course.tabs), 4, "wrong number of tabs")
self.assertEqual(course.display_name, "The most wonderful course",
@@ -171,34 +549,31 @@ class SplitModuleCourseTests(SplitModuleTest):
self.assertIsNotNone(self.findByIdInResult(courses, "head12345"))
self.assertIsNotNone(self.findByIdInResult(courses, "head23456"))
- courses = modulestore().get_courses(
- branch='draft',
- qualifiers={'edited_on': {"$lt": datetime.datetime(2013, 3, 28, 15)}})
- self.assertEqual(len(courses), 2)
-
def test_get_course(self):
'''
Test the various calling forms for get_course
'''
- locator = CourseLocator(version_guid=self.GUID_D1)
+ locator = CourseLocator(package_id="testx.GreekHero", branch="draft")
+ head_course = modulestore().get_course(locator)
+ self.assertNotEqual(head_course.location.version_guid, head_course.previous_version)
+ locator = CourseLocator(version_guid=head_course.previous_version)
course = modulestore().get_course(locator)
self.assertIsNone(course.location.package_id)
- self.assertEqual(str(course.location.version_guid), self.GUID_D1)
+ self.assertEqual(course.location.version_guid, head_course.previous_version)
self.assertEqual(course.category, 'course')
self.assertEqual(len(course.tabs), 6)
self.assertEqual(course.display_name, "The Ancient Greek Hero")
self.assertEqual(course.graceperiod, datetime.timedelta(hours=2))
self.assertIsNone(course.advertised_start)
self.assertEqual(len(course.children), 0)
- self.assertEqual(str(course.definition_locator.definition_id), "ad00000000000000dddd0001")
+ self.assertNotEqual(course.definition_locator.definition_id, head_course.definition_locator.definition_id)
# check dates and graders--forces loading of descriptor
self.assertEqual(course.edited_by, "testassist@edx.org")
self.assertDictEqual(course.grade_cutoffs, {"Pass": 0.55})
- locator = CourseLocator(package_id='GreekHero', branch='draft')
+ locator = CourseLocator(package_id='testx.GreekHero', branch='draft')
course = modulestore().get_course(locator)
- self.assertEqual(course.location.package_id, "GreekHero")
- self.assertEqual(str(course.location.version_guid), self.GUID_D0)
+ self.assertEqual(course.location.package_id, "testx.GreekHero")
self.assertEqual(course.category, 'course')
self.assertEqual(len(course.tabs), 6)
self.assertEqual(course.display_name, "The Ancient Greek Hero")
@@ -208,14 +583,13 @@ class SplitModuleCourseTests(SplitModuleTest):
self.assertEqual(course.edited_by, "testassist@edx.org")
self.assertDictEqual(course.grade_cutoffs, {"Pass": 0.45})
- locator = CourseLocator(package_id='wonderful', branch='published')
+ locator = CourseLocator(package_id='testx.wonderful', branch='published')
course = modulestore().get_course(locator)
- self.assertEqual(course.location.package_id, "wonderful")
- self.assertEqual(str(course.location.version_guid), self.GUID_P)
+ published_version = course.location.version_guid
- locator = CourseLocator(package_id='wonderful', branch='draft')
+ locator = CourseLocator(package_id='testx.wonderful', branch='draft')
course = modulestore().get_course(locator)
- self.assertEqual(str(course.location.version_guid), self.GUID_D2)
+ self.assertNotEqual(course.location.version_guid, published_version)
def test_get_course_negative(self):
# Now negative testing
@@ -225,13 +599,13 @@ class SplitModuleCourseTests(SplitModuleTest):
modulestore().get_course, CourseLocator(package_id='nosuchthing', branch='draft'))
self.assertRaises(ItemNotFoundError,
modulestore().get_course,
- CourseLocator(package_id='GreekHero', branch='published'))
+ CourseLocator(package_id='testx.GreekHero', branch='published'))
def test_cache(self):
"""
Test that the mechanics of caching work.
"""
- locator = CourseLocator(version_guid=self.GUID_D0)
+ locator = CourseLocator(package_id='testx.GreekHero', branch='draft')
course = modulestore().get_course(locator)
block_map = modulestore().cache_items(course.system, course.children, depth=3)
self.assertIn('chapter1', block_map)
@@ -241,22 +615,32 @@ class SplitModuleCourseTests(SplitModuleTest):
"""
get_course_successors(course_locator, version_history_depth=1)
"""
- locator = CourseLocator(version_guid=self.GUID_D3)
+ locator = CourseLocator(package_id='testx.GreekHero', branch='draft')
+ course = modulestore().get_course(locator)
+ versions = [course.location.version_guid, course.previous_version]
+ locator = CourseLocator(version_guid=course.previous_version)
+ course = modulestore().get_course(locator)
+ versions.append(course.previous_version)
+
+ locator = CourseLocator(version_guid=course.previous_version)
result = modulestore().get_course_successors(locator)
self.assertIsInstance(result, VersionTree)
self.assertIsNone(result.locator.package_id)
- self.assertEqual(str(result.locator.version_guid), self.GUID_D3)
+ self.assertEqual(result.locator.version_guid, versions[-1])
self.assertEqual(len(result.children), 1)
- self.assertEqual(str(result.children[0].locator.version_guid), self.GUID_D1)
+ self.assertEqual(result.children[0].locator.version_guid, versions[-2])
self.assertEqual(len(result.children[0].children), 0, "descended more than one level")
+
result = modulestore().get_course_successors(locator, version_history_depth=2)
self.assertEqual(len(result.children), 1)
- self.assertEqual(str(result.children[0].locator.version_guid), self.GUID_D1)
+ self.assertEqual(result.children[0].locator.version_guid, versions[-2])
self.assertEqual(len(result.children[0].children), 1)
+
result = modulestore().get_course_successors(locator, version_history_depth=99)
self.assertEqual(len(result.children), 1)
- self.assertEqual(str(result.children[0].locator.version_guid), self.GUID_D1)
+ self.assertEqual(result.children[0].locator.version_guid, versions[-2])
self.assertEqual(len(result.children[0].children), 1)
+ self.assertEqual(result.children[0].children[0].locator.version_guid, versions[0])
class SplitModuleItemTests(SplitModuleTest):
'''
@@ -267,97 +651,98 @@ class SplitModuleItemTests(SplitModuleTest):
'''
has_item(BlockUsageLocator)
'''
- package_id = 'GreekHero'
+ package_id = 'testx.GreekHero'
+ locator = CourseLocator(package_id=package_id, branch='draft')
+ course = modulestore().get_course(locator)
+ previous_version = course.previous_version
# positive tests of various forms
- locator = BlockUsageLocator(version_guid=self.GUID_D1, block_id='head12345')
- self.assertTrue(modulestore().has_item(package_id, locator),
- "couldn't find in %s" % self.GUID_D1)
+ locator = BlockUsageLocator(version_guid=previous_version, block_id='head12345')
+ self.assertTrue(
+ modulestore().has_item(package_id, locator), "couldn't find in %s" % previous_version
+ )
- locator = BlockUsageLocator(package_id='GreekHero', block_id='head12345', branch='draft')
+ locator = BlockUsageLocator(package_id='testx.GreekHero', block_id='head12345', branch='draft')
self.assertTrue(
modulestore().has_item(locator.package_id, locator),
- "couldn't find in 12345"
- )
- self.assertTrue(
- modulestore().has_item(locator.package_id, BlockUsageLocator(
- package_id=locator.package_id,
- branch='draft',
- block_id=locator.block_id
- )),
- "couldn't find in draft 12345"
)
self.assertFalse(
modulestore().has_item(locator.package_id, BlockUsageLocator(
package_id=locator.package_id,
branch='published',
block_id=locator.block_id)),
- "found in published 12345"
- )
- locator.branch = 'draft'
- self.assertTrue(
- modulestore().has_item(locator.package_id, locator),
- "not found in draft 12345"
+ "found in published head"
)
# not a course obj
- locator = BlockUsageLocator(package_id='GreekHero', block_id='chapter1', branch='draft')
+ locator = BlockUsageLocator(package_id='testx.GreekHero', block_id='chapter1', branch='draft')
self.assertTrue(
modulestore().has_item(locator.package_id, locator),
"couldn't find chapter1"
)
# in published course
- locator = BlockUsageLocator(package_id="wonderful", block_id="head23456", branch='draft')
+ locator = BlockUsageLocator(package_id="testx.wonderful", block_id="head23456", branch='draft')
self.assertTrue(
modulestore().has_item(
locator.package_id,
BlockUsageLocator(package_id=locator.package_id, block_id=locator.block_id, branch='published')
- ), "couldn't find in 23456"
+ )
)
locator.branch = 'published'
- self.assertTrue(modulestore().has_item(package_id, locator), "couldn't find in 23456")
+ self.assertTrue(modulestore().has_item(package_id, locator), "couldn't find in published")
def test_negative_has_item(self):
# negative tests--not found
# no such course or block
- package_id = 'GreekHero'
+ package_id = 'testx.GreekHero'
locator = BlockUsageLocator(package_id="doesnotexist", block_id="head23456", branch='draft')
self.assertFalse(modulestore().has_item(package_id, locator))
- locator = BlockUsageLocator(package_id="wonderful", block_id="doesnotexist", branch='draft')
+ locator = BlockUsageLocator(package_id="testx.wonderful", block_id="doesnotexist", branch='draft')
self.assertFalse(modulestore().has_item(package_id, locator))
# negative tests--insufficient specification
self.assertRaises(InsufficientSpecificationError, BlockUsageLocator)
- self.assertRaises(InsufficientSpecificationError,
- modulestore().has_item, None, BlockUsageLocator(version_guid=self.GUID_D1))
- self.assertRaises(InsufficientSpecificationError,
- modulestore().has_item, None, BlockUsageLocator(package_id='GreekHero'))
+
+ locator = CourseLocator(package_id=package_id, branch='draft')
+ course = modulestore().get_course(locator)
+ previous_version = course.previous_version
+
+ with self.assertRaises(InsufficientSpecificationError):
+ modulestore().has_item(None, BlockUsageLocator(version_guid=previous_version))
+ with self.assertRaises(InsufficientSpecificationError):
+ modulestore().has_item(None, BlockUsageLocator(package_id='testx.GreekHero'))
def test_get_item(self):
'''
get_item(blocklocator)
'''
+ locator = CourseLocator(package_id="testx.GreekHero", branch='draft')
+ course = modulestore().get_course(locator)
+ previous_version = course.previous_version
+
# positive tests of various forms
- locator = BlockUsageLocator(version_guid=self.GUID_D1, block_id='head12345')
+ locator = BlockUsageLocator(version_guid=previous_version, block_id='head12345')
block = modulestore().get_item(locator)
self.assertIsInstance(block, CourseDescriptor)
# get_instance just redirects to get_item, ignores package_id
self.assertIsInstance(modulestore().get_instance("package_id", locator), CourseDescriptor)
def verify_greek_hero(block):
- self.assertEqual(block.location.package_id, "GreekHero")
+ """
+ Check contents of block
+ """
+ self.assertEqual(block.location.package_id, "testx.GreekHero")
self.assertEqual(len(block.tabs), 6, "wrong number of tabs")
self.assertEqual(block.display_name, "The Ancient Greek Hero")
self.assertEqual(block.advertised_start, "Fall 2013")
self.assertEqual(len(block.children), 3)
- self.assertEqual(str(block.definition_locator.definition_id), "ad00000000000000dddd0000")
# check dates and graders--forces loading of descriptor
self.assertEqual(block.edited_by, "testassist@edx.org")
self.assertDictEqual(
block.grade_cutoffs, {"Pass": 0.45},
)
- locator = BlockUsageLocator(package_id='GreekHero', block_id='head12345', branch='draft')
+ locator = BlockUsageLocator(package_id='testx.GreekHero', block_id='head12345', branch='draft')
verify_greek_hero(modulestore().get_item(locator))
# get_instance just redirects to get_item, ignores package_id
verify_greek_hero(modulestore().get_instance("package_id", locator))
@@ -376,16 +761,15 @@ class SplitModuleItemTests(SplitModuleTest):
def test_get_non_root(self):
# not a course obj
- locator = BlockUsageLocator(package_id='GreekHero', block_id='chapter1', branch='draft')
+ locator = BlockUsageLocator(package_id='testx.GreekHero', block_id='chapter1', branch='draft')
block = modulestore().get_item(locator)
- self.assertEqual(block.location.package_id, "GreekHero")
+ self.assertEqual(block.location.package_id, "testx.GreekHero")
self.assertEqual(block.category, 'chapter')
- self.assertEqual(str(block.definition_locator.definition_id), "cd00000000000000dddd0020")
self.assertEqual(block.display_name, "Hercules")
self.assertEqual(block.edited_by, "testassist@edx.org")
# in published course
- locator = BlockUsageLocator(package_id="wonderful", block_id="head23456", branch='published')
+ locator = BlockUsageLocator(package_id="testx.wonderful", block_id="head23456", branch='published')
self.assertIsInstance(
modulestore().get_item(locator),
CourseDescriptor
@@ -396,15 +780,15 @@ class SplitModuleItemTests(SplitModuleTest):
locator = BlockUsageLocator(package_id="doesnotexist", block_id="head23456", branch='draft')
with self.assertRaises(ItemNotFoundError):
modulestore().get_item(locator)
- locator = BlockUsageLocator(package_id="wonderful", block_id="doesnotexist", branch='draft')
+ locator = BlockUsageLocator(package_id="testx.wonderful", block_id="doesnotexist", branch='draft')
with self.assertRaises(ItemNotFoundError):
modulestore().get_item(locator)
# negative tests--insufficient specification
with self.assertRaises(InsufficientSpecificationError):
- modulestore().get_item(BlockUsageLocator(version_guid=self.GUID_D1))
+ modulestore().get_item(BlockUsageLocator(version_guid=ObjectId()))
with self.assertRaises(InsufficientSpecificationError):
- modulestore().get_item(BlockUsageLocator(package_id='GreekHero', branch='draft'))
+ modulestore().get_item(BlockUsageLocator(package_id='testx.GreekHero', branch='draft'))
# pylint: disable=W0212
def test_matching(self):
@@ -437,7 +821,7 @@ class SplitModuleItemTests(SplitModuleTest):
'''
get_items(locator, qualifiers, [branch])
'''
- locator = CourseLocator(version_guid=self.GUID_D0)
+ locator = CourseLocator(package_id="testx.GreekHero", branch='draft')
# get all modules
matches = modulestore().get_items(locator)
self.assertEqual(len(matches), 6)
@@ -465,11 +849,11 @@ class SplitModuleItemTests(SplitModuleTest):
'''
get_parent_locations(locator, [block_id], [branch]): [BlockUsageLocator]
'''
- locator = BlockUsageLocator(package_id="GreekHero", branch='draft', block_id='chapter1')
+ locator = BlockUsageLocator(package_id="testx.GreekHero", branch='draft', block_id='chapter1')
parents = modulestore().get_parent_locations(locator)
self.assertEqual(len(parents), 1)
self.assertEqual(parents[0].block_id, 'head12345')
- self.assertEqual(parents[0].package_id, "GreekHero")
+ self.assertEqual(parents[0].package_id, "testx.GreekHero")
locator.block_id = 'chapter2'
parents = modulestore().get_parent_locations(locator)
self.assertEqual(len(parents), 1)
@@ -482,7 +866,7 @@ class SplitModuleItemTests(SplitModuleTest):
"""
Test the existing get_children method on xdescriptors
"""
- locator = BlockUsageLocator(package_id="GreekHero", block_id="head12345", branch='draft')
+ locator = BlockUsageLocator(package_id="testx.GreekHero", block_id="head12345", branch='draft')
block = modulestore().get_item(locator)
children = block.get_children()
expected_ids = [
@@ -524,9 +908,9 @@ class TestItemCrud(SplitModuleTest):
create_item(course_or_parent_locator, category, user, definition_locator=None, fields): new_desciptor
"""
# grab link to course to ensure new versioning works
- locator = CourseLocator(package_id="GreekHero", branch='draft')
+ locator = CourseLocator(package_id="testx.GreekHero", branch='draft')
premod_course = modulestore().get_course(locator)
- premod_time = datetime.datetime.now(UTC) - datetime.timedelta(seconds=1)
+ premod_history = modulestore().get_course_history_info(premod_course.location)
# add minimal one w/o a parent
category = 'sequential'
new_module = modulestore().create_item(
@@ -534,7 +918,7 @@ class TestItemCrud(SplitModuleTest):
fields={'display_name': 'new sequential'}
)
# check that course version changed and course's previous is the other one
- self.assertEqual(new_module.location.package_id, "GreekHero")
+ self.assertEqual(new_module.location.package_id, "testx.GreekHero")
self.assertNotEqual(new_module.location.version_guid, premod_course.location.version_guid)
self.assertIsNone(locator.version_guid, "Version inadvertently filled in")
current_course = modulestore().get_course(locator)
@@ -542,10 +926,8 @@ class TestItemCrud(SplitModuleTest):
history_info = modulestore().get_course_history_info(current_course.location)
self.assertEqual(history_info['previous_version'], premod_course.location.version_guid)
- self.assertEqual(str(history_info['original_version']), self.GUID_D3)
+ self.assertEqual(history_info['original_version'], premod_history['original_version'])
self.assertEqual(history_info['edited_by'], "user123")
- self.assertGreaterEqual(history_info['edited_on'], premod_time)
- self.assertLessEqual(history_info['edited_on'], datetime.datetime.now(UTC))
# check block's info: category, definition_locator, and display_name
self.assertEqual(new_module.category, 'sequential')
self.assertIsNotNone(new_module.definition_locator)
@@ -561,19 +943,22 @@ class TestItemCrud(SplitModuleTest):
"""
Test create_item w/ specifying the parent of the new item
"""
- locator = BlockUsageLocator(package_id="wonderful", block_id="head23456", branch='draft')
+ locator = BlockUsageLocator(package_id="testx.GreekHero", branch='draft', block_id='chapter2')
+ original = modulestore().get_item(locator)
+
+ locator = BlockUsageLocator(package_id="testx.wonderful", block_id="head23456", branch='draft')
premod_course = modulestore().get_course(locator)
category = 'chapter'
new_module = modulestore().create_item(
locator, category, 'user123',
fields={'display_name': 'new chapter'},
- definition_locator=DefinitionLocator("cd00000000000000dddd0022")
+ definition_locator=original.definition_locator
)
# check that course version changed and course's previous is the other one
self.assertNotEqual(new_module.location.version_guid, premod_course.location.version_guid)
parent = modulestore().get_item(locator)
self.assertIn(new_module.location.block_id, parent.children)
- self.assertEqual(str(new_module.definition_locator.definition_id), "cd00000000000000dddd0022")
+ self.assertEqual(new_module.definition_locator.definition_id, original.definition_locator.definition_id)
def test_unique_naming(self):
"""
@@ -581,9 +966,11 @@ class TestItemCrud(SplitModuleTest):
a definition id and new def data that it branches the definition in the db.
Actually, this tries to test all create_item features not tested above.
"""
- locator = BlockUsageLocator(package_id="contender", block_id="head345679", branch='draft')
+ locator = BlockUsageLocator(package_id="testx.GreekHero", branch='draft', block_id='problem1')
+ original = modulestore().get_item(locator)
+
+ locator = BlockUsageLocator(package_id="guestx.contender", block_id="head345679", branch='draft')
category = 'problem'
- premod_time = datetime.datetime.now(UTC) - datetime.timedelta(seconds=1)
new_payload = "empty"
new_module = modulestore().create_item(
locator, category, 'anotheruser',
@@ -593,7 +980,7 @@ class TestItemCrud(SplitModuleTest):
another_module = modulestore().create_item(
locator, category, 'anotheruser',
fields={'display_name': 'problem 2', 'data': another_payload},
- definition_locator=DefinitionLocator("0d00000040000000dddd0031"),
+ definition_locator=original.definition_locator,
)
# check that course version changed and course's previous is the other one
parent = modulestore().get_item(locator)
@@ -607,17 +994,15 @@ class TestItemCrud(SplitModuleTest):
self.assertIsNone(new_history['previous_version'])
self.assertEqual(new_history['original_version'], new_module.definition_locator.definition_id)
self.assertEqual(new_history['edited_by'], "anotheruser")
- self.assertLessEqual(new_history['edited_on'], datetime.datetime.now(UTC))
- self.assertGreaterEqual(new_history['edited_on'], premod_time)
another_history = modulestore().get_definition_history_info(another_module.definition_locator)
- self.assertEqual(str(another_history['previous_version']), '0d00000040000000dddd0031')
+ self.assertEqual(another_history['previous_version'], original.definition_locator.definition_id)
def test_encoded_naming(self):
"""
Check that using odd characters in block id don't break ability to add and retrieve block.
"""
- parent_locator = BlockUsageLocator(package_id="contender", block_id="head345679", branch='draft')
- chapter_locator = BlockUsageLocator(package_id="contender", block_id="foo.bar_-~:0", branch='draft')
+ parent_locator = BlockUsageLocator(package_id="guestx.contender", block_id="head345679", branch='draft')
+ chapter_locator = BlockUsageLocator(package_id="guestx.contender", block_id="foo.bar_-~:0", branch='draft')
modulestore().create_item(
parent_locator, 'chapter', 'anotheruser',
block_id=chapter_locator.block_id,
@@ -628,7 +1013,7 @@ class TestItemCrud(SplitModuleTest):
self.assertEqual(new_module.location.block_id, "foo.bar_-~:0") # hardcode to ensure BUL init didn't change
# now try making that a parent of something
new_payload = "empty"
- problem_locator = BlockUsageLocator(package_id="contender", block_id="prob.bar_-~:99a", branch='draft')
+ problem_locator = BlockUsageLocator(package_id="guestx.contender", block_id="prob.bar_-~:99a", branch='draft')
modulestore().create_item(
chapter_locator, 'problem', 'anotheruser',
block_id=problem_locator.block_id,
@@ -729,13 +1114,12 @@ class TestItemCrud(SplitModuleTest):
"""
test updating an items metadata ensuring the definition doesn't version but the course does if it should
"""
- locator = BlockUsageLocator(package_id="GreekHero", block_id="problem3_2", branch='draft')
+ locator = BlockUsageLocator(package_id="testx.GreekHero", block_id="problem3_2", branch='draft')
problem = modulestore().get_item(locator)
pre_def_id = problem.definition_locator.definition_id
pre_version_guid = problem.location.version_guid
self.assertIsNotNone(pre_def_id)
self.assertIsNotNone(pre_version_guid)
- premod_time = datetime.datetime.now(UTC) - datetime.timedelta(seconds=1)
self.assertNotEqual(problem.max_attempts, 4, "Invalidates rest of test")
problem.max_attempts = 4
@@ -758,16 +1142,13 @@ class TestItemCrud(SplitModuleTest):
history_info = modulestore().get_course_history_info(current_course.location)
self.assertEqual(history_info['previous_version'], pre_version_guid)
- self.assertEqual(str(history_info['original_version']), self.GUID_D3)
self.assertEqual(history_info['edited_by'], "**replace_user**")
- self.assertGreaterEqual(history_info['edited_on'], premod_time)
- self.assertLessEqual(history_info['edited_on'], datetime.datetime.now(UTC))
def test_update_children(self):
"""
test updating an item's children ensuring the definition doesn't version but the course does if it should
"""
- locator = BlockUsageLocator(package_id="GreekHero", block_id="chapter3", branch='draft')
+ locator = BlockUsageLocator(package_id="testx.GreekHero", block_id="chapter3", branch='draft')
block = modulestore().get_item(locator)
pre_def_id = block.definition_locator.definition_id
pre_version_guid = block.location.version_guid
@@ -793,7 +1174,7 @@ class TestItemCrud(SplitModuleTest):
"""
test updating an item's definition: ensure it gets versioned as well as the course getting versioned
"""
- locator = BlockUsageLocator(package_id="GreekHero", block_id="head12345", branch='draft')
+ locator = BlockUsageLocator(package_id="testx.GreekHero", block_id="head12345", branch='draft')
block = modulestore().get_item(locator)
pre_def_id = block.definition_locator.definition_id
pre_version_guid = block.location.version_guid
@@ -810,8 +1191,10 @@ class TestItemCrud(SplitModuleTest):
"""
Test updating metadata, children, and definition in a single call ensuring all the versioning occurs
"""
+ locator = BlockUsageLocator(package_id="testx.GreekHero", branch='draft', block_id='problem1')
+ original = modulestore().get_item(locator)
# first add 2 children to the course for the update to manipulate
- locator = BlockUsageLocator(package_id="contender", block_id="head345679", branch='draft')
+ locator = BlockUsageLocator(package_id="guestx.contender", block_id="head345679", branch='draft')
category = 'problem'
new_payload = "empty"
modulestore().create_item(
@@ -822,7 +1205,7 @@ class TestItemCrud(SplitModuleTest):
modulestore().create_item(
locator, category, 'test_update_manifold',
fields={'display_name': 'problem 2', 'data': another_payload},
- definition_locator=DefinitionLocator("0d00000040000000dddd0031"),
+ definition_locator=original.definition_locator,
)
# pylint: disable=W0212
modulestore()._clear_cache()
@@ -878,6 +1261,9 @@ class TestItemCrud(SplitModuleTest):
# check subtree
def check_subtree(node):
+ """
+ Check contents of subtree recursively
+ """
if node:
node_loc = node.location
self.assertFalse(modulestore().has_item(reusable_location.package_id,
@@ -895,6 +1281,9 @@ class TestItemCrud(SplitModuleTest):
check_subtree(nodes[0])
def create_course_for_deletion(self):
+ """
+ Create a course we can delete
+ """
course = modulestore().create_course('nihilx.deletion', 'nihilx', 'deleting_user')
root = BlockUsageLocator(
package_id=course.location.package_id,
@@ -905,6 +1294,9 @@ class TestItemCrud(SplitModuleTest):
return modulestore().get_item(root)
def create_subtree_for_deletion(self, parent, category_queue):
+ """
+ Create a subtree in the tb deleted course
+ """
if not category_queue:
return
node = modulestore().create_item(parent, category_queue[0], 'deleting_user')
@@ -915,28 +1307,23 @@ class TestItemCrud(SplitModuleTest):
class TestCourseCreation(SplitModuleTest):
"""
- Test create_course, duh :-)
+ Test create_course
"""
def test_simple_creation(self):
"""
The simplest case but probing all expected results from it.
"""
# Oddly getting differences of 200nsec
- pre_time = datetime.datetime.now(UTC) - datetime.timedelta(milliseconds=1)
new_course = modulestore().create_course('test_org.test_course', 'test_org', 'create_user')
new_locator = new_course.location
# check index entry
index_info = modulestore().get_course_index_info(new_locator)
self.assertEqual(index_info['org'], 'test_org')
- self.assertGreaterEqual(index_info["edited_on"], pre_time)
- self.assertLessEqual(index_info["edited_on"], datetime.datetime.now(UTC))
self.assertEqual(index_info['edited_by'], 'create_user')
# check structure info
structure_info = modulestore().get_course_history_info(new_locator)
self.assertEqual(structure_info['original_version'], index_info['versions']['draft'])
self.assertIsNone(structure_info['previous_version'])
- self.assertGreaterEqual(structure_info["edited_on"], pre_time)
- self.assertLessEqual(structure_info["edited_on"], datetime.datetime.now(UTC))
self.assertEqual(structure_info['edited_by'], 'create_user')
# check the returned course object
self.assertIsInstance(new_course, CourseDescriptor)
@@ -952,8 +1339,7 @@ class TestCourseCreation(SplitModuleTest):
"""
Test making a course which points to an existing draft and published but not making any changes to either.
"""
- pre_time = datetime.datetime.now(UTC)
- original_locator = CourseLocator(package_id="wonderful", branch='draft')
+ original_locator = CourseLocator(package_id="testx.wonderful", branch='draft')
original_index = modulestore().get_course_index_info(original_locator)
new_draft = modulestore().create_course(
'best', 'leech', 'leech_master',
@@ -962,18 +1348,14 @@ class TestCourseCreation(SplitModuleTest):
self.assertRegexpMatches(new_draft_locator.package_id, 'best')
# the edited_by and other meta fields on the new course will be the original author not this one
self.assertEqual(new_draft.edited_by, 'test@edx.org')
- self.assertLess(new_draft.edited_on, pre_time)
self.assertEqual(new_draft_locator.version_guid, original_index['versions']['draft'])
# however the edited_by and other meta fields on course_index will be this one
new_index = modulestore().get_course_index_info(new_draft_locator)
- self.assertGreaterEqual(new_index["edited_on"], pre_time)
- self.assertLessEqual(new_index["edited_on"], datetime.datetime.now(UTC))
self.assertEqual(new_index['edited_by'], 'leech_master')
new_published_locator = CourseLocator(package_id=new_draft_locator.package_id, branch='published')
new_published = modulestore().get_course(new_published_locator)
self.assertEqual(new_published.edited_by, 'test@edx.org')
- self.assertLess(new_published.edited_on, pre_time)
self.assertEqual(new_published.location.version_guid, original_index['versions']['published'])
# changing this course will not change the original course
@@ -987,12 +1369,9 @@ class TestCourseCreation(SplitModuleTest):
self.assertNotEqual(new_index['versions']['draft'], original_index['versions']['draft'])
new_draft = modulestore().get_course(new_draft_locator)
self.assertEqual(new_item.edited_by, 'leech_master')
- self.assertGreaterEqual(new_item.edited_on, pre_time)
self.assertNotEqual(new_item.location.version_guid, original_index['versions']['draft'])
self.assertNotEqual(new_draft.location.version_guid, original_index['versions']['draft'])
structure_info = modulestore().get_course_history_info(new_draft_locator)
- self.assertGreaterEqual(structure_info["edited_on"], pre_time)
- self.assertLessEqual(structure_info["edited_on"], datetime.datetime.now(UTC))
self.assertEqual(structure_info['edited_by'], 'leech_master')
original_course = modulestore().get_course(original_locator)
@@ -1008,8 +1387,7 @@ class TestCourseCreation(SplitModuleTest):
"""
Create a new course which overrides metadata and course_data
"""
- pre_time = datetime.datetime.now(UTC)
- original_locator = CourseLocator(package_id="contender", branch='draft')
+ original_locator = CourseLocator(package_id="guestx.contender", branch='draft')
original = modulestore().get_course(original_locator)
original_index = modulestore().get_course_index_info(original_locator)
fields = {}
@@ -1029,12 +1407,9 @@ class TestCourseCreation(SplitModuleTest):
self.assertRegexpMatches(new_draft_locator.package_id, 'counter')
# the edited_by and other meta fields on the new course will be the original author not this one
self.assertEqual(new_draft.edited_by, 'leech_master')
- self.assertGreaterEqual(new_draft.edited_on, pre_time)
self.assertNotEqual(new_draft_locator.version_guid, original_index['versions']['draft'])
# however the edited_by and other meta fields on course_index will be this one
new_index = modulestore().get_course_index_info(new_draft_locator)
- self.assertGreaterEqual(new_index["edited_on"], pre_time)
- self.assertLessEqual(new_index["edited_on"], datetime.datetime.now(UTC))
self.assertEqual(new_index['edited_by'], 'leech_master')
self.assertEqual(new_draft.display_name, fields['display_name'])
self.assertDictEqual(
@@ -1046,7 +1421,7 @@ class TestCourseCreation(SplitModuleTest):
"""
Test changing the org, pretty id, etc of a course. Test that it doesn't allow changing the id, etc.
"""
- locator = CourseLocator(package_id="GreekHero", branch='draft')
+ locator = CourseLocator(package_id="testx.GreekHero", branch='draft')
course_info = modulestore().get_course_index_info(locator)
course_info['org'] = 'funkyU'
modulestore().update_course_index(course_info)
@@ -1059,17 +1434,18 @@ class TestCourseCreation(SplitModuleTest):
self.assertEqual(course_info['org'], 'moreFunky')
# an allowed but not necessarily recommended way to revert the draft version
+ head_course = modulestore().get_course(locator)
versions = course_info['versions']
- versions['draft'] = self.GUID_D1
+ versions['draft'] = head_course.previous_version
modulestore().update_course_index(course_info)
course = modulestore().get_course(locator)
- self.assertEqual(str(course.location.version_guid), self.GUID_D1)
+ self.assertEqual(course.location.version_guid, versions['draft'])
# an allowed but not recommended way to publish a course
- versions['published'] = self.GUID_D1
+ versions['published'] = versions['draft']
modulestore().update_course_index(course_info)
course = modulestore().get_course(CourseLocator(package_id=locator.package_id, branch="published"))
- self.assertEqual(str(course.location.version_guid), self.GUID_D1)
+ self.assertEqual(course.location.version_guid, versions['draft'])
def test_create_with_root(self):
"""
@@ -1111,11 +1487,11 @@ class TestInheritance(SplitModuleTest):
"""
# Note, not testing value where defined (course) b/c there's no
# defined accessor for it on CourseDescriptor.
- locator = BlockUsageLocator(package_id="GreekHero", block_id="problem3_2", branch='draft')
+ locator = BlockUsageLocator(package_id="testx.GreekHero", block_id="problem3_2", branch='draft')
node = modulestore().get_item(locator)
# inherited
self.assertEqual(node.graceperiod, datetime.timedelta(hours=2))
- locator = BlockUsageLocator(package_id="GreekHero", block_id="problem1", branch='draft')
+ locator = BlockUsageLocator(package_id="testx.GreekHero", block_id="problem1", branch='draft')
node = modulestore().get_item(locator)
# overridden
self.assertEqual(node.graceperiod, datetime.timedelta(hours=4))
@@ -1130,14 +1506,14 @@ class TestPublish(SplitModuleTest):
self.user = random.getrandbits(32)
def tearDown(self):
- SplitModuleTest.tearDownClass()
+ SplitModuleTest.tearDown(self)
def test_publish_safe(self):
"""
Test the standard patterns: publish to new branch, revise and publish
"""
- source_course = CourseLocator(package_id="GreekHero", branch='draft')
- dest_course = CourseLocator(package_id="GreekHero", branch="published")
+ source_course = CourseLocator(package_id="testx.GreekHero", branch='draft')
+ dest_course = CourseLocator(package_id="testx.GreekHero", branch="published")
modulestore().xblock_publish(self.user, source_course, dest_course, ["head12345"], ["chapter2", "chapter3"])
expected = ["head12345", "chapter1"]
self._check_course(
@@ -1145,19 +1521,19 @@ class TestPublish(SplitModuleTest):
)
# add a child under chapter1
new_module = modulestore().create_item(
- self._usage(source_course, "chapter1"), "sequential", self.user,
+ BlockUsageLocator.make_relative(source_course, "chapter1"), "sequential", self.user,
fields={'display_name': 'new sequential'},
)
# remove chapter1 from expected b/c its pub'd version != the source anymore since source changed
expected.remove("chapter1")
# check that it's not in published course
with self.assertRaises(ItemNotFoundError):
- modulestore().get_item(self._usage(dest_course, new_module.location.block_id))
+ modulestore().get_item(BlockUsageLocator.make_relative(dest_course, new_module.location.block_id))
# publish it
modulestore().xblock_publish(self.user, source_course, dest_course, [new_module.location.block_id], None)
expected.append(new_module.location.block_id)
# check that it is in the published course and that its parent is the chapter
- pub_module = modulestore().get_item(self._usage(dest_course, new_module.location.block_id))
+ pub_module = modulestore().get_item(BlockUsageLocator.make_relative(dest_course, new_module.location.block_id))
self.assertEqual(
modulestore().get_parent_locations(pub_module.location)[0].block_id, "chapter1"
)
@@ -1169,7 +1545,7 @@ class TestPublish(SplitModuleTest):
modulestore().xblock_publish(self.user, source_course, dest_course, [new_module.location.block_id], None)
expected.append(new_module.location.block_id)
# check that it is in the published course (no error means it worked)
- pub_module = modulestore().get_item(self._usage(dest_course, new_module.location.block_id))
+ pub_module = modulestore().get_item(BlockUsageLocator.make_relative(dest_course, new_module.location.block_id))
self._check_course(
source_course, dest_course, expected, ["chapter2", "chapter3", "problem1", "problem3_2"]
)
@@ -1178,13 +1554,13 @@ class TestPublish(SplitModuleTest):
"""
Test the exceptions which preclude successful publication
"""
- source_course = CourseLocator(package_id="GreekHero", branch='draft')
+ source_course = CourseLocator(package_id="testx.GreekHero", branch='draft')
# destination does not exist
destination_course = CourseLocator(package_id="Unknown", branch="published")
with self.assertRaises(ItemNotFoundError):
modulestore().xblock_publish(self.user, source_course, destination_course, ["chapter3"], None)
# publishing into a new branch w/o publishing the root
- destination_course = CourseLocator(package_id="GreekHero", branch="published")
+ destination_course = CourseLocator(package_id="testx.GreekHero", branch="published")
with self.assertRaises(ItemNotFoundError):
modulestore().xblock_publish(self.user, source_course, destination_course, ["chapter3"], None)
# publishing a subdag w/o the parent already in course
@@ -1196,17 +1572,17 @@ class TestPublish(SplitModuleTest):
"""
Test publishing moves and deletes.
"""
- source_course = CourseLocator(package_id="GreekHero", branch='draft')
- dest_course = CourseLocator(package_id="GreekHero", branch="published")
+ source_course = CourseLocator(package_id="testx.GreekHero", branch='draft')
+ dest_course = CourseLocator(package_id="testx.GreekHero", branch="published")
modulestore().xblock_publish(self.user, source_course, dest_course, ["head12345"], ["chapter2"])
expected = ["head12345", "chapter1", "chapter3", "problem1", "problem3_2"]
self._check_course(source_course, dest_course, expected, ["chapter2"])
# now move problem1 and delete problem3_2
- chapter1 = modulestore().get_item(self._usage(source_course, "chapter1"))
- chapter3 = modulestore().get_item(self._usage(source_course, "chapter3"))
+ chapter1 = modulestore().get_item(BlockUsageLocator.make_relative(source_course, "chapter1"))
+ chapter3 = modulestore().get_item(BlockUsageLocator.make_relative(source_course, "chapter3"))
chapter1.children.append("problem1")
chapter3.children.remove("problem1")
- modulestore().delete_item(self._usage(source_course, "problem3_2"), self.user)
+ modulestore().delete_item(BlockUsageLocator.make_relative(source_course, "problem3_2"), self.user)
modulestore().xblock_publish(self.user, source_course, dest_course, ["head12345"], ["chapter2"])
expected = ["head12345", "chapter1", "chapter3", "problem1"]
self._check_course(source_course, dest_course, expected, ["chapter2", "problem3_2"])
@@ -1215,13 +1591,18 @@ class TestPublish(SplitModuleTest):
"""
Check that the course has the expected blocks and does not have the unexpected blocks
"""
+ history_info = modulestore().get_course_history_info(dest_course_loc)
+ self.assertEqual(history_info['edited_by'], self.user)
for expected in expected_blocks:
- source = modulestore().get_item(self._usage(source_course_loc, expected))
- pub_copy = modulestore().get_item(self._usage(dest_course_loc, expected))
+ source = modulestore().get_item(BlockUsageLocator.make_relative(source_course_loc, expected))
+ pub_copy = modulestore().get_item(BlockUsageLocator.make_relative(dest_course_loc, expected))
# everything except previous_version & children should be the same
self.assertEqual(source.category, pub_copy.category)
self.assertEqual(source.update_version, pub_copy.update_version)
- self.assertEqual(self.user, pub_copy.edited_by)
+ self.assertEqual(
+ self.user, pub_copy.edited_by,
+ "{} edited_by {} not {}".format(pub_copy.location, pub_copy.edited_by, self.user)
+ )
for field in source.fields.values():
if field.name == 'children':
self._compare_children(field.read_from(source), field.read_from(pub_copy), unexpected_blocks)
@@ -1229,13 +1610,7 @@ class TestPublish(SplitModuleTest):
self.assertEqual(field.read_from(source), field.read_from(pub_copy))
for unexp in unexpected_blocks:
with self.assertRaises(ItemNotFoundError):
- modulestore().get_item(self._usage(dest_course_loc, unexp))
-
- def _usage(self, course_loc, block_id):
- """
- Generate a BlockUsageLocator for the combo of the course location and block id
- """
- return BlockUsageLocator(package_id=course_loc.package_id, branch=course_loc.branch, block_id=block_id)
+ modulestore().get_item(BlockUsageLocator.make_relative(dest_course_loc, unexp))
def _compare_children(self, source_children, dest_children, unexpected):
"""
@@ -1252,15 +1627,18 @@ class TestPublish(SplitModuleTest):
#===========================================
-# This mocks the django.modulestore() function and is intended purely to disentangle
-# the tests from django
def modulestore():
+ """
+ Mock the django dependent global modulestore function to disentangle tests from django
+ """
def load_function(engine_path):
+ """
+ Load the given engine
+ """
module_path, _, name = engine_path.rpartition('.')
return getattr(import_module(module_path), name)
if SplitModuleTest.modulestore is None:
- SplitModuleTest.bootstrapDB()
class_ = load_function(SplitModuleTest.MODULESTORE['ENGINE'])
options = {}
@@ -1274,6 +1652,8 @@ def modulestore():
**options
)
+ SplitModuleTest.bootstrapDB()
+
return SplitModuleTest.modulestore
diff --git a/common/test/data/splitmongo_json/active_versions.json b/common/test/data/splitmongo_json/active_versions.json
deleted file mode 100644
index e84f4659bd..0000000000
--- a/common/test/data/splitmongo_json/active_versions.json
+++ /dev/null
@@ -1,24 +0,0 @@
-[{"_id" : "GreekHero",
- "org" : "testx",
- "versions" : {
- "draft" : { "$oid" : "1d00000000000000dddd0000" }
- },
- "edited_on" : {"$date" : 1364481713238},
- "edited_by" : "test@edx.org"},
-
- {"_id" : "wonderful",
- "org" : "testx",
- "versions" : {
- "draft" : { "$oid" : "1d00000000000000dddd2222" },
- "published" : { "$oid" : "1d00000000000000eeee0000" }
- },
- "edited_on" : {"$date" : 1364481313238},
- "edited_by" : "test@edx.org"},
-
- {"_id" : "contender",
- "org" : "guestx",
- "versions" : {
- "draft" : { "$oid" : "1d00000000000000dddd5555" }},
- "edited_on" : {"$date" : 1364491313238},
- "edited_by" : "test@guestx.edu"}
-]
diff --git a/common/test/data/splitmongo_json/definitions.json b/common/test/data/splitmongo_json/definitions.json
deleted file mode 100644
index 81b84fe951..0000000000
--- a/common/test/data/splitmongo_json/definitions.json
+++ /dev/null
@@ -1,356 +0,0 @@
-[
- {
- "_id": { "$oid" : "ad00000000000000dddd0000"},
- "category":"course",
- "fields":{
- "textbooks":[
-
- ],
- "grading_policy":{
- "GRADER":[
- {
- "min_count":4,
- "weight":0.15,
- "type":"Homework",
- "drop_count":2,
- "short_label":"HWa"
- },
- {
- "short_label":"",
- "min_count":12,
- "type":"Lab",
- "drop_count":2,
- "weight":0.15
- },
- {
- "short_label":"Midterm",
- "min_count":1,
- "type":"Midterm Exam",
- "drop_count":0,
- "weight":0.3
- },
- {
- "short_label":"Final",
- "min_count":1,
- "type":"Final Exam",
- "drop_count":0,
- "weight":0.4
- }
- ],
- "GRADE_CUTOFFS":{
- "Pass":0.45
- }
- },
- "wiki_slug":null
- },
- "edit_info": {
- "edited_by":"testassist@edx.org",
- "edited_on":{"$date" : 1364481713238},
- "previous_version":{ "$oid" : "ad00000000000000dddd0001"},
- "original_version":{ "$oid" : "ad00000000000000dddd0010"}
- }
- },
- {
- "_id":{ "$oid" : "ad00000000000000dddd0001"},
- "category":"course",
- "fields":{
- "textbooks":[
-
- ],
- "grading_policy":{
- "GRADER":[
- {
- "min_count":5,
- "weight":0.15,
- "type":"Homework",
- "drop_count":1,
- "short_label":"HWa"
- },
- {
- "short_label":"",
- "min_count":12,
- "type":"Lab",
- "drop_count":2,
- "weight":0.15
- },
- {
- "short_label":"Midterm",
- "min_count":1,
- "type":"Midterm Exam",
- "drop_count":0,
- "weight":0.3
- },
- {
- "short_label":"Final",
- "min_count":1,
- "type":"Final Exam",
- "drop_count":0,
- "weight":0.4
- }
- ],
- "GRADE_CUTOFFS":{
- "Pass":0.55
- }
- },
- "wiki_slug":null
- },
- "edit_info": {
- "edited_by":"testassist@edx.org",
- "edited_on":{"$date" : 1364481713238},
- "previous_version":{ "$oid" : "ad00000000000000dddd0010"},
- "original_version":{ "$oid" : "ad00000000000000dddd0010"}
- }
- },
- {
- "_id":{ "$oid" : "ad00000000000000dddd0010"},
- "category":"course",
- "fields":{
- "textbooks":[
-
- ],
- "grading_policy":{
- "GRADER":[
- {
- "min_count":5,
- "weight":0.15,
- "type":"Homework",
- "drop_count":1,
- "short_label":"HWa"
- },
- {
- "short_label":"",
- "min_count":2,
- "type":"Lab",
- "drop_count":0,
- "weight":0.15
- },
- {
- "short_label":"Midterm",
- "min_count":1,
- "type":"Midterm Exam",
- "drop_count":0,
- "weight":0.3
- },
- {
- "short_label":"Final",
- "min_count":1,
- "type":"Final Exam",
- "drop_count":0,
- "weight":0.4
- }
- ],
- "GRADE_CUTOFFS":{
- "Pass":0.75
- }
- },
- "wiki_slug":null
- },
- "edit_info": {
- "edited_by":"test@edx.org",
- "edited_on":{"$date": 1364473713238},
- "previous_version":null,
- "original_version":{ "$oid" : "ad00000000000000dddd0010"}
- }
- },
- {
- "_id":{ "$oid" : "ad00000000000000dddd0020"},
- "category":"course",
- "fields":{
- "textbooks":[
-
- ],
- "grading_policy":{
- "GRADER":[
- {
- "min_count":14,
- "weight":0.25,
- "type":"Homework",
- "drop_count":1,
- "short_label":"HWa"
- },
- {
- "short_label":"",
- "min_count":12,
- "type":"Lab",
- "drop_count":2,
- "weight":0.25
- },
- {
- "short_label":"Midterm",
- "min_count":1,
- "type":"Midterm Exam",
- "drop_count":0,
- "weight":0.2
- },
- {
- "short_label":"Final",
- "min_count":1,
- "type":"Final Exam",
- "drop_count":0,
- "weight":0.3
- }
- ],
- "GRADE_CUTOFFS":{
- "Pass":0.45
- }
- },
- "wiki_slug":null
- },
- "edit_info": {
- "edited_by":"test@edx.org",
- "edited_on":{"$date": 1364481313238},
- "previous_version":{ "$oid" : "2d00000000000000dddd0020"},
- "original_version":{ "$oid" : "2d00000000000000dddd0020"}
- }
- },
- {
- "_id":{ "$oid" : "2d00000000000000dddd0020"},
- "category":"course",
- "fields":{
- "textbooks":[
-
- ],
- "grading_policy":{
- "GRADER":[
- {
- "min_count":14,
- "weight":0.25,
- "type":"Homework",
- "drop_count":1,
- "short_label":"HWa"
- },
- {
- "short_label":"",
- "min_count":12,
- "type":"Lab",
- "drop_count":2,
- "weight":0.25
- },
- {
- "short_label":"Midterm",
- "min_count":1,
- "type":"Midterm Exam",
- "drop_count":0,
- "weight":0.2
- },
- {
- "short_label":"Final",
- "min_count":1,
- "type":"Final Exam",
- "drop_count":0,
- "weight":0.3
- }
- ],
- "GRADE_CUTOFFS":{
- "Pass":0.95
- }
- },
- "wiki_slug":null
- },
- "edit_info": {
- "edited_by":"test@edx.org",
- "edited_on":{"$date" : 1364481313238},
- "previous_version":null,
- "original_version":{ "$oid" : "2d00000000000000dddd0020"}
- }
- },
- {
- "_id":{ "$oid" : "3d00000000000000dddd0020"},
- "category":"course",
- "fields":{
- "textbooks":[
-
- ],
- "grading_policy":{
- "GRADER":[
- {
- "min_count":4,
- "weight":0.25,
- "type":"Homework",
- "drop_count":0,
- "short_label":"HW"
- },
- {
- "short_label":"Midterm",
- "min_count":1,
- "type":"Midterm Exam",
- "drop_count":0,
- "weight":0.4
- },
- {
- "short_label":"Final",
- "min_count":1,
- "type":"Final Exam",
- "drop_count":0,
- "weight":0.35
- }
- ],
- "GRADE_CUTOFFS":{
- "Pass":0.25
- }
- },
- "wiki_slug":null
- },
- "edit_info": {
- "edited_by":"test@edx.org",
- "edited_on":{"$date" : 1364481313238},
- "previous_version":null,
- "original_version":{ "$oid" : "2d00000000000000dddd0020"}
- }
- },
- {
- "_id":{ "$oid" : "cd00000000000000dddd0020"},
- "category":"chapter",
- "fields":{},
- "edit_info": {
- "edited_by":"testassist@edx.org",
- "edited_on":{"$date" : 1364483713238},
- "previous_version":null,
- "original_version":{ "$oid" : "cd00000000000000dddd0020"}
- }
- },
- {
- "_id":{ "$oid" : "cd00000000000000dddd0022"},
- "category":"chapter",
- "fields":{},
- "edit_info": {
- "edited_by":"testassist@edx.org",
- "edited_on":{"$date" : 1364483713238},
- "previous_version":null,
- "original_version":{ "$oid" : "cd00000000000000dddd0022"}
- }
- },
- {
- "_id":{ "$oid" : "cd00000000000000dddd0032"},
- "category":"chapter",
- "fields":{},
- "edit_info": {
- "edited_by":"testassist@edx.org",
- "edited_on":{"$date" : 1364483713238},
- "previous_version":null,
- "original_version":{ "$oid" : "cd00000000000000dddd0032"}
- }
- },
- {
- "_id":{ "$oid" : "0d00000040000000dddd0031"},
- "category":"problem",
- "fields": {"data": ""},
- "edit_info": {
- "edited_by":"testassist@edx.org",
- "edited_on":{"$date" : 1364483713238},
- "previous_version":null,
- "original_version":{ "$oid" : "0d00000040000000dddd0031"}
- }
- },
- {
- "_id":{ "$oid" : "0d00000040000000dddd0032"},
- "category":"problem",
- "fields": {"data": ""},
- "edit_info": {
- "edited_by":"testassist@edx.org",
- "edited_on":{"$date" : 1364483713238},
- "previous_version":null,
- "original_version":{ "$oid" : "0d00000040000000dddd0032"}
- }
- }
-]
\ No newline at end of file
diff --git a/common/test/data/splitmongo_json/structures.json b/common/test/data/splitmongo_json/structures.json
deleted file mode 100644
index 644df803b4..0000000000
--- a/common/test/data/splitmongo_json/structures.json
+++ /dev/null
@@ -1,495 +0,0 @@
-[
- {
- "_id": { "$oid" : "1d00000000000000dddd0000"},
- "root":"head12345",
- "original_version":{ "$oid" : "1d00000000000000dddd3333" },
- "previous_version":{ "$oid" : "1d00000000000000dddd1111" },
- "edited_by":"testassist@edx.org",
- "edited_on":{
- "$date":1364483713238
- },
- "blocks":{
- "head12345":{
- "category":"course",
- "definition":{ "$oid" : "ad00000000000000dddd0000"},
- "fields":{
- "children":[
- "chapter1",
- "chapter2",
- "chapter3"
- ],
- "end":"2013-06-13T04:30",
- "tabs":[
- {
- "type":"courseware"
- },
- {
- "type":"course_info",
- "name":"Course Info"
- },
- {
- "type":"discussion",
- "name":"Discussion"
- },
- {
- "type":"wiki",
- "name":"Wiki"
- },
- {
- "type":"static_tab",
- "name":"Syllabus",
- "url_slug":"01356a17b5924b17a04b7fc2426a3798"
- },
- {
- "type":"static_tab",
- "name":"Advice for Students",
- "url_slug":"57e9991c0d794ff58f7defae3e042e39"
- }
- ],
- "enrollment_start":"2013-01-01T05:00",
- "graceperiod":"2 hours 0 minutes 0 seconds",
- "start":"2013-02-14T05:00",
- "enrollment_end":"2013-03-02T05:00",
- "data_dir":"MITx-2-Base",
- "advertised_start":"Fall 2013",
- "display_name":"The Ancient Greek Hero"
- },
- "edit_info": {
- "update_version":{ "$oid" : "1d00000000000000dddd0000" },
- "previous_version":{ "$oid" : "1d00000000000000dddd1111" },
- "edited_by":"testassist@edx.org",
- "edited_on":{
- "$date":1364483713238
- }
- }
- },
- "chapter1":{
- "category":"chapter",
- "definition":{ "$oid" : "cd00000000000000dddd0020"},
- "fields":{
- "children":[
-
- ],
- "display_name":"Hercules"
- },
- "edit_info": {
- "update_version":{ "$oid" : "1d00000000000000dddd0000" },
- "previous_version":null,
- "edited_by":"testassist@edx.org",
- "edited_on":{
- "$date":1364483713238
- }
- }
- },
- "chapter2":{
- "category":"chapter",
- "definition":{ "$oid" : "cd00000000000000dddd0022"},
- "fields":{
- "children":[
-
- ],
- "display_name":"Hera heckles Hercules"
- },
- "edit_info": {
- "update_version":{ "$oid" : "1d00000000000000dddd0000" },
- "previous_version":null,
- "edited_by":"testassist@edx.org",
- "edited_on":{
- "$date":1364483713238
- }
- }
- },
- "chapter3":{
- "category":"chapter",
- "definition":{ "$oid" : "cd00000000000000dddd0032"},
- "fields":{
- "children":[
- "problem1",
- "problem3_2"
- ],
- "display_name":"Hera cuckolds Zeus"
- },
- "edit_info": {
- "update_version":{ "$oid" : "1d00000000000000dddd0000" },
- "previous_version":null,
- "edited_by":"testassist@edx.org",
- "edited_on":{
- "$date":1364483713238
- }
- }
- },
- "problem1":{
- "category":"problem",
- "definition":{ "$oid" : "0d00000040000000dddd0031"},
- "fields":{
- "children":[
-
- ],
- "display_name":"Problem 3.1",
- "graceperiod":"4 hours 0 minutes 0 seconds"
- },
- "edit_info": {
- "update_version":{ "$oid" : "1d00000000000000dddd0000" },
- "previous_version":null,
- "edited_by":"testassist@edx.org",
- "edited_on":{
- "$date":1364483713238
- }
- }
- },
- "problem3_2":{
- "category":"problem",
- "definition":{ "$oid" : "0d00000040000000dddd0032"},
- "fields":{
- "children":[
-
- ],
- "display_name":"Problem 3.2"
- },
- "edit_info": {
- "update_version":{ "$oid" : "1d00000000000000dddd0000" },
- "previous_version":null,
- "edited_by":"testassist@edx.org",
- "edited_on":{
- "$date":1364483713238
- }
- }
- }
- }
- },
- {
- "_id": { "$oid" : "1d00000000000000dddd1111"},
- "root":"head12345",
- "original_version":{ "$oid" : "1d00000000000000dddd3333" },
- "previous_version":{ "$oid" : "1d00000000000000dddd3333" },
- "edited_by":"testassist@edx.org",
- "edited_on":{
- "$date":1364481713238
- },
- "blocks":{
- "head12345":{
- "category":"course",
- "definition":{ "$oid" : "ad00000000000000dddd0001"},
- "fields":{
- "children":[
-
- ],
- "end":"2013-04-13T04:30",
- "tabs":[
- {
- "type":"courseware"
- },
- {
- "type":"course_info",
- "name":"Course Info"
- },
- {
- "type":"discussion",
- "name":"Discussion"
- },
- {
- "type":"wiki",
- "name":"Wiki"
- },
- {
- "type":"static_tab",
- "name":"Syllabus",
- "url_slug":"01356a17b5924b17a04b7fc2426a3798"
- },
- {
- "type":"static_tab",
- "name":"Advice for Students",
- "url_slug":"57e9991c0d794ff58f7defae3e042e39"
- }
- ],
- "enrollment_start":null,
- "graceperiod":"2 hours 0 minutes 0 seconds",
- "start":"2013-02-14T05:00",
- "enrollment_end":null,
- "data_dir":"MITx-2-Base",
- "advertised_start":null,
- "display_name":"The Ancient Greek Hero"
- },
- "edit_info": {
- "update_version":{ "$oid" : "1d00000000000000dddd1111" },
- "previous_version":{ "$oid" : "1d00000000000000dddd3333" },
- "edited_by":"testassist@edx.org",
- "edited_on":{
- "$date":1364481713238
- }
- }
- }
- }
- },
- {
- "_id": { "$oid" : "1d00000000000000dddd3333"},
- "root":"head12345",
- "original_version":{ "$oid" : "1d00000000000000dddd3333" },
- "previous_version":null,
- "edited_by":"test@edx.org",
- "edited_on":{
- "$date":1364473713238
- },
- "blocks":{
- "head12345":{
- "category":"course",
- "definition":{ "$oid" : "ad00000000000000dddd0010"},
- "fields":{
- "children":[
-
- ],
- "end":null,
- "tabs":[
- {
- "type":"courseware"
- },
- {
- "type":"course_info",
- "name":"Course Info"
- },
- {
- "type":"discussion",
- "name":"Discussion"
- },
- {
- "type":"wiki",
- "name":"Wiki"
- }
- ],
- "enrollment_start":null,
- "graceperiod":null,
- "start":"2013-02-14T05:00",
- "enrollment_end":null,
- "data_dir":"MITx-2-Base",
- "advertised_start":null,
- "display_name":"The Ancient Greek Hero"
- },
- "edit_info": {
- "update_version":{ "$oid" : "1d00000000000000dddd3333" },
- "previous_version":null,
- "edited_by":"test@edx.org",
- "edited_on":{
- "$date":1364473713238
- }
- }
- }
- }
- },
- {
- "_id": { "$oid" : "1d00000000000000dddd2222"},
- "root":"head23456",
- "original_version":{ "$oid" : "1d00000000000000dddd4444" },
- "previous_version":{ "$oid" : "1d00000000000000dddd4444" },
- "edited_by":"test@edx.org",
- "edited_on":{
- "$date":1364481313238
- },
- "blocks":{
- "head23456":{
- "category":"course",
- "definition":{ "$oid" : "ad00000000000000dddd0020"},
- "fields":{
- "children":[
-
- ],
- "end":null,
- "tabs":[
- {
- "type":"courseware"
- },
- {
- "type":"course_info",
- "name":"Course Info"
- },
- {
- "type":"discussion",
- "name":"Discussion"
- },
- {
- "type":"wiki",
- "name":"Wiki"
- }
- ],
- "enrollment_start":null,
- "graceperiod":null,
- "start":"2013-02-14T05:00",
- "enrollment_end":null,
- "data_dir":"MITx-2-Base",
- "advertised_start":null,
- "display_name":"The most wonderful course"
- },
- "edit_info": {
- "update_version":{ "$oid" : "1d00000000000000dddd2222" },
- "previous_version":{ "$oid" : "1d00000000000000dddd4444" },
- "edited_by":"test@edx.org",
- "edited_on":{
- "$date":1364481313238
- }
- }
-
- }
- }
- },
- {
- "_id": { "$oid" : "1d00000000000000dddd4444"},
- "root":"head23456",
- "original_version":{ "$oid" : "1d00000000000000dddd4444" },
- "previous_version":null,
- "edited_by":"test@edx.org",
- "edited_on":{
- "$date":1364480313238
- },
- "blocks":{
- "head23456":{
- "category":"course",
- "definition":{ "$oid" : "2d00000000000000dddd0020"},
- "fields":{
- "children":[
-
- ],
- "end":null,
- "tabs":[
- {
- "type":"courseware"
- },
- {
- "type":"course_info",
- "name":"Course Info"
- },
- {
- "type":"discussion",
- "name":"Discussion"
- },
- {
- "type":"wiki",
- "name":"Wiki"
- }
- ],
- "enrollment_start":null,
- "graceperiod":null,
- "start":"2013-02-14T05:00",
- "enrollment_end":null,
- "data_dir":"MITx-2-Base",
- "advertised_start":null,
- "display_name":"A wonderful course"
- },
- "edit_info": {
- "update_version":{ "$oid" : "1d00000000000000dddd4444" },
- "previous_version":null,
- "edited_by":"test@edx.org",
- "edited_on":{
- "$date":1364480313238
- }
- }
- }
- }
- },
- {
- "_id": { "$oid" : "1d00000000000000eeee0000"},
- "root":"head23456",
- "original_version":{ "$oid" : "1d00000000000000eeee0000" },
- "previous_version":null,
- "edited_by":"test@edx.org",
- "edited_on":{
- "$date":1364481333238
- },
- "blocks":{
- "head23456":{
- "category":"course",
- "definition":{ "$oid" : "ad00000000000000dddd0020"},
- "fields":{
- "children":[
-
- ],
- "end":null,
- "tabs":[
- {
- "type":"courseware"
- },
- {
- "type":"course_info",
- "name":"Course Info"
- },
- {
- "type":"discussion",
- "name":"Discussion"
- },
- {
- "type":"wiki",
- "name":"Wiki"
- }
- ],
- "enrollment_start":null,
- "graceperiod":null,
- "start":"2013-02-14T05:00",
- "enrollment_end":null,
- "data_dir":"MITx-2-Base",
- "advertised_start":null,
- "display_name":"The most wonderful course"
- },
- "edit_info": {
- "update_version":{ "$oid" : "1d00000000000000eeee0000" },
- "previous_version":null,
- "edited_by":"test@edx.org",
- "edited_on":{
- "$date":1364481333238
- }
- }
- }
- }
- },
- {
- "_id": { "$oid" : "1d00000000000000dddd5555"},
- "root":"head345679",
- "original_version":{ "$oid" : "1d00000000000000dddd5555" },
- "previous_version":null,
- "edited_by":"test@guestx.edu",
- "edited_on":{
- "$date":1364491313238
- },
- "blocks":{
- "head345679":{
- "category":"course",
- "definition":{ "$oid" : "3d00000000000000dddd0020"},
- "fields":{
- "children":[
-
- ],
- "end":null,
- "tabs":[
- {
- "type":"courseware"
- },
- {
- "type":"course_info",
- "name":"Course Info"
- },
- {
- "type":"discussion",
- "name":"Discussion"
- },
- {
- "type":"wiki",
- "name":"Wiki"
- }
- ],
- "enrollment_start":null,
- "graceperiod":null,
- "start":"2013-03-14T05:00",
- "enrollment_end":null,
- "data_dir":"MITx-3-Base",
- "advertised_start":null,
- "display_name":"Yet another contender"
- },
- "edit_info": {
- "update_version":{ "$oid" : "1d00000000000000dddd5555" },
- "previous_version":null,
- "edited_by":"test@guestx.edu",
- "edited_on":{
- "$date":1364491313238
- }
- }
- }
- }
- }
-]