def mock_descriptor(fields=[]):
    descriptor = Mock(entry_point=XBlock.entry_point)
    descriptor.scope_ids = ScopeIds('user1', 'mock_problem', location('def_id'), location('usage_id'))
    descriptor.module_class.fields.values.return_value = fields
    descriptor.fields.values.return_value = fields
    descriptor.module_class.__name__ = 'MockProblemModule'
    return descriptor
def mock_descriptor(fields=[]):
    descriptor = Mock()
    descriptor.scope_ids = ScopeIds('user1', 'mock_problem', location('def_id'), location('usage_id'))
    descriptor.module_class.fields.values.return_value = fields
    descriptor.fields.values.return_value = fields
    descriptor.module_class.__name__ = 'MockProblemModule'
    return descriptor
Example #3
0
def mock_descriptor(fields=[]):
    descriptor = Mock(entry_point=XBlock.entry_point)
    descriptor.scope_ids = ScopeIds("user1", "mock_problem", location("def_id"), location("usage_id"))
    descriptor.module_class.fields.values.return_value = fields
    descriptor.fields.values.return_value = fields
    descriptor.module_class.__name__ = "MockProblemModule"
    return descriptor
Example #4
0
    def test_set_field_in_missing_student_module(self):
        "Test that setting a field in a missing StudentModule creates the student module"
        self.assertEquals(0, len(self.field_data_cache))
        self.assertEquals(0, StudentModule.objects.all().count())

        # We are updating a problem, so we write to courseware_studentmodulehistoryextended
        # as well as courseware_studentmodule. We also need to read the database
        # to discover if something other than the DjangoXBlockUserStateClient
        # has written to the StudentModule (such as UserStateCache setting the score
        # on the StudentModule).
        # Django 1.8 also has a number of other BEGIN and SAVESTATE queries.
        with self.assertNumQueries(4, using='default'):
            with self.assertNumQueries(1, using='student_module_history'):
                self.kvs.set(user_state_key('a_field'), 'a_value')

        self.assertEquals(
            1,
            sum(len(cache) for cache in self.field_data_cache.cache.values()))
        self.assertEquals(1, StudentModule.objects.all().count())

        student_module = StudentModule.objects.all()[0]
        self.assertEquals({'a_field': 'a_value'},
                          json.loads(student_module.state))
        self.assertEquals(self.user, student_module.student)
        self.assertEquals(
            location('usage_id').replace(run=None),
            student_module.module_state_key)
        self.assertEquals(course_id, student_module.course_id)
Example #5
0
 def setUp(self):
     super(TestStudentModuleHistoryBackends, self).setUp()
     for record in (1, 2, 3):
         # This will store into CSMHE via the post_save signal
         csm = StudentModuleFactory.create(module_state_key=location('usage_id'),
                                           course_id=course_id,
                                           state=json.dumps({'type': 'csmhe', 'order': record}))
         # This manually gets us a CSMH record to compare
         csmh = StudentModuleHistory(student_module=csm,
                                     version=None,
                                     created=csm.modified,
                                     state=json.dumps({'type': 'csmh', 'order': record}),
                                     grade=csm.grade,
                                     max_grade=csm.max_grade)
         csmh.save()
    def test_set_field_in_missing_student_module(self):
        "Test that setting a field in a missing StudentModule creates the student module"
        self.assertEquals(0, len(self.field_data_cache.cache))
        self.assertEquals(0, StudentModule.objects.all().count())

        self.kvs.set(user_state_key('a_field'), 'a_value')

        self.assertEquals(1, len(self.field_data_cache.cache))
        self.assertEquals(1, StudentModule.objects.all().count())

        student_module = StudentModule.objects.all()[0]
        self.assertEquals({'a_field': 'a_value'}, json.loads(student_module.state))
        self.assertEquals(self.user, student_module.student)
        self.assertEquals(location('usage_id').replace(run=None), student_module.module_state_key)
        self.assertEquals(course_id, student_module.course_id)
