Example #1
0
def test_twofaced_field_access():
    # Check that a field with different to_json and from_json representations
    # persists and saves correctly.
    class TwoFacedField(Field):
        """A field that emits different 'json' than it parses."""
        def from_json(self, thestr):
            """Store an int, the length of the string parsed."""
            return len(thestr)

        def to_json(self, value):
            """Emit some number of X's."""
            return "X" * value

    class FieldTester(XBlock):
        """Test block for TwoFacedField."""
        how_many = TwoFacedField(scope=Scope.settings)

    original_json = "YYY"
    runtime = TestRuntime(
        services={'field-data': DictFieldData({'how_many': original_json})})
    field_tester = FieldTester(runtime, scope_ids=Mock(spec=ScopeIds))

    # Test that the native value isn't equal to the original json we specified.
    assert_not_equals(field_tester.how_many, original_json)
    # Test that the native -> json value isn't equal to the original json we specified.
    assert_not_equals(TwoFacedField().to_json(field_tester.how_many),
                      original_json)

    # The previous accesses will mark the field as dirty (via __get__)
    assert_equals(len(field_tester._dirty_fields), 1)
    # However, the field should not ACTUALLY be marked as a field that is needing to be saved.
    assert_not_in('how_many', field_tester._get_fields_to_save())  # pylint: disable=W0212
Example #2
0
def test_cached_parent():
    class HasParent(XBlock):
        pass

    runtime = Mock()
    block = HasParent(runtime, DictFieldData({}), Mock())

    # block has no parent yet, and we don't need to call the runtime to find
    # that out.
    assert_equals(block.get_parent(), None)
    assert not runtime.get_block.called

    # Set a parent id for the block.  Get the parent.  Now we have one, and we
    # used runtime.get_block to get it.
    block.parent = "some_parent_id"
    parent = block.get_parent()
    assert_not_equals(parent, None)
    assert runtime.get_block.called_with("some_parent_id")

    # Get the parent again.  It will be the same parent, and we didn't call the
    # runtime.
    runtime.reset_mock()
    parent2 = block.get_parent()
    assert parent2 is parent
    assert not runtime.get_block.called
Example #3
0
def test_cached_parent():
    class HasParent(XBlock):
        """
        Dummy empty class
        """
        pass

    runtime = TestRuntime(services={'field-data': DictFieldData({})})
    runtime.get_block = Mock()
    block = HasParent(runtime, scope_ids=Mock(spec=ScopeIds))

    # block has no parent yet, and we don't need to call the runtime to find
    # that out.
    assert_equals(block.get_parent(), None)
    assert not runtime.get_block.called

    # Set a parent id for the block.  Get the parent.  Now we have one, and we
    # used runtime.get_block to get it.
    block.parent = "some_parent_id"
    parent = block.get_parent()
    assert_not_equals(parent, None)
    assert runtime.get_block.called_with("some_parent_id")

    # Get the parent again.  It will be the same parent, and we didn't call the
    # runtime.
    runtime.get_block.reset_mock()
    parent2 = block.get_parent()
    assert parent2 is parent
    assert not runtime.get_block.called
Example #4
0
def test_caching_is_per_instance():
    # Test that values cached for one instance do not appear on another
    class FieldTester(object):
        """Toy class for ModelMetaclass and field access testing"""
        __metaclass__ = ModelMetaclass

        field_a = List(scope=Scope.settings)

        def __init__(self, field_data):
            self._field_data = field_data
            self._dirty_fields = {}

    field_data = MagicMock(spec=FieldData)
    field_data.get = lambda block, name, default=None: [name]  # pylint: disable=C0322

    # Same field_data used in different objects should result
    # in separately-cached values, so that changing a value
    # in one instance doesn't affect values stored in others.
    field_tester_a = FieldTester(field_data)
    field_tester_b = FieldTester(field_data)
    value = field_tester_a.field_a
    assert_equals(value, field_tester_a.field_a)
    field_tester_a.field_a.append(1)
    assert_equals(value, field_tester_a.field_a)
    assert_not_equals(value, field_tester_b.field_a)
