def test_status(self): with Transaction() as tran: instance = Dummy(raw={"patent": "aaa"}) assert instance.status is Status.NEW with ForceChanger(instance): instance.uri = "/uri/patent/usa/granted/1/" assert instance.uri == "/uri/patent/usa/granted/1/" assert instance.status is Status.NEW instance.save() with tran: assert instance.status is Status.NORMAL assert instance.uri == "/uri/patent/usa/granted/1/" assert instance.status is Status.NORMAL assert instance.uri == "/uri/patent/usa/granted/1/" with ForceChanger(instance): instance.uri = "/uri/patent/usa/granted/2/" assert instance.uri == "/uri/patent/usa/granted/2/" assert instance.status is Status.DIRTY instance.save() assert instance.status is Status.DIRTY assert instance.uri == "/uri/patent/usa/granted/2/" instance.delete() with tran: assert instance.status is Status.DELETED with self.assertRaises(AssertionError): with ForceChanger(instance): instance.uri = "/uri/patent/usa/granted/3/" assert instance.uri == "/uri/patent/usa/granted/2/"
def test_optimistic_lock(self): with Transaction(): Dummy().save() with Transaction() as tran1: instance1 = Model.objects.get(type__in=Dummy.types) with Transaction() as tran2: instance2 = Model.objects.get(type__in=Dummy.types) assert instance1 == instance2 assert id(instance1) != id(instance2) assert instance1.version == instance2.version == 1 with tran1: with ForceChanger(instance1): instance1.uri = "/uri/patent/usa/granted/1/" assert instance1.version == 1 instance1.save() assert instance1.version == 1 assert instance1.version == 2 with self.assertRaises(OptimisticLockException): with tran2: with ForceChanger(instance2): instance2.uri = "/uri/patent/usa/granted/2/" assert instance2.version == 1 instance2.save()
def test_history2(self): with Transaction(): assert ModelHistory.objects.count() == 0 instance = Dummy.objects.create() assert ModelHistory.objects.count() == 0 with ForceChanger(instance): instance.uri = "/uri/1/" instance.save() assert ModelHistory.objects.count() == 0 assert ModelHistory.objects.count() == 1 - 1 with Transaction(): instance = Model.objects.get(id=instance.id) with ForceChanger(instance): instance.uri = "/uri/2/" instance.save() assert ModelHistory.objects.count() == 1 - 1 assert ModelHistory.objects.count() == 2 - 1 with Transaction(): instance = Model.objects.get(id=instance.id) instance.delete() assert ModelHistory.objects.count() == 2 - 1 assert ModelHistory.objects.count() == 3 - 1 with Transaction(): instance = Model.objects.get_deleted(id=instance.id) instance._destroy() assert ModelHistory.objects.count() == 4 - 1 assert ModelHistory.objects.count() == 4 - 1
def test_model_version(self): with Transaction(): instance = Dummy() assert instance.version == 0 with ForceChanger(instance): instance.uri = "/uri/patent/usa/granted/1/" assert instance.uri == "/uri/patent/usa/granted/1/" assert instance.version == 0 instance.save() assert instance.version == 1 with Transaction(): instance2 = Model.objects.get(id=instance.id) assert instance2.version == 1 with ForceChanger(instance2): instance2.uri = "/uri/patent/usa/granted/2/" assert instance2.version == 1 instance2.save() assert instance2.version == 2 with Transaction() as tran: instance3 = Model.objects.get(type__in=Dummy.types) assert instance3.version == 2 tran.remove(instance3) instance_db = Model.objects.get(id=instance3.id) assert id(instance_db) != id(instance3) assert instance_db.version == 2 instance_db.delete() assert instance_db.version == 2 assert instance_db.version == 3 assert instance3.version == 2
def test_uri_property(self): uri = "/uri/1/" assert Dummy.objects.filter(uri=uri).count() == 0 instance = Dummy() assert instance.uri is None assert instance.computed["uri"] is None assert not instance.computed_uri_hash with ForceChanger(instance): instance.uri = uri assert instance.uri == uri assert instance.computed["uri"] == uri assert instance.computed_uri_hash instance.save() assert Dummy.objects.filter(uri=uri).count() == 1 with ForceChanger(instance): instance.uri = None assert instance.uri is None assert instance.computed_uri_hash is None uname = "*****@*****.**" instance.uname = uname assert instance.uname == uname assert instance.uri == "/uri/base/dummy/{}/".format(uname) assert instance.computed_uri_hash is not None instance.save() tran = TransactionManager.get_transaction() instance._syncdb_update(tran) query = str(Dummy.objects.filter(uname=uname).query) assert query.find("computed_uri_hash") != -1 assert Dummy.objects.filter(uname=uname).count() == 1 assert Dummy.objects.filter(uname="asdf").count() == 0 with self.assertRaises(AssertionError): instance.uri = "asdf" other_uname = "*****@*****.**" instance.uname = other_uname assert instance.uname == other_uname instance.uname = uname assert instance.uname == uname instance2 = Dummy() instance2.uname = other_uname assert instance2.uname == other_uname assert instance2.status == Status.NEW with self.assertRaises(DuplicateUriException): instance2.uname = uname assert instance2.status == Status.INVALID with self.assertRaises(AssertionError): instance2.uname = other_uname with self.assertRaises(AssertionError): instance2.save() instance.save()
def test_model_setter(self): uri = "/uri/patent/usa/granted/1/" instance = Dummy() with ForceChanger(instance): instance.uri = uri self.assertDictContainsSubset({"uri": uri}, instance.computed) instance.temp = 1 self.assertDictContainsSubset({"temp": 1}, instance.data) with self.assertRaises(AttributeError): del instance.temp with self.assertRaises(TypeError): del instance["temp"] instance.patent.update({"raw": "ttt", "plain": "ttt"}) self.assertDictContainsSubset( {"patent": { "raw": "ttt", "plain": "ttt", "html": None }}, instance.data) instance.patent.update({"raw": "u", "html": "u"}) self.assertDictContainsSubset( {"patent": { "raw": "u", "plain": "ttt", "html": "u" }}, instance.data) instance.data["monitors"] = [] instance.monitors.append(1) self.assertDictContainsSubset({"monitors": [1]}, instance.data) instance.monitors.append(2) self.assertDictContainsSubset({"monitors": [1, 2]}, instance.data)
def test_data_setter(self): instance = Dummy() old_computed = deepcopy(instance.computed) old_data = deepcopy(instance.data) with ForceChanger(instance): instance.uri = "/uri/1/" assert instance.computed["uri"] == "/uri/1/" old_computed["uri"] = "/uri/1/" old_computed["uri_hash"] = json_encode(instance.uri_hash) assert instance.computed == old_computed instance.data = {"temp": 1} assert instance.data["temp"] == 1 old_data["temp"] = 1 assert instance.data == old_data instance.data = {"temp": 0} assert instance.data["temp"] == 0 old_data["temp"] = 0 assert instance.data == old_data instance.monitors.append(0) assert instance.data["monitors"] == [0] old_data["monitors"] = [0] assert instance.data == old_data
def test_computed_framework(self): instance = Dummy() with self.assertRaises(AssertionError): instance.computed = {} assert instance.computed_uri_hash is None with ForceChanger(instance): instance.uri = "/uri/1/" uri_hash_1 = instance.computed_uri_hash assert uri_hash_1 assert instance.computed["uri_hash"] == str(uri_hash_1) with ForceChanger(instance): instance.uri = "/uri/2/" uri_hash_2 = instance.computed_uri_hash assert uri_hash_2 assert instance.computed["uri_hash"] == str(uri_hash_2) assert uri_hash_1 != uri_hash_2
def onchange_subfield(self, field_name, subfield_name, old, new): assert old != new, "old 와 new 값이 같은 경우는 원천적으로 발생되지 않도록 해야 합니다." old_status, _mjson_revert_patch, subfields = (self.status, self._mjson_revert_patch, self.subfields) subfield = subfields[field_name][subfield_name] assert not isinstance(subfield, SubfieldWrapper) if old_status == Status.CREATING: # TODO : save() 호출 자체를 없애고 나면 이것도 없애기 # 이때는 on_create 이후 별도로 onchange 이벤트를 일괄 발생시킴 return if subfield_name not in _mjson_revert_patch[field_name]: _mjson_revert_patch[field_name][subfield_name] = json_encode(old) with ForceChanger(self): if old_status not in (Status.NEW, Status.NO_SYNC): self.status = Status.DIRTY self._process_dependent_computed(subfield_name) # original onchange_func_name = ONCHANGE_FUNC_NAME.format(subfield_name) func = getattr(self, onchange_func_name, None) func and func(old, new) # wrappers for wrapper in subfields["_wrapper_reverse"].get(subfield_name, []): onchange_func_name = ONCHANGE_FUNC_NAME.format(wrapper.wrapper_subfield_name) func = getattr(self, onchange_func_name, None) func and func(old, new) self._process_expire_onchange(subfield_name)
def test_data_setter(self): with Transaction() as tran: instance = Dummy.objects.create() old_data = deepcopy(instance.data) old_computed = deepcopy(instance.computed) old_transaction_id = tran.id with tran: with ForceChanger(instance): instance.uri = "/uri/1/" instance.save() with Transaction(): instance_old = instance instance = Dummy.objects.get(id=instance.id) assert id(instance_old) != id(instance) assert instance.computed["uri"] == "/uri/1/" old_computed["uri"] = "/uri/1/" old_computed["uri_hash"] = json_encode(instance.uri_hash) old_computed["_mjson_revert_patch"] = { "data": {}, "status": 10, "version": 1, "computed": { "uri": None, "uri_hash": None }, "computed_uri_hash": None, "last_transaction": old_transaction_id, } assert instance.computed == old_computed instance.data = {"temp": 1} instance.save() with Transaction(): instance_old = instance instance = Dummy.objects.get(id=instance.id) assert id(instance_old) != id(instance) assert instance.data["temp"] == 1 old_data["temp"] = 1 assert instance.data == old_data instance.data = {"temp": 0} instance.save() with Transaction(): instance_old = instance instance = Dummy.objects.get(id=instance.id) assert id(instance_old) != id(instance) assert instance.data["temp"] == 0 old_data["temp"] = 0 assert instance.data == old_data instance.monitors.append(0) instance.save() with Transaction(): instance_old = instance instance = Dummy.objects.get(id=instance.id) assert id(instance_old) != id(instance) assert instance.data["monitors"] == [0] old_data["monitors"] = [0] assert instance.data == old_data
def test_set_computed_uri_hash(self): instance = Dummy() with self.assertRaises(AssertionError): instance.computed_uri_hash = "/uri/0/" assert instance.computed_uri_hash is None with ForceChanger(instance): instance.uri = "/uri/1/" with self.assertRaises(AssertionError): instance.computed_uri_hash = None assert instance.computed_uri_hash is not None
def test_model_getter(self): instance = Dummy() uri = "/uri/patent/usa/granted/1/" with ForceChanger(instance): instance.uri = uri assert instance.uri == uri instance.d = {"a": 1, "b": 2, "c": None} assert instance.d == {"a": 1, "b": 2, "c": None} assert instance.d["a"] == 1
def test_model_setter2(self): instance = Dummy(raw={"patent": "aaa"}) with ForceChanger(instance): instance.uri = "/uri/patent/usa/granted/1/" assert instance.computed["uri"] == "/uri/patent/usa/granted/1/" instance.save() assert instance.computed["uri"] == "/uri/patent/usa/granted/1/" assert instance.computed["uri"] == "/uri/patent/usa/granted/1/" with ForceChanger(instance): instance.uri = "/uri/patent/usa/granted/2/" assert instance.computed["uri"] == "/uri/patent/usa/granted/2/" instance.save() assert instance.computed["uri"] == "/uri/patent/usa/granted/2/" instance.delete() with self.assertRaises(AssertionError): with ForceChanger(instance): instance.uri = "/uri/patent/usa/granted/3/" assert instance.computed["uri"] == "/uri/patent/usa/granted/2/"
def test_history4(self): with Transaction(): assert ModelHistory.objects.count() == 0 instance = Dummy.objects.create() assert ModelHistory.objects.count() == 0 with Transaction(): instance = Model.objects.get(id=instance.id) with ForceChanger(instance): instance.uri = "/uri/1/" instance.save() assert ModelHistory.objects.count() == 0 assert ModelHistory.objects.count() == 1
def test(self): instance = Dummy() instance.d = {"a": 1, "b": 2, "c": now()} actor = Actor() with ForceChanger(instance): assert instance.data["owner"] is None instance.owner = actor assert instance.data["owner"] == actor.id instance.owner = None assert instance.data["owner"] is None instance.owner = actor assert instance.data["owner"] == actor.id
def test_create_db3(self): with Transaction(): assert Model.objects.count() == 0 instance = Dummy() assert Model.objects.count() == 0 instance.save() assert Model.objects.count() == 1 assert instance.version == 1 with ForceChanger(instance): instance.uri = "/uri/2/" instance.save() assert instance.version == 1 assert instance.version == 2
def test_filter(self): with Transaction() as tran: instance = Dummy.objects.create() with ForceChanger(instance): instance.uri = "/uri/1/" instance.temp = 1 instance.monitors.extend([2, 3, 4]) instance.save() Dummy.objects.create() other_dummy = Dummy.objects.create() dummy = Dummy.objects.create() container = DummyContainer.objects.create() instance.container = container instance.save() dummy.container = container dummy.save() container2 = DummyContainer.objects.create() assert instance.version == 0 assert dummy.version == 0 assert instance.version == 1 assert dummy.version == 1 qs1 = Dummy.objects.all() assert len(qs1) == 4 assert qs1._result_cache is not None qs2 = qs1.filter(version=1) assert qs2 != qs1 assert len(qs2) == 4 qs3 = qs1.filter(version=2) assert qs3 != qs1 assert len(qs3) == 0 assert len(qs1.filter(version=4)) == 0 qs5 = DummyContainer.objects.all() assert len(qs5) == 2 assert qs5._result_cache is not None # json (DB) assert len(Dummy.objects.filter(data__temp=1)) == 1 assert len(Dummy.objects.filter(data__temp=0)) == 0 assert len(Dummy.objects.filter(data__monitors__contains=2)) == 1 assert len(Dummy.objects.filter(data__monitors__contains=1)) == 0 assert len(Dummy.objects.filter(data__monitors__contains=[2, 3])) == 1 # json (cache) assert len(qs1.filter(data__temp=1)) == 1 assert len(qs1.filter(data__temp=0)) == 0 assert len(qs1.filter(data__monitors__contains=2)) == 1 assert len(qs1.filter(data__monitors__contains=1)) == 0 assert len(qs1.filter(data__monitors__contains=[2, 3])) == 1
def test(self): uri = "/uri/1/" with Transaction(): instance = Dummy() with ForceChanger(instance): instance.uri = uri assert instance.uri_hash == compute_hash_uuid(uri) instance.save() assert instance.uri_hash == compute_hash_uuid(uri) assert instance.uri_hash == compute_hash_uuid(uri) mjson1 = instance.mjson with ReadonlyTransaction(): instance = Dummy.objects.get(id=instance.id) assert instance.mjson == mjson1 assert instance.uri == uri assert instance.uri_hash == compute_hash_uuid(uri)
def test_standalone(self): instance = Dummy() uri = "/uri/patent/usa/granted/1/" with ForceChanger(instance): instance.uri = uri assert instance.uri == uri instance.d = {"a": 1, "b": 2, "c": None} assert instance.d == {"a": 1, "b": 2, "c": None} assert instance.d["a"] == 1 instance.d = {"a": 11} assert instance.d == {"a": 11, "b": 2, "c": None} instance.d = {"b": 22} assert instance.d == {"a": 11, "b": 22, "c": None} instance.d = {} assert instance.d == {"a": 11, "b": 22, "c": None}
def test_order_by(self): with Transaction() as tran: instance = Dummy.objects.create() with ForceChanger(instance): instance.uri = "/uri/1/" instance.save() Dummy.objects.create() Dummy.objects.create() Dummy.objects.create() qs = Dummy.objects.order_by("id") assert len(qs) == 4 assert qs._result_cache is not None qs2 = qs.order_by("-id") assert id(qs._result_cache) != id(qs2._result_cache) assert qs2._result_cache[0] == qs._result_cache[3] assert qs2._result_cache[1] == qs._result_cache[2] assert qs2._result_cache[2] == qs._result_cache[1] assert qs2._result_cache[3] == qs._result_cache[0]
def test_write(self): cls = self.get_proxy_model_class() if not cls.__dict__.get("ABSTRACT", False): assert cls.objects.count() == 0 instance = self._get_inited_instance() assert cls.objects.count() == 0 instance.save() assert cls.objects.count() == 1 with ForceChanger(instance): instance.optimistic_lock_count += 1 instance.save() assert cls.objects.count() == 1 instance.delete() assert cls.objects.count() == 0 instance._destroy() assert cls.objects.count() == 0 assert instance.id is None else: with self.assertRaises(AssertionError): cls.objects.create()
def test_no_transaction(self): with Transaction(): Dummy().save() Dummy().save() Dummy().save() assert Model.objects.count() == 3 assert len(Model.objects.filter(type__in=Dummy.types).all()) == 3 assert not Model.objects.filter(type__in=Dummy.types).query.order_by assert Model.objects.order_by("-id").query.order_by assert Model.objects.filter(type__in=Dummy.types).order_by("-id").query.order_by instance1 = Model.objects.filter(type__in=Dummy.types).order_by("-id").first() assert instance1 instance2 = Model.objects.get(id=instance1.id) assert instance1 == instance2 assert id(instance1) != instance2 with self.assertRaises(AssertionError): with ForceChanger(instance2): instance2.uri = "/uri/2/"
def _syncdb_update(self, tran, update_fields=None): assert update_fields is None update_fields = self.get_modified_field_names() assert len(update_fields) >= 2, "수정된 필드가 없는데 syncdb_update() 가 호출되었습니다." assert "status" in update_fields and "status" in self._mjson_revert_patch, "status 필드가 적절한 방식으로 수정되지 않았습니다." assert ( "version" not in update_fields and "last_transaction" not in update_fields ), "system 필드가 적절한 방식으로 수정되지 않았습니다." with ForceChanger(self): self.version += 1 self.last_transaction = tran.id if settings.IS_UNIT_TEST: mjson_reverted = patch_mjson(deepcopy(self.mjson), MappingProxyType(self._mjson_revert_patch)) # TODO : schema 만 바뀐 경우에 save() 가 가능하도록 하는 구현 부분 리팩토링 if "_schema_changed" in mjson_reverted["data"]: del mjson_reverted["data"]["_schema_changed"] if "_schema_changed" in mjson_reverted["computed"]: del mjson_reverted["computed"]["_schema_changed"] assert mjson_reverted == self._mjson_on_init, "subfield 를 통하지 않는 등 잘못된 방식으로 필드가 수정되었습니다." self.create_history() self.computed["_mjson_revert_patch"] = self._mjson_revert_patch update_fields.extend(["version", "last_transaction", "computed"]) super()._syncdb_update(tran, update_fields=update_fields)
def test_transaction(self): with Transaction(): instance = Dummy() instance.save() assert instance.last_transaction is not None old_last_transaction = instance.last_transaction with Transaction() as tran1: tran2 = TransactionManager.get_transaction() assert id(tran1) == id(tran2) instance1 = Model.objects.get(id=instance.id) # 중간에 다른 트랜잭션에서 치고 들어온 것을 simulation with Transaction() as tran3: assert tran3 != tran1 tran4 = TransactionManager.get_transaction() assert id(tran3) == id(tran4) instance2 = Model.objects.get(id=instance1.id) assert instance2 == instance1 assert id(instance1) != id(instance2) with ForceChanger(instance2): instance2.uri = "/uri/1/" instance2.save() assert instance2.last_transaction > old_last_transaction old_last_transaction = instance2.last_transaction with tran1: tran6 = TransactionManager.get_transaction() assert id(tran6) == id(tran1) assert instance1.computed["uri"] is None with Transaction(): instance3 = Model.objects.get(id=instance1.id) assert instance3.computed["uri"] == "/uri/1/" instance3.delete() assert instance3.last_transaction > old_last_transaction
def take_optimistic_lock(self): if self.status in (Status.CREATING, Status.NEW): return with ForceChanger(self): self.optimistic_lock_count += 1 self.save()
def _mark_delete(self): with ForceChanger(self): self.computed_uri_hash = None super()._mark_delete()