Example #7
0
    def test_set_field_in_missing_student_module(self):
        "Test that setting a field in a missing StudentModule creates the student module"
        self.assertEquals(0, len(self.field_data_cache.cache))
        self.assertEquals(0, StudentModule.objects.all().count())

        self.kvs.set(user_state_key('a_field'), 'a_value')

        self.assertEquals(1, len(self.field_data_cache.cache))
        self.assertEquals(1, StudentModule.objects.all().count())

        student_module = StudentModule.objects.all()[0]
        self.assertEquals({'a_field': 'a_value'}, json.loads(student_module.state))
        self.assertEquals(self.user, student_module.student)
        self.assertEquals(location('usage_id').replace(run=None), student_module.module_state_key)
        self.assertEquals(course_id, student_module.course_id)
Example #8
0
    def test_set_field_in_missing_student_module(self):
        "Test that setting a field in a missing StudentModule creates the student module"
        self.assertEquals(0, len(self.field_data_cache.cache))
        self.assertEquals(0, StudentModule.objects.all().count())

        # We are updating a problem, so we write to courseware_studentmodulehistory
        # as well as courseware_studentmodule
        with self.assertNumQueries(2):
            self.kvs.set(user_state_key('a_field'), 'a_value')

        self.assertEquals(1, len(self.field_data_cache.cache))
        self.assertEquals(1, StudentModule.objects.all().count())

        student_module = StudentModule.objects.all()[0]
        self.assertEquals({'a_field': 'a_value'}, json.loads(student_module.state))
        self.assertEquals(self.user, student_module.student)
        self.assertEquals(location('usage_id').replace(run=None), student_module.module_state_key)
        self.assertEquals(course_id, student_module.course_id)
Example #9
0
    def test_set_field_in_missing_student_module(self):
        "Test that setting a field in a missing StudentModule creates the student module"
        self.assertEquals(0, len(self.field_data_cache.cache))
        self.assertEquals(0, StudentModule.objects.all().count())

        # We are updating a problem, so we write to courseware_studentmodulehistory
        # as well as courseware_studentmodule
        with self.assertNumQueries(6):
            self.kvs.set(user_state_key('a_field'), 'a_value')

        self.assertEquals(1, len(self.field_data_cache.cache))
        self.assertEquals(1, StudentModule.objects.all().count())

        student_module = StudentModule.objects.all()[0]
        self.assertEquals({'a_field': 'a_value'},
                          json.loads(student_module.state))
        self.assertEquals(self.user, student_module.student)
        self.assertEquals(
            location('usage_id').replace(run=None),
            student_module.module_state_key)
        self.assertEquals(course_id, student_module.course_id)
    def test_set_field_in_missing_student_module(self):
        "Test that setting a field in a missing StudentModule creates the student module"
        self.assertEquals(0, len(self.field_data_cache))
        self.assertEquals(0, StudentModule.objects.all().count())

        # We are updating a problem, so we write to courseware_studentmodulehistory
        # as well as courseware_studentmodule. We also need to read the database
        # to discover if something other than the DjangoXBlockUserStateClient
        # has written to the StudentModule (such as UserStateCache setting the score
        # on the StudentModule).
        with self.assertNumQueries(3):
            self.kvs.set(user_state_key('a_field'), 'a_value')

        self.assertEquals(1, sum(len(cache) for cache in self.field_data_cache.cache.values()))
        self.assertEquals(1, StudentModule.objects.all().count())

        student_module = StudentModule.objects.all()[0]
        self.assertEquals({'a_field': 'a_value'}, json.loads(student_module.state))
        self.assertEquals(self.user, student_module.student)
        self.assertEquals(location('usage_id').replace(run=None), student_module.module_state_key)
        self.assertEquals(course_id, student_module.course_id)
Example #11
0
 def setUp(self):
     super(TestStudentModuleHistoryBackends, self).setUp()
     for record in (1, 2, 3):
         # This will store into CSMHE via the post_save signal
         csm = StudentModuleFactory.create(
             module_state_key=location('usage_id'),
             course_id=course_id,
             state=json.dumps({
                 'type': 'csmhe',
                 'order': record
             }))
         # This manually gets us a CSMH record to compare
         csmh = StudentModuleHistory(student_module=csm,
                                     version=None,
                                     created=csm.modified,
                                     state=json.dumps({
                                         'type': 'csmh',
                                         'order': record
                                     }),
                                     grade=csm.grade,
                                     max_grade=csm.max_grade)
         csmh.save()