Example #5
0
def test_caching_is_per_instance():
    # Test that values cached for one instance do not appear on another
    class FieldTester(object):
        """Toy class for ModelMetaclass and field access testing"""
        __metaclass__ = ModelMetaclass

        field_a = List(scope=Scope.settings)

        def __init__(self, field_data):
            self._field_data = field_data
            self._dirty_fields = {}

    field_data = MagicMock(spec=FieldData)
    field_data.get = lambda block, name, default=None: [name]  # pylint: disable=C0322

    # Same field_data used in different objects should result
    # in separately-cached values, so that changing a value
    # in one instance doesn't affect values stored in others.
    field_tester_a = FieldTester(field_data)
    field_tester_b = FieldTester(field_data)
    value = field_tester_a.field_a
    assert_equals(value, field_tester_a.field_a)
    field_tester_a.field_a.append(1)
    assert_equals(value, field_tester_a.field_a)
    assert_not_equals(value, field_tester_b.field_a)
Example #6
0
def test_caching_is_per_instance():
    # Test that values cached for one instance do not appear on another
    class FieldTester(ScopedStorageMixin):
        """Toy class for ModelMetaclass and field access testing"""
        field_a = List(scope=Scope.settings)

    field_data = MagicMock(spec=FieldData)
    field_data.get = lambda block, name, default=None: [name]  # pylint: disable=C0322

    # Same field_data used in different objects should result
    # in separately-cached values, so that changing a value
    # in one instance doesn't affect values stored in others.
    field_tester_a = FieldTester(
        runtime=TestRuntime(services={'field-data': field_data}),
        scope_ids=MagicMock(spec=ScopeIds)
    )
    field_tester_b = FieldTester(
        runtime=TestRuntime(services={'field-data': field_data}),
        scope_ids=MagicMock(spec=ScopeIds)
    )
    value = field_tester_a.field_a
    assert_equals(value, field_tester_a.field_a)
    field_tester_a.field_a.append(1)
    assert_equals(value, field_tester_a.field_a)
    assert_not_equals(value, field_tester_b.field_a)
Example #7
0
def test_twofaced_field_access():
    # Check that a field with different to_json and from_json representations
    # persists and saves correctly.
    class TwoFacedField(Field):
        """A field that emits different 'json' than it parses."""
        def from_json(self, thestr):
            """Store an int, the length of the string parsed."""
            return len(thestr)

        def to_json(self, value):
            """Emit some number of X's."""
            return "X" * value

    class FieldTester(XBlock):
        """Test block for TwoFacedField."""
        how_many = TwoFacedField(scope=Scope.settings)

    original_json = "YYY"
    runtime = TestRuntime(services={'field-data': DictFieldData({'how_many': original_json})})
    field_tester = FieldTester(runtime, scope_ids=Mock(spec=ScopeIds))

    # Test that the native value isn't equal to the original json we specified.
    assert_not_equals(field_tester.how_many, original_json)
    # Test that the native -> json value isn't equal to the original json we specified.
    assert_not_equals(TwoFacedField().to_json(field_tester.how_many), original_json)

    # The previous accesses will mark the field as dirty (via __get__)
    assert_equals(len(field_tester._dirty_fields), 1)
    # However, the field should not ACTUALLY be marked as a field that is needing to be saved.
    assert_not_in('how_many', field_tester._get_fields_to_save())   # pylint: disable=W0212
Example #8
0
def test_cached_parent():
    class HasParent(XBlock):
        """
        Dummy empty class
        """
        pass

    runtime = TestRuntime(services={'field-data': DictFieldData({})})
    runtime.get_block = Mock()
    block = HasParent(runtime, scope_ids=Mock(spec=ScopeIds))

    # block has no parent yet, and we don't need to call the runtime to find
    # that out.
    assert_equals(block.get_parent(), None)
    assert not runtime.get_block.called

    # Set a parent id for the block.  Get the parent.  Now we have one, and we
    # used runtime.get_block to get it.
    block.parent = "some_parent_id"
    parent = block.get_parent()
    assert_not_equals(parent, None)
    assert runtime.get_block.called_with("some_parent_id")

    # Get the parent again.  It will be the same parent, and we didn't call the
    # runtime.
    runtime.get_block.reset_mock()
    parent2 = block.get_parent()
    assert parent2 is parent
    assert not runtime.get_block.called
