示例#1
0
    def test_put_without_update_timestamps(self) -> None:
        model = base_models.BaseModel()
        self.assertIsNone(model.created_on)
        self.assertIsNone(model.last_updated)

        # First `put` does not raise an Exception because it sets last_updated
        # automatically since it is None.
        model.put()

        # Immediately calling `put` again fails, because update_timestamps needs
        # to be called first.
        with self.assertRaisesRegex( # type: ignore[no-untyped-call]
            Exception, re.escape('did not call update_timestamps()')
        ):
            model.put()

        model = base_models.BaseModel.get_by_id(model.id)

        # Getting a fresh model requires update_timestamps too.
        with self.assertRaisesRegex( # type: ignore[no-untyped-call]
            Exception, re.escape('did not call update_timestamps()')
        ):
            model.put()

        model.update_timestamps()
        # OK, update_timestamps called before put.
        model.put()
示例#2
0
    def test_generic_query_put_get_and_delete_operations(self) -> None:
        model = base_models.BaseModel()

        all_models = base_models.BaseModel.get_all()
        self.assertEqual(all_models.count(), 0)

        model.update_timestamps()
        model.put()
        all_models = base_models.BaseModel.get_all()
        self.assertEqual(all_models.count(), 1)
        base_model = all_models.get()

        # Ruling out the possibility of None for mypy type checking.
        assert base_model is not None
        self.assertEqual(base_model, model)

        model_id = base_model.id
        self.assertEqual(model, base_models.BaseModel.get(model_id))

        model.delete()
        all_models = base_models.BaseModel.get_all()
        self.assertEqual(all_models.count(), 0)
        self.assertEqual(model_id, 4)
        with self.assertRaisesRegex(
            base_models.BaseModel.EntityNotFoundError,
            'Entity for class BaseModel with id 4 not found'
        ):
            model.get(model_id)
示例#3
0
    def test_put(self) -> None:
        model = base_models.BaseModel()
        self.assertIsNone(model.created_on)
        self.assertIsNone(model.last_updated)

        # Field last_updated will get updated anyway because it is None.
        model.update_timestamps(update_last_updated_time=False)
        model.put()
        model_id = model.id
        self.assertIsNotNone(
            base_models.BaseModel.get_by_id(model_id).created_on)
        self.assertIsNotNone(
            base_models.BaseModel.get_by_id(model_id).last_updated)
        last_updated = model.last_updated

        # Field last_updated won't get updated because update_last_updated_time
        # is set to False and last_updated already has some value.
        model.update_timestamps(update_last_updated_time=False)
        model.put()
        self.assertEqual(
            base_models.BaseModel.get_by_id(model_id).last_updated,
            last_updated)

        # Field last_updated will get updated because update_last_updated_time
        # is set to True (by default).
        model.update_timestamps()
        model.put()
        self.assertNotEqual(
            base_models.BaseModel.get_by_id(model_id).last_updated,
            last_updated)
示例#4
0
    def test_generic_query_put_get_and_delete_operations(self):
        # type: () -> None
        model = base_models.BaseModel()

        all_models = base_models.BaseModel.get_all()
        self.assertEqual(all_models.count(), 0)

        model.update_timestamps()
        model.put()
        all_models = base_models.BaseModel.get_all()
        self.assertEqual(all_models.count(), 1)
        base_model = cast(base_models.BaseModel, all_models.get())
        self.assertEqual(base_model, model)

        model_id = base_model.id
        self.assertEqual(model, base_models.BaseModel.get(model_id))

        model.delete()
        all_models = base_models.BaseModel.get_all()
        self.assertEqual(all_models.count(), 0)
        with self.assertRaisesRegexp( # type: ignore[no-untyped-call]
            base_models.BaseModel.EntityNotFoundError,
            'Entity for class BaseModel with id 4 not found'
        ):
            model.get(model_id)
示例#5
0
    def test_get_new_id_method_returns_unique_ids(self) -> None:
        ids: Set[str] = set([])
        for _ in range(100):
            new_id = base_models.BaseModel.get_new_id('')
            self.assertNotIn(new_id, ids)

            base_models.BaseModel(id=new_id).put()
            ids.add(new_id)
示例#6
0
    def test_clone_model(self) -> None:
        model = base_models.BaseModel(id='123', deleted=True)
        clone = job_utils.clone_model(model)

        self.assertEqual(model.id, clone.id)
        self.assertEqual(model, clone)
        self.assertIsNot(model, clone)
        self.assertIsInstance(clone, base_models.BaseModel)
示例#7
0
    def test_clone_with_changes(self) -> None:
        model = base_models.BaseModel(id='123', deleted=True)
        clone = job_utils.clone_model(model, deleted=False)

        self.assertNotEqual(model, clone)
        self.assertIsNot(model, clone)
        self.assertIsInstance(clone, base_models.BaseModel)
        self.assertTrue(model.deleted)
        self.assertFalse(clone.deleted)