Example #12
0
    def test_set_field_in_missing_student_module(self):
        "Test that setting a field in a missing StudentModule creates the student module"
        self.assertEquals(0, len(self.field_data_cache))
        self.assertEquals(0, StudentModule.objects.all().count())

        # We are updating a problem, so we write to courseware_studentmodulehistoryextended
        # as well as courseware_studentmodule. We also need to read the database
        # to discover if something other than the DjangoXBlockUserStateClient
        # has written to the StudentModule (such as UserStateCache setting the score
        # on the StudentModule).
        # Django 1.8 also has a number of other BEGIN and SAVESTATE queries.
        with self.assertNumQueries(4, using="default"):
            with self.assertNumQueries(1, using="student_module_history"):
                self.kvs.set(user_state_key("a_field"), "a_value")

        self.assertEquals(1, sum(len(cache) for cache in self.field_data_cache.cache.values()))
        self.assertEquals(1, StudentModule.objects.all().count())

        student_module = StudentModule.objects.all()[0]
        self.assertEquals({"a_field": "a_value"}, json.loads(student_module.state))
        self.assertEquals(self.user, student_module.student)
        self.assertEquals(location("usage_id").replace(run=None), student_module.module_state_key)
        self.assertEquals(course_id, student_module.course_id)
Example #13
0
class StudentModuleFactory(cmfStudentModuleFactory):
    module_state_key = location('usage_id')
    course_id = course_id
    field.name = name
    return field


def mock_descriptor(fields=[]):
    descriptor = Mock()
    descriptor.scope_ids = ScopeIds('user1', 'mock_problem', location('def_id'), location('usage_id'))
    descriptor.module_class.fields.values.return_value = fields
    descriptor.fields.values.return_value = fields
    descriptor.module_class.__name__ = 'MockProblemModule'
    return descriptor

# The user ids here are 1 because we make a student in the setUp functions, and
# they get an id of 1.  There's an assertion in setUp to ensure that assumption
# is still true.
user_state_summary_key = partial(DjangoKeyValueStore.Key, Scope.user_state_summary, None, location('usage_id'))
settings_key = partial(DjangoKeyValueStore.Key, Scope.settings, None, location('usage_id'))
user_state_key = partial(DjangoKeyValueStore.Key, Scope.user_state, 1, location('usage_id'))
prefs_key = partial(DjangoKeyValueStore.Key, Scope.preferences, 1, 'mock_problem')
user_info_key = partial(DjangoKeyValueStore.Key, Scope.user_info, 1, None)


class StudentModuleFactory(cmfStudentModuleFactory):
    module_state_key = location('usage_id')
    course_id = course_id


class TestInvalidScopes(TestCase):
    def setUp(self):
        self.user = UserFactory.create(username='******')
        self.field_data_cache = FieldDataCache([mock_descriptor([mock_field(Scope.user_state, 'a_field')])], course_id, self.user)