Example #9
0
def test_cached_parent():
    class HasParent(XBlock):
        pass

    runtime = Mock()
    block = HasParent(runtime, DictFieldData({}), Mock())

    # block has no parent yet, and we don't need to call the runtime to find
    # that out.
    assert_equals(block.get_parent(), None)
    assert not runtime.get_block.called

    # Set a parent id for the block.  Get the parent.  Now we have one, and we
    # used runtime.get_block to get it.
    block.parent = "some_parent_id"
    parent = block.get_parent()
    assert_not_equals(parent, None)
    assert runtime.get_block.called_with("some_parent_id")

    # Get the parent again.  It will be the same parent, and we didn't call the
    # runtime.
    runtime.reset_mock()
    parent2 = block.get_parent()
    assert parent2 is parent
    assert not runtime.get_block.called
Example #10
0
    def test_mutation_without_save_doesnt_write(self):
        initial_value = self.field_data.get(self.block, 'field')
        reference_copy = copy.deepcopy(initial_value)

        mutable = self.get()
        self.mutate(mutable)

        # Verify that the test isn't vacuously true
        assert_not_equals(reference_copy, mutable)

        final_value = self.field_data.get(self.block, 'field')
        assert_equals(reference_copy, final_value)
        assert_equals(initial_value, final_value)
Example #11
0
    def test_set_save_get_mutate_save(self):
        reference_value = copy.deepcopy(self.new_value)
        self.mutate(reference_value)

        # Verify that the test isn't vacuously true
        assert_not_equals(self.new_value, reference_value)

        self.set(copy.deepcopy(self.new_value))
        self.block.save()
        self.mutate(self.get())
        self.block.save()
        final_value = self.field_data.get(self.block, 'field')
        assert_equals(reference_value, final_value)
Example #12
0
    def test_mutation_without_save_doesnt_write(self):
        initial_value = self.field_data.get(self.block, 'field')
        reference_copy = copy.deepcopy(initial_value)

        mutable = self.get()
        self.mutate(mutable)

        # Verify that the test isn't vacuously true
        assert_not_equals(reference_copy, mutable)

        final_value = self.field_data.get(self.block, 'field')
        assert_equals(reference_copy, final_value)
        assert_equals(initial_value, final_value)
Example #13
0
    def test_set_save_get_mutate_save(self):
        reference_value = copy.deepcopy(self.new_value)
        self.mutate(reference_value)

        # Verify that the test isn't vacuously true
        assert_not_equals(self.new_value, reference_value)

        self.set(copy.deepcopy(self.new_value))
        self.block.save()
        self.mutate(self.get())
        self.block.save()
        final_value = self.field_data.get(self.block, 'field')
        assert_equals(reference_value, final_value)
Example #14
0
    def test_mutation_with_save_writes(self):
        assert_false(self.field_data.has(self.block, 'field'))

        mutable = self.get()
        reference_copy = copy.deepcopy(mutable)
        self.mutate(reference_copy)

        # Verify that the test isn't vacuously true
        assert_not_equals(mutable, reference_copy)

        self.mutate(mutable)
        self.block.save()

        final_value = self.field_data.get(self.block, 'field')
        assert_equals(reference_copy, final_value)
Example #15
0
    def test_mutation_with_save_writes(self):
        assert_false(self.field_data.has(self.block, 'field'))

        mutable = self.get()
        reference_copy = copy.deepcopy(mutable)
        self.mutate(reference_copy)

        # Verify that the test isn't vacuously true
        assert_not_equals(mutable, reference_copy)

        self.mutate(mutable)
        self.block.save()

        final_value = self.field_data.get(self.block, 'field')
        assert_equals(reference_copy, final_value)
Example #16
0
def test_twofaced_field_access():
    # Check that a field with different to_json and from_json representations
    # persists and saves correctly.
    class FieldTester(XBlock):
        """Test block for TwoFacedField."""
        how_many = TwoFacedField(scope=Scope.settings)

    original_json = "YYY"
    field_tester = FieldTester(MagicMock(), DictFieldData({'how_many': original_json}), Mock())

    # Test that the native value isn't equal to the original json we specified.
    assert_not_equals(field_tester.how_many, original_json)
    # Test that the native -> json value isn't equal to the original json we specified.
    assert_not_equals(TwoFacedField().to_json(field_tester.how_many), original_json)

    # The previous accesses will mark the field as dirty (via __get__)
    assert_equals(len(field_tester._dirty_fields), 1)
    # However, the field should not ACTUALLY be marked as a field that is needing to be saved.
    assert_not_in('how_many', field_tester._get_fields_to_save())   # pylint: disable=W0212