示例#8
0
    def test_clone_with_changes_to_id(self) -> None:
        model = base_models.BaseModel(id='123')
        clone = job_utils.clone_model(model, id='124')

        self.assertNotEqual(model, clone)
        self.assertIsNot(model, clone)
        self.assertIsInstance(clone, base_models.BaseModel)
        self.assertEqual(model.id, '123')
        self.assertEqual(clone.id, '124')
示例#9
0
    def test_get_new_id_method_returns_unique_ids(self):
        # type: () -> None
        ids = set([]) # type: Set[Text]
        for _ in python_utils.RANGE(100):
            new_id = base_models.BaseModel.get_new_id('')
            self.assertNotIn(new_id, ids)

            base_models.BaseModel(id=new_id).put()
            ids.add(new_id)
示例#10
0
    def test_message(self) -> None:
        model = base_models.BaseModel(id='?!"',
                                      created_on=self.YEAR_AGO,
                                      last_updated=self.NOW)
        error = base_validation_errors.ModelIdRegexError(model, '[abc]{3}')

        self.assertEqual(
            error.stderr,
            'ModelIdRegexError in BaseModel(id="?!\\""): id does not '
            'match the expected regex="[abc]{3}"')
示例#11
0
    def test_message(self) -> None:
        model = base_models.BaseModel(id='123',
                                      created_on=self.NOW,
                                      last_updated=self.YEAR_LATER)
        error = base_validation_errors.ModelMutatedDuringJobError(model)

        self.assertEqual(
            error.stderr, 'ModelMutatedDuringJobError in BaseModel(id="123"): '
            'last_updated=%r is later than the audit job\'s start time' %
            (model.last_updated))
示例#12
0
    def test_message(self) -> None:
        model = base_models.BaseModel(id='123',
                                      created_on=self.NOW,
                                      last_updated=self.YEAR_AGO)
        error = base_validation_errors.InconsistentTimestampsError(model)

        self.assertEqual(
            error.stderr,
            'InconsistentTimestampsError in BaseModel(id="123"): '
            'created_on=%r is later than last_updated=%r' %
            (self.NOW, self.YEAR_AGO))
示例#13
0
    def test_message(self) -> None:
        model = base_models.BaseModel(id='123',
                                      deleted=True,
                                      created_on=self.YEAR_AGO,
                                      last_updated=self.YEAR_AGO)
        error = base_validation_errors.ModelExpiredError(model)

        self.assertEqual(
            error.stderr,
            'ModelExpiredError in BaseModel(id="123"): deleted=True when '
            'older than %d days' %
            (feconf.PERIOD_TO_HARD_DELETE_MODELS_MARKED_AS_DELETED.days))
示例#14
0
    def test_delete_multi(self) -> None:
        model1 = base_models.BaseModel()
        model2 = base_models.BaseModel()
        model3 = base_models.BaseModel()
        model2.deleted = True

        model1.update_timestamps()
        model1.put()
        model2.update_timestamps()
        model2.put()
        model3.update_timestamps()
        model3.put()

        model1_id = model1.id
        model2_id = model2.id
        model3_id = model3.id

        base_models.BaseModel.delete_multi([model1, model2, model3])

        result = base_models.BaseModel.get_multi([
            model1_id, model2_id, model3_id])

        self.assertEqual(result, [None, None, None])
示例#15
0
    def test_model_domain_object_validate_error(self) -> None:
        model = base_models.BaseModel(id='123',
                                      deleted=True,
                                      created_on=self.YEAR_AGO,
                                      last_updated=self.YEAR_AGO)
        error_message = 'Invalid validation type for domain object: Invalid'

        error = base_validation_errors.ModelDomainObjectValidateError(
            model, error_message)

        msg = ('ModelDomainObjectValidateError in BaseModel(id="123"): Entity'
               ' fails domain validation with the error: %s' % error_message)

        self.assertEqual(error.stderr, msg)
示例#16
0
    def test_get_multi(self) -> None:
        model1 = base_models.BaseModel()
        model2 = base_models.BaseModel()
        model3 = base_models.BaseModel()
        model2.deleted = True

        model1.update_timestamps()
        model1.put()
        model2.update_timestamps()
        model2.put()
        model3.update_timestamps()
        model3.put()

        model1_id = model1.id
        model2_id = model2.id
        model3_id = model3.id

        # For all the None ids, get_multi should return None at the appropriate
        # position.
        result = base_models.BaseModel.get_multi(
            [model1_id, model2_id, None, model3_id, 'none', None])

        self.assertEqual(result, [model1, None, None, model3, None, None])
示例#17
0
    def test_validation_type_for_domain_object(self) -> None:
        model = base_models.BaseModel(
            id='mock-123',
            deleted=False,
            created_on=self.YEAR_AGO,
            last_updated=self.NOW)

        output = (
            self.pipeline
            | beam.Create([model])
            | beam.ParDo(
                base_validation.ValidateModelDomainObjectInstances())
        )

        self.assert_pcoll_equal(output, [])