Example #15
0
class TestStudentModuleStorage(OtherUserFailureTestMixin, TestCase):
    """Tests for user_state storage via StudentModule"""
    other_key_factory = partial(DjangoKeyValueStore.Key, Scope.user_state, 2,
                                location('usage_id'))  # user_id=2, not 1
    existing_field_name = "a_field"
    # Tell Django to clean out all databases, not just default
    multi_db = True

    def setUp(self):
        super(TestStudentModuleStorage, self).setUp()
        student_module = StudentModuleFactory(
            state=json.dumps({
                'a_field': 'a_value',
                'b_field': 'b_value'
            }))
        self.user = student_module.student
        self.assertEqual(
            self.user.id,
            1)  # check our assumption hard-coded in the key functions above.

        # There should be only one query to load a single descriptor with a single user_state field
        with self.assertNumQueries(1):
            self.field_data_cache = FieldDataCache(
                [mock_descriptor([mock_field(Scope.user_state, 'a_field')])],
                course_id, self.user)

        self.kvs = DjangoKeyValueStore(self.field_data_cache)

    def test_get_existing_field(self):
        "Test that getting an existing field in an existing StudentModule works"
        # This should only read from the cache, not the database
        with self.assertNumQueries(0):
            self.assertEquals('a_value',
                              self.kvs.get(user_state_key('a_field')))

    def test_get_missing_field(self):
        "Test that getting a missing field from an existing StudentModule raises a KeyError"
        # This should only read from the cache, not the database
        with self.assertNumQueries(0):
            self.assertRaises(KeyError, self.kvs.get,
                              user_state_key('not_a_field'))

    def test_set_existing_field(self):
        "Test that setting an existing user_state field changes the value"
        # We are updating a problem, so we write to courseware_studentmodulehistory
        # as well as courseware_studentmodule. We also need to read the database
        # to discover if something other than the DjangoXBlockUserStateClient
        # has written to the StudentModule (such as UserStateCache setting the score
        # on the StudentModule).
        with self.assertNumQueries(4, using='default'):
            with self.assertNumQueries(1, using='student_module_history'):
                self.kvs.set(user_state_key('a_field'), 'new_value')
        self.assertEquals(1, StudentModule.objects.all().count())
        self.assertEquals({
            'b_field': 'b_value',
            'a_field': 'new_value'
        }, json.loads(StudentModule.objects.all()[0].state))

    def test_set_missing_field(self):
        "Test that setting a new user_state field changes the value"
        # We are updating a problem, so we write to courseware_studentmodulehistory
        # as well as courseware_studentmodule. We also need to read the database
        # to discover if something other than the DjangoXBlockUserStateClient
        # has written to the StudentModule (such as UserStateCache setting the score
        # on the StudentModule).
        with self.assertNumQueries(4, using='default'):
            with self.assertNumQueries(1, using='student_module_history'):
                self.kvs.set(user_state_key('not_a_field'), 'new_value')
        self.assertEquals(1, StudentModule.objects.all().count())
        self.assertEquals(
            {
                'b_field': 'b_value',
                'a_field': 'a_value',
                'not_a_field': 'new_value'
            }, json.loads(StudentModule.objects.all()[0].state))

    def test_delete_existing_field(self):
        "Test that deleting an existing field removes it from the StudentModule"
        # We are updating a problem, so we write to courseware_studentmodulehistory
        # as well as courseware_studentmodule. We also need to read the database
        # to discover if something other than the DjangoXBlockUserStateClient
        # has written to the StudentModule (such as UserStateCache setting the score
        # on the StudentModule).
        with self.assertNumQueries(2, using='default'):
            with self.assertNumQueries(1, using='student_module_history'):
                self.kvs.delete(user_state_key('a_field'))
        self.assertEquals(1, StudentModule.objects.all().count())
        self.assertRaises(KeyError, self.kvs.get,
                          user_state_key('not_a_field'))

    def test_delete_missing_field(self):
        "Test that deleting a missing field from an existing StudentModule raises a KeyError"
        with self.assertNumQueries(0):
            self.assertRaises(KeyError, self.kvs.delete,
                              user_state_key('not_a_field'))
        self.assertEquals(1, StudentModule.objects.all().count())
        self.assertEquals({
            'b_field': 'b_value',
            'a_field': 'a_value'
        }, json.loads(StudentModule.objects.all()[0].state))

    def test_has_existing_field(self):
        "Test that `has` returns True for existing fields in StudentModules"
        with self.assertNumQueries(0):
            self.assertTrue(self.kvs.has(user_state_key('a_field')))

    def test_has_missing_field(self):
        "Test that `has` returns False for missing fields in StudentModule"
        with self.assertNumQueries(0):
            self.assertFalse(self.kvs.has(user_state_key('not_a_field')))

    def construct_kv_dict(self):
        """Construct a kv_dict that can be passed to set_many"""
        key1 = user_state_key('field_a')
        key2 = user_state_key('field_b')
        new_value = 'new value'
        newer_value = 'newer value'
        return {key1: new_value, key2: newer_value}

    def test_set_many(self):
        "Test setting many fields that are scoped to Scope.user_state"
        kv_dict = self.construct_kv_dict()

        # Scope.user_state is stored in a single row in the database, so we only
        # need to send a single update to that table.
        # We also are updating a problem, so we write to courseware student module history
        # We also need to read the database to discover if something other than the
        # DjangoXBlockUserStateClient has written to the StudentModule (such as
        # UserStateCache setting the score on the StudentModule).
        with self.assertNumQueries(4, using="default"):
            with self.assertNumQueries(1, using="student_module_history"):
                self.kvs.set_many(kv_dict)

        for key in kv_dict:
            self.assertEquals(self.kvs.get(key), kv_dict[key])

    def test_set_many_failure(self):
        "Test failures when setting many fields that are scoped to Scope.user_state"
        kv_dict = self.construct_kv_dict()
        # because we're patching the underlying save, we need to ensure the
        # fields are in the cache
        for key in kv_dict:
            self.kvs.set(key, 'test_value')

        with patch('django.db.models.Model.save', side_effect=DatabaseError):
            with self.assertRaises(
                    KeyValueMultiSaveError) as exception_context:
                self.kvs.set_many(kv_dict)
        self.assertEquals(exception_context.exception.saved_field_names, [])