Example #17
0
def test_unique_id_default():
    class TestBlock(XBlock):
        """
        Block for testing
        """
        field_a = String(default=UNIQUE_ID, scope=Scope.settings)
        field_b = String(default=UNIQUE_ID, scope=Scope.user_state)

    sids = ScopeIds(user_id="bob",
                    block_type="bobs-type",
                    def_id="definition-id",
                    usage_id="usage-id")

    runtime = TestRuntime(services={'field-data': DictFieldData({})})
    block = TestBlock(runtime, DictFieldData({}), sids)
    unique_a = block.field_a
    unique_b = block.field_b
    # Create another instance of the same block. Unique ID defaults should not change.
    runtime = TestRuntime(services={'field-data': DictFieldData({})})
    block = TestBlock(runtime, DictFieldData({}), sids)
    assert_equals(unique_a, block.field_a)
    assert_equals(unique_b, block.field_b)
    # Change the user id. Unique ID default should change for field_b with
    # user_state scope, but not for field_a with scope=settings.
    runtime = TestRuntime(services={'field-data': DictFieldData({})})
    block = TestBlock(runtime, DictFieldData({}), sids._replace(user_id='alice'))
    assert_equals(unique_a, block.field_a)
    assert_not_equals(unique_b, block.field_b)
    # Change the usage id. Unique ID default for both fields should change.
    runtime = TestRuntime(services={'field-data': DictFieldData({})})
    block = TestBlock(runtime, DictFieldData({}), sids._replace(usage_id='usage-2'))
    assert_not_equals(unique_a, block.field_a)
    assert_not_equals(unique_b, block.field_b)
Example #18
0
def test_unique_id_default():
    class TestBlock(XBlock):
        """
        Block for testing
        """
        field_a = String(default=UNIQUE_ID, scope=Scope.settings)
        field_b = String(default=UNIQUE_ID, scope=Scope.user_state)

    sids = ScopeIds(user_id="bob",
                    block_type="bobs-type",
                    def_id="definition-id",
                    usage_id="usage-id")

    runtime = TestRuntime(services={'field-data': DictFieldData({})})
    block = TestBlock(runtime, DictFieldData({}), sids)
    unique_a = block.field_a
    unique_b = block.field_b
    # Create another instance of the same block. Unique ID defaults should not change.
    runtime = TestRuntime(services={'field-data': DictFieldData({})})
    block = TestBlock(runtime, DictFieldData({}), sids)
    assert_equals(unique_a, block.field_a)
    assert_equals(unique_b, block.field_b)
    # Change the user id. Unique ID default should change for field_b with
    # user_state scope, but not for field_a with scope=settings.
    runtime = TestRuntime(services={'field-data': DictFieldData({})})
    block = TestBlock(runtime, DictFieldData({}),
                      sids._replace(user_id='alice'))
    assert_equals(unique_a, block.field_a)
    assert_not_equals(unique_b, block.field_b)
    # Change the usage id. Unique ID default for both fields should change.
    runtime = TestRuntime(services={'field-data': DictFieldData({})})
    block = TestBlock(runtime, DictFieldData({}),
                      sids._replace(usage_id='usage-2'))
    assert_not_equals(unique_a, block.field_a)
    assert_not_equals(unique_b, block.field_b)
Example #19
0
def test_caching_is_per_instance():
    # Test that values cached for one instance do not appear on another
    class FieldTester(ScopedStorageMixin):
        """Toy class for ModelMetaclass and field access testing"""
        field_a = List(scope=Scope.settings)

    field_data = MagicMock(spec=FieldData)
    field_data.get = lambda block, name, default=None: [name]  # pylint: disable=C0322

    # Same field_data used in different objects should result
    # in separately-cached values, so that changing a value
    # in one instance doesn't affect values stored in others.
    field_tester_a = FieldTester(
        runtime=TestRuntime(services={'field-data': field_data}),
        scope_ids=MagicMock(spec=ScopeIds))
    field_tester_b = FieldTester(
        runtime=TestRuntime(services={'field-data': field_data}),
        scope_ids=MagicMock(spec=ScopeIds))
    value = field_tester_a.field_a
    assert_equals(value, field_tester_a.field_a)
    field_tester_a.field_a.append(1)
    assert_equals(value, field_tester_a.field_a)
    assert_not_equals(value, field_tester_b.field_a)