示例#18
0
    def test_process_reports_model_mutated_during_job_error(self) -> None:
        invalid_timestamp = base_models.BaseModel(
            id='124',
            created_on=self.NOW,
            last_updated=self.YEAR_LATER)

        output = (
            self.pipeline
            | beam.Create([invalid_timestamp])
            | beam.ParDo(base_validation.ValidateModelTimestamps())
        )

        self.assert_pcoll_equal(output, [
            base_validation_errors.ModelMutatedDuringJobError(
                invalid_timestamp),
        ])
示例#19
0
    def test_process_reports_model_timestamp_relationship_error(self) -> None:
        invalid_timestamp = base_models.BaseModel(
            id='123',
            created_on=self.NOW,
            last_updated=self.YEAR_AGO)

        output = (
            self.pipeline
            | beam.Create([invalid_timestamp])
            | beam.ParDo(base_validation.ValidateModelTimestamps())
        )

        self.assert_pcoll_equal(output, [
            base_validation_errors.InconsistentTimestampsError(
                invalid_timestamp),
        ])
示例#20
0
    def test_process_reports_error_for_old_deleted_model(self) -> None:
        expired_model = base_models.BaseModel(
            id='123',
            deleted=True,
            created_on=self.YEAR_AGO,
            last_updated=self.YEAR_AGO)

        output = (
            self.pipeline
            | beam.Create([expired_model])
            | beam.ParDo(base_validation.ValidateDeletedModel())
        )

        self.assert_pcoll_equal(output, [
            base_validation_errors.ModelExpiredError(expired_model),
        ])
示例#21
0
    def test_validate_model_id(self) -> None:
        invalid_id_model = base_models.BaseModel(
            id='123@?!*',
            created_on=self.YEAR_AGO,
            last_updated=self.NOW)

        output = (
            self.pipeline
            | beam.Create([invalid_id_model])
            | beam.ParDo(base_validation.ValidateBaseModelId())
        )

        self.assert_pcoll_equal(output, [
            base_validation_errors.ModelIdRegexError(
                invalid_id_model,
                base_validation.BASE_MODEL_ID_PATTERN),
        ])
示例#22
0
    def test_put_multi(self):
        # type: () -> None
        models_1 = [base_models.BaseModel() for _ in python_utils.RANGE(3)]
        for model in models_1:
            self.assertIsNone(model.created_on)
            self.assertIsNone(model.last_updated)

        # Field last_updated will get updated anyway because it is None.
        base_models.BaseModel.update_timestamps_multi(
            models_1, update_last_updated_time=False)
        base_models.BaseModel.put_multi(models_1)
        model_ids = [model.id for model in models_1]
        last_updated_values = []
        for model_id in model_ids:
            model = base_models.BaseModel.get_by_id(model_id)
            self.assertIsNotNone(model.created_on)
            self.assertIsNotNone(model.last_updated)
            last_updated_values.append(model.last_updated)

        # Field last_updated won't get updated because update_last_updated_time
        # is set to False and last_updated already has some value.
        models_2_without_none = cast(
            List[base_models.BaseModel],
            base_models.BaseModel.get_multi(model_ids)
        )
        base_models.BaseModel.update_timestamps_multi(
            models_2_without_none, update_last_updated_time=False)
        base_models.BaseModel.put_multi(models_2_without_none)
        for model_id, last_updated in python_utils.ZIP(
                model_ids, last_updated_values):
            model = base_models.BaseModel.get_by_id(model_id)
            self.assertEqual(model.last_updated, last_updated)

        # Field last_updated will get updated because update_last_updated_time
        # is set to True (by default).
        models_3_without_none = cast(
            List[base_models.BaseModel],
            base_models.BaseModel.get_multi(model_ids)
        )
        base_models.BaseModel.update_timestamps_multi(models_3_without_none)
        base_models.BaseModel.put_multi(models_3_without_none)
        for model_id, last_updated in python_utils.ZIP(
                model_ids, last_updated_values):
            model = base_models.BaseModel.get_by_id(model_id)
            self.assertNotEqual(model.last_updated, last_updated)
示例#23
0
    def test_error_is_raised_with_invalid_validation_type_for_domain_object(
        self
    ) -> None:
        model = base_models.BaseModel(
            id='mock-123',
            deleted=False,
            created_on=self.YEAR_AGO,
            last_updated=self.NOW)

        output = (
            self.pipeline
            | beam.Create([model])
            | beam.ParDo(MockValidateModelDomainObjectInstancesWithInvalid())
        )
        self.assert_pcoll_equal(output, [
            base_validation_errors.ModelDomainObjectValidateError(
                model, 'Invalid validation type for domain object: invalid')
        ])
示例#24
0
 def setUp(self) -> None:
     super(BaseAuditErrorTests, self).setUp()
     self.model = base_models.BaseModel(id='123')
示例#25
0
    def test_get_from_datastore_model(self) -> None:
        model = base_models.BaseModel()

        self.assertEqual(job_utils.get_model_kind(model), 'BaseModel')