Example #16
0
def mock_descriptor(fields=[]):
    descriptor = Mock(entry_point=XBlock.entry_point)
    descriptor.scope_ids = ScopeIds('user1', 'mock_problem',
                                    location('def_id'), location('usage_id'))
    descriptor.module_class.fields.values.return_value = fields
    descriptor.fields.values.return_value = fields
    descriptor.module_class.__name__ = 'MockProblemModule'
    return descriptor


# The user ids here are 1 because we make a student in the setUp functions, and
# they get an id of 1.  There's an assertion in setUp to ensure that assumption
# is still true.
user_state_summary_key = partial(DjangoKeyValueStore.Key,
                                 Scope.user_state_summary, None,
                                 location('usage_id'))
settings_key = partial(DjangoKeyValueStore.Key, Scope.settings, None,
                       location('usage_id'))
user_state_key = partial(DjangoKeyValueStore.Key, Scope.user_state, 1,
                         location('usage_id'))
prefs_key = partial(DjangoKeyValueStore.Key, Scope.preferences, 1,
                    'mock_problem')
user_info_key = partial(DjangoKeyValueStore.Key, Scope.user_info, 1, None)


class StudentModuleFactory(cmfStudentModuleFactory):
    module_state_key = location('usage_id')
    course_id = course_id


class TestInvalidScopes(TestCase):
class TestStudentModuleStorage(OtherUserFailureTestMixin, TestCase):
    """Tests for user_state storage via StudentModule"""
    other_key_factory = partial(DjangoKeyValueStore.Key, Scope.user_state, 2, location('usage_id'))  # user_id=2, not 1
    existing_field_name = "a_field"

    def setUp(self):
        student_module = StudentModuleFactory(state=json.dumps({'a_field': 'a_value', 'b_field': 'b_value'}))
        self.user = student_module.student
        self.assertEqual(self.user.id, 1)   # check our assumption hard-coded in the key functions above.
        self.field_data_cache = FieldDataCache([mock_descriptor([mock_field(Scope.user_state, 'a_field')])], course_id, self.user)
        self.kvs = DjangoKeyValueStore(self.field_data_cache)

    def test_get_existing_field(self):
        "Test that getting an existing field in an existing StudentModule works"
        self.assertEquals('a_value', self.kvs.get(user_state_key('a_field')))

    def test_get_missing_field(self):
        "Test that getting a missing field from an existing StudentModule raises a KeyError"
        self.assertRaises(KeyError, self.kvs.get, user_state_key('not_a_field'))

    def test_set_existing_field(self):
        "Test that setting an existing user_state field changes the value"
        self.kvs.set(user_state_key('a_field'), 'new_value')
        self.assertEquals(1, StudentModule.objects.all().count())
        self.assertEquals({'b_field': 'b_value', 'a_field': 'new_value'}, json.loads(StudentModule.objects.all()[0].state))

    def test_set_missing_field(self):
        "Test that setting a new user_state field changes the value"
        self.kvs.set(user_state_key('not_a_field'), 'new_value')
        self.assertEquals(1, StudentModule.objects.all().count())
        self.assertEquals({'b_field': 'b_value', 'a_field': 'a_value', 'not_a_field': 'new_value'}, json.loads(StudentModule.objects.all()[0].state))

    def test_delete_existing_field(self):
        "Test that deleting an existing field removes it from the StudentModule"
        self.kvs.delete(user_state_key('a_field'))
        self.assertEquals(1, StudentModule.objects.all().count())
        self.assertRaises(KeyError, self.kvs.get, user_state_key('not_a_field'))

    def test_delete_missing_field(self):
        "Test that deleting a missing field from an existing StudentModule raises a KeyError"
        self.assertRaises(KeyError, self.kvs.delete, user_state_key('not_a_field'))
        self.assertEquals(1, StudentModule.objects.all().count())
        self.assertEquals({'b_field': 'b_value', 'a_field': 'a_value'}, json.loads(StudentModule.objects.all()[0].state))

    def test_has_existing_field(self):
        "Test that `has` returns True for existing fields in StudentModules"
        self.assertTrue(self.kvs.has(user_state_key('a_field')))

    def test_has_missing_field(self):
        "Test that `has` returns False for missing fields in StudentModule"
        self.assertFalse(self.kvs.has(user_state_key('not_a_field')))

    def construct_kv_dict(self):
        """Construct a kv_dict that can be passed to set_many"""
        key1 = user_state_key('field_a')
        key2 = user_state_key('field_b')
        new_value = 'new value'
        newer_value = 'newer value'
        return {key1: new_value, key2: newer_value}

    def test_set_many(self):
        "Test setting many fields that are scoped to Scope.user_state"
        kv_dict = self.construct_kv_dict()
        self.kvs.set_many(kv_dict)

        for key in kv_dict:
            self.assertEquals(self.kvs.get(key), kv_dict[key])

    def test_set_many_failure(self):
        "Test failures when setting many fields that are scoped to Scope.user_state"
        kv_dict = self.construct_kv_dict()
        # because we're patching the underlying save, we need to ensure the
        # fields are in the cache
        for key in kv_dict:
            self.kvs.set(key, 'test_value')

        with patch('django.db.models.Model.save', side_effect=DatabaseError):
            with self.assertRaises(KeyValueMultiSaveError) as exception_context:
                self.kvs.set_many(kv_dict)
        self.assertEquals(len(exception_context.exception.saved_field_names), 0)
    field.name = name
    return field


def mock_descriptor(fields=[]):
    descriptor = Mock(entry_point=XBlock.entry_point)
    descriptor.scope_ids = ScopeIds('user1', 'mock_problem', location('def_id'), location('usage_id'))
    descriptor.module_class.fields.values.return_value = fields
    descriptor.fields.values.return_value = fields
    descriptor.module_class.__name__ = 'MockProblemModule'
    return descriptor

# The user ids here are 1 because we make a student in the setUp functions, and
# they get an id of 1.  There's an assertion in setUp to ensure that assumption
# is still true.
user_state_summary_key = partial(DjangoKeyValueStore.Key, Scope.user_state_summary, None, location('usage_id'))
settings_key = partial(DjangoKeyValueStore.Key, Scope.settings, None, location('usage_id'))
user_state_key = partial(DjangoKeyValueStore.Key, Scope.user_state, 1, location('usage_id'))
prefs_key = partial(DjangoKeyValueStore.Key, Scope.preferences, 1, 'mock_problem')
user_info_key = partial(DjangoKeyValueStore.Key, Scope.user_info, 1, None)


class StudentModuleFactory(cmfStudentModuleFactory):
    module_state_key = location('usage_id')
    course_id = course_id


@attr('shard_1')
class TestInvalidScopes(TestCase):
    def setUp(self):
        super(TestInvalidScopes, self).setUp()