def test_dispatched_event(httpserver): from krules_core import messages message_dispatcher_factory.override( providers.Singleton(lambda: CloudEventsDispatcher( httpserver.url, "pytest", test=True))) router = message_router_factory() subject = subject_factory("test-subject") subject.set_ext("ext1", "val1") subject.set_ext("ext2", 2) _id, code, sent_headers = router.route("test-message", subject, {"key1": "hello"}) assert (200 <= code < 300) assert (sent_headers.get("Ce-Id") == _id) assert (sent_headers.get("Ce-Source") == "pytest") assert (sent_headers.get("Ce-Subject") == "test-subject") assert (sent_headers.get("Ce-Type") == "test-message") assert (sent_headers.get("Ce-Originid") == _id) assert (sent_headers.get("Ce-Ext1") == "val1") assert (sent_headers.get("Ce-Ext2") == "2") # with event info subject = subject_factory("test-subject", event_info={"Originid": 1234}) _, _, sent_headers = router.route("test-message", subject, {"key1": "hello"}) assert (sent_headers.get("Ce-Id") != sent_headers.get("Ce-Originid")) assert (sent_headers.get("Ce-Originid") == '1234') # property name _, _, sent_headers = router.route(messages.SUBJECT_PROPERTY_CHANGED, subject, {PayloadConst.PROPERTY_NAME: "foo"}) assert (sent_headers.get("Ce-Propertyname") == 'foo')
def test_props(): pod = subject_factory(f"k8s:/api/v1/namespaces/{NAMESPACE}/pods/{POD_NAME}", use_cache_default=True) assert pod.ext_name == pod.get_ext("name") == POD_NAME with pytest.raises(AttributeError): pod.get("p1") pod.p1 = 1 pod.ext_p2 = "p2" pod.store() pod = subject_factory(f"k8s:/api/v1/namespaces/{NAMESPACE}/pods/{POD_NAME}", use_cache_default=True) assert pod.p1 == 1 pod.p1 = lambda p: p+1 assert pod.p1 == 2 pod_nc = subject_factory(f"k8s:/api/v1/namespaces/{NAMESPACE}/pods/{POD_NAME}", use_cache_default=False) assert pod_nc.p1 == 1 pod.store() assert pod_nc.p1 == 2 del pod.p1 pod.store() with pytest.raises(AttributeError): pod_nc.get("p1")
def test_dispatched_event(fake_receiver): from krules_core import event_types event_dispatcher_factory.override( providers.Singleton(lambda: CloudEventsDispatcher( fake_receiver.url, "pytest", test=True))) router = event_router_factory() subject = subject_factory("test-subject") subject.set_ext("ext1", "val1") subject.set_ext("ext2", "2") _id, code, sent_headers = router.route("test-type", subject, {"key1": "hello"}) assert (200 <= code < 300) assert (sent_headers.get("ce-id") == _id) assert (sent_headers.get("ce-source") == "pytest") assert (sent_headers.get("ce-subject") == "test-subject") assert (sent_headers.get("ce-type") == "test-type") assert (sent_headers.get("ce-Originid") == _id) assert (sent_headers.get("ce-ext1") == "val1") assert (sent_headers.get("ce-ext2") == "2") # with event info subject = subject_factory("test-subject", event_info={"originid": 1234}) _, _, sent_headers = router.route("test-type", subject, {"key1": "hello"}) assert (sent_headers.get("id") != sent_headers.get("ce-Originid")) assert (sent_headers.get("ce-Originid") == '1234') # property name _, _, sent_headers = router.route(event_types.SUBJECT_PROPERTY_CHANGED, subject, {PayloadConst.PROPERTY_NAME: "foo"}) assert (sent_headers.get("ce-propertyname") == 'foo')
def test_property_proxy(subject_no_cache): from krules_core.providers import subject_factory, subject_storage_factory global _test_events _test_events = [] subject_no_cache.flush() with pytest.raises(AttributeError): _ = subject_no_cache.foo subject_no_cache.foo = 1 assert subject_no_cache.foo == 1 assert len(_test_events) == 1 if subject_storage_factory(subject_no_cache.name).is_persistent(): assert subject_factory(subject_no_cache.name).get("foo") == 1 assert subject_no_cache.m_foo == 1 assert subject_no_cache.foo == 1 subject_no_cache.m_foo = 2 assert len(_test_events) == 1 subject_no_cache.ext_foo = 3 assert subject_no_cache.ext_foo == 3 assert subject_no_cache.foo == 2 assert len(_test_events) == 1 if subject_storage_factory(subject_no_cache.name).is_persistent(): assert subject_factory(subject_no_cache.name).get_ext("foo") == 3 subject_no_cache.foo = lambda foo: foo * foo assert len(_test_events) == 2 assert subject_no_cache.foo == 4 subject_no_cache.foo.incr() assert len(_test_events) == 3 assert subject_no_cache.foo == 5 subject_no_cache.m_foo.incr(2) assert len(_test_events) == 3 assert subject_no_cache.foo == 7 subject_no_cache.foo.decr() assert subject_no_cache.foo == 6 with pytest.raises(TypeError): subject_no_cache.ext_foo.incr() with pytest.raises(TypeError): subject_no_cache.ext_foo.decr() del subject_no_cache.foo assert len(_test_events) == 5 with pytest.raises(AttributeError): _ = subject_no_cache.foo subject_no_cache.foo = 1 del subject_no_cache.m_foo assert len(_test_events) == 6 with pytest.raises(AttributeError): _ = subject_no_cache.foo del subject_no_cache.ext_foo with pytest.raises(AttributeError): _ = subject_no_cache.ext_foo
def execute(self, message=None, subject=None, payload=None, hash=None, when=lambda _: datetime.now(), replace=False): if message is None: message = self.message if subject is None: subject = self.subject if payload is None: payload = self.payload if str(self.subject) != str(subject): subject = subject_factory(str(subject), event_info=self.subject.event_info()) if callable(when): when = when(self) if type(when) is not str: when = when.isoformat() new_payload = { "message": message, "subject": str(subject), "payload": payload, "when": when, "replace": replace } message_router_factory().route( "schedule-message", subject, new_payload, dispatch_policy=DispatchPolicyConst.DIRECT)
def subject_no_cache(): from krules_core.providers import subject_factory global counter counter += 1 return subject_factory('test-subject-{0}'.format(counter), use_cache_default=False).flush()
def test_with_self(): class WithSelfSet(RuleFunctionBase): def execute(self, arg1, arg2, arg3): self.payload["arg1"] = arg1 self.payload["arg2"] = arg2 self.payload["arg3"] = arg3 RuleFactory.create( "test-with-self", subscribe_to="test-argprocessors-self", data={ processing: [ WithSelfSet(lambda self: self.payload["value_from"], arg2=lambda self: self.subject.get("value_from"), arg3=lambda p: "I'll never be called") ] }) payload = {"value_from": 1} subject = subject_factory("test-1") subject.set("value_from", 2) event_router_factory().route("test-argprocessors-self", subject, payload) proc_events_rx_factory.subscribe(lambda x: x[ rulename] == "test-with-self" and _assert(x[processing][0]["args"][ 0] == 1 and x[processing][0]["kwargs"]["arg2"] == 2 and isinstance( x[processing][0]["kwargs"]["arg3"], str))) assert payload["arg1"] == 1 assert payload["arg2"] == 2 assert inspect.isfunction(payload["arg3"])
def execute(self): ''' take the list of networks interfaces name set by multus in "k8s.v1.cni.cncf.io/networks" annotation and for each name add into the subject the pair name-status, which status is the status set by multus in "k8s.v1.cni.cncf.io/networks-status" annotation. (status mainly contain the ip of the network interface) ''' interfaces = self.payload["metadata"]["annotations"][ "k8s.v1.cni.cncf.io/networks"] statuses = self.payload["metadata"]["annotations"][ "k8s.v1.cni.cncf.io/networks-status"] statuses = json.loads(statuses) interfaces = interfaces.split(', ') subject = subject_factory( f"service:{self.payload['metadata']['name']}") if "multus-app" in self.payload["metadata"]["labels"]: subject.set_ext("multusapp", self.payload["metadata"]["labels"]["multus-app"]) for interface in interfaces: for status in statuses: if status.get("name") == interface: subject.set(status.get("name"), status, use_cache=False) break
def publish_proc_events_filtered(result, jp_expr, expt_value, debug=False): if jp_expr is not None: if not isinstance(jp_expr, list): jp_expr = [jp_expr] for expr in jp_expr: if callable(expt_value): _pass = expt_value(jp.match1(f"$[?({expr})]", [result])) else: _pass = (jp.match1(f"$[?({expr})]", [result]) == expt_value) if not _pass: return data = result event_info = data["event_info"] result_subject = subject_factory(data[RuleConst.RULENAME], event_info=event_info) if debug and result["type"] != RULE_PROC_EVENT: dispatch_policy = DispatchPolicyConst.NEVER else: dispatch_policy = DispatchPolicyConst.DIRECT event_router_factory().route(RULE_PROC_EVENT, result_subject, data, dispatch_policy=dispatch_policy)
def route(self, type, subject, payload, dispatch_policy=DispatchPolicyConst.DEFAULT): if isinstance(subject, str): # NOTE: this should have already happened if we want to take care or event info from krules_core.providers import subject_factory subject = subject_factory(subject) from ..providers import event_dispatcher_factory _callables = self._callables.get(type, None) # try: if not dispatch_policy == DispatchPolicyConst.DIRECT: if _callables is not None: for _callable in _callables: _callable(type, subject, payload) # finally: # subject.store() # TODO: unit test (policies) if dispatch_policy != DispatchPolicyConst.NEVER and _callables is None \ and dispatch_policy == DispatchPolicyConst.DEFAULT \ or dispatch_policy == DispatchPolicyConst.ALWAYS \ or dispatch_policy == DispatchPolicyConst.DIRECT: logger.debug("dispatch {} to {} with payload {}".format( type, subject, payload)) return event_dispatcher_factory().dispatch(type, subject, payload)
def main(): start_time = datetime.now() try: dispatch_policy = os.environ.get("DISPATCH_POLICY", DispatchPolicyConst.NEVER) m = marshaller.NewDefaultHTTPMarshaller() event = m.FromRequest(v1.Event(), request.headers, io.BytesIO(request.data), lambda x: json.load(x)) event_info = event.Properties() event_info.update(event_info.pop("extensions")) event_data = event_info.pop("data") app.logger.debug("RCVR: {}".format(event_data)) event_type = event_info.get("type") subject = event_info.get("subject", "sys-0") if event_info["source"] == os.environ.get("K_SERVICE", os.environ.get("SOURCE")): return Response(status=201) event_info["originid"] = event_info.get("originid", event_info.get("id")) app.logger.debug("subject: {}".format(subject)) app.logger.debug("event_data: {}".format(event_data)) subject = subject_factory(name=subject, event_info=event_info, event_data=event_data) event_data["_event_info"] = event_info # TODO: KRUL-155 try: app.router.route(event_type, subject, event_data, dispatch_policy=dispatch_policy) finally: pass exec_time = (datetime.now() - start_time).total_seconds() app.logger.info( "Event", extra={ 'props': { 'event_info': event_info, 'type': event_type, 'subject': subject.name, 'exec_time': exec_time, # 'headers': list(headers.keys()) } }) return Response(status=200) except Exception as ex: app.logger.error(ex, exc_info=True) return Response(status=201)
def publish_proc_events_all(result): data = result # data = json.loads(json.dumps(result, cls=_JSONEncoder).encode("utf-8")) event_info = data.get("event_info", {}) result_subject = subject_factory(data[RuleConst.RULENAME], event_info=event_info) event_router_factory().route( RULE_PROC_EVENT, result_subject, data, dispatch_policy=DispatchPolicyConst.DIRECT )
def test_inferred_properties(): global POD_NAME, NAMESPACE pod = subject_factory(f"k8s:/api/v1/namespaces/{NAMESPACE}/pods/{POD_NAME}/status", event_data={}) assert pod.ext_name == pod.get_ext("name") == POD_NAME assert pod.ext_namespace == pod.get_ext("namespace") == NAMESPACE #assert pod.ext_group == pod.get_ext("group") == "" assert pod.ext_apiversion == pod.get_ext("apiversion") == "v1" assert pod.ext_resourcetype == pod.get_ext("resourcetype") == "pods" assert pod.ext_subresource == pod.get_ext("subresource") == "status"
def set_running_fws_in_payload(obj, payload): """ Set ip address of the LB_FW_NETWORK interface of the FW passed as first parameter in the payload passed as second parameter. """ subject = subject_factory(f"service:{obj['metadata']['name']}") try: if subject.get_ext("multusapp"): payload["fw_ips"] = payload.get("fw_ips", []) payload["fw_ips"].append(subject.get(LB_FW_NETWORK)["ips"][0]) except AttributeError as ex: print(str(ex))
def test_cache_policy(subject): from krules_core.providers import subject_factory, subject_storage_factory # default policy: use cache subject.flush() subject.set("p1", None) subject.set_ext("p2", None) subject_fresh = subject_factory(subject.name) with pytest.raises(AttributeError): subject_fresh.get("p1") with pytest.raises(AttributeError): subject_fresh.get_ext("p2") subject = subject_factory(subject.name, use_cache_default=False) subject.flush() subject.set("p1", None) subject.set_ext("p2", None) if subject_storage_factory(subject.name).is_persistent(): subject_fresh = subject_factory(subject.name) subject_fresh.get("p1") subject_fresh.get_ext("p2")
def publish_proc_events_errors(result): if not result.get("got_errors", False): return data = result # data = json.loads(json.dumps(result, cls=_JSONEncoder).encode("utf-8")) event_info = data["event_info"] result_subject = subject_factory(data[RuleConst.RULENAME], event_info=event_info) event_router_factory().route( RULE_PROC_EVENT, result_subject, data, dispatch_policy=DispatchPolicyConst.DIRECT )
def k8s_subject(obj=None, resource_path=None, prefix="k8s:"): """ Returns a k8s subject instance providing a kubernetes resource :param obj: :param resource_path: :param prefix: :return: """ if hasattr(obj, 'obj'): obj = obj.obj if obj is None: obj = {} if resource_path is None: resource_path = obj["metadata"]["selfLink"] return subject_factory(f"{prefix}{resource_path}", event_data=obj)
def dispatch(self, event_type, subject, payload): if isinstance(subject, str): subject = subject_factory(subject) _event_info = subject.event_info() _id = str(uuid.uuid4()) logging.debug("new event id: {}".format(_id)) event = v1.Event() event.SetContentType('application/json') event.SetEventID(_id) event.SetSource(self._source) event.SetSubject(str(subject)) event.SetEventTime( datetime.utcnow().replace(tzinfo=pytz.UTC).isoformat()) event.SetEventType(event_type) # set extended properties ext_props = subject.get_ext_props() property_name = payload.get(PayloadConst.PROPERTY_NAME, None) if property_name is not None: ext_props.update({"propertyname": property_name}) event.SetExtensions(ext_props) event.Set('Originid', str(_event_info.get("originid", _id))) event.SetData(payload) m = marshaller.NewHTTPMarshaller( [binary.NewBinaryHTTPCloudEventConverter()]) headers, body = m.ToRequest(event, converters.TypeBinary, lambda x: json.dumps(x, cls=_JSONEncoder)) # headers['Ce-Originid'] = str(_event_info.get("Originid", _id)) if callable(self._dispatch_url): dispatch_url = self._dispatch_url(subject, event_type) else: dispatch_url = self._dispatch_url response = requests.post(dispatch_url, headers=headers, data=body) response.raise_for_status() if self._test: return _id, response.status_code, headers return _id
def publish_proc_events_filtered(result, jp_expr, expt_value): if callable(expt_value): _pass = expt_value(jp.match1(jp_expr, result)) else: _pass = (jp.match1(jp_expr, result) == expt_value) if not _pass: return data = result # data = json.loads(json.dumps(result, cls=_JSONEncoder).encode("utf-8")) event_info = data["event_info"] result_subject = subject_factory(data[RuleConst.RULENAME], event_info=event_info) event_router_factory().route( RULE_PROC_EVENT, result_subject, data, dispatch_policy=DispatchPolicyConst.DIRECT )
def fake_receiver_app(environ, start_response): """Simplest possible WSGI application""" request = Request(environ) m = marshaller.NewDefaultHTTPMarshaller() event = m.FromRequest(v1.Event(), request.headers, io.BytesIO(request.data), lambda x: json.load(x)) event_info = event.Properties() event_info.update(event_info.pop("extensions")) subject = subject_factory(event_info.get("subject", "sys-0")) assert "originid" in event_info assert "subject" in event_info assert "data" in event_info status = '200 OK' response_headers = [('Content-type', 'text/plain')] start_response(status, response_headers) return ['Ok']
def test_with_payload_and_subject(): class WithPayloadSet(RuleFunctionBase): def execute(self, arg1, arg2, arg3): self.payload["arg1"] = arg1 self.payload["arg2"] = arg2 self.payload["arg3"] = arg3 RuleFactory.create( "test-with-payload-and-subject", subscribe_to="test-argprocessors-payload-and-subject", data={ processing: [ WithPayloadSet(lambda payload: payload["value_from"], arg2=lambda subject: subject.get("value_from"), arg3=lambda p: "I'll never be called") ] }) _payload = {"value_from": 1} _subject = subject_factory("test-1") _subject.set("value_from", 2) event_router_factory().route("test-argprocessors-payload-and-subject", _subject, _payload) proc_events_rx_factory().subscribe( lambda x: x[rulename] == "test-with-payload-and-subject" and _assert(x[ processing][0]["args"][0] == 1 and x[processing][0][ "kwargs"]["arg2"] == 2 and hasattr( x[processing][0]["kwargs"]["arg3"], "__call__"))) assert _payload["arg1"] == 1 assert _payload["arg2"] == 2 assert inspect.isfunction(_payload["arg3"])
def main(): start_time = datetime.now() try: dispatch_policy = os.environ.get("DISPATCH_POLICY", DispatchPolicyConst.NEVER) m = marshaller.NewDefaultHTTPMarshaller() event = m.FromRequest(v1.Event(), request.headers, io.BytesIO(request.data), lambda x: json.load(x)) event_info = event.Properties() event_info.update(event_info.pop("extensions")) event_data = event_info.pop("data") app.logger.debug("RCVR: {}".format(event_data)) type = event_info.get("type") subject = event_info.get("subject", "sys-0") g.subjects = [] # TODO: important!! # need to find a way to avoid a return of messages from the same service # (for example when resending it again after intercepted in the first time) # this workaround only works when in a knative service or at least when SOURCE environment # variable is set if event_info["source"] == os.environ.get("K_SERVICE", os.environ.get("SOURCE")): return Response(status=201) event_info["originid"] = event_info.get("originid", event_info.get("id")) logger.debug("subject: {}".format(subject)) logger.debug("event_data: {}".format(event_data)) from dependency_injector import providers subject = subject_factory(name=subject, event_info=event_info, event_data=event_data) event_data["_event_info"] = event_info # TODO: KRUL-155 try: event_router_factory().route(type, subject, event_data, dispatch_policy=dispatch_policy) finally: for sub in g.subjects: sub.store() exec_time = (datetime.now() - start_time).total_seconds() logger.info( "Event", extra={ 'props': { 'event_info': event_info, 'type': type, 'subject': subject.name, 'exec_time': exec_time, #'headers': list(headers.keys()) } }) return Response(status=200) except Exception as ex: app.logger.error(ex, exc_info=True) return Response(status=201)
rulename: "on-csv-upload-import-devices", subscribe_to: "google.storage.object.finalize", ruledata: { filters: [ SubjectMatch("onboarding/import/(?P<deviceclass>.+)/(?P<filename>.+)", payload_dest="path_info"), CheckPayloadPropertyValue("contentType", "text/csv"), ], processing: [ ProcessCSV_AsDict( driver=GoogleStorageDriver, bucket=_(lambda _self: _self.payload["bucket"]), path=_(lambda _self: _self.payload["name"]), func=lambda device_data, _self: ( message_router_factory().route( "onboard-device", subject_factory(device_data.pop("deviceid"), event_info=_self.subject.event_info()), { "data": device_data, "class": _self.payload["path_info"]["deviceclass"] }), ) ) ], } }, """ Catch csv upload errors, reject file """, { rulename: 'on-csv-upload-import-devices-error',
def subject(): global counter counter += 1 return subject_factory('test-subject-{0}'.format(counter)).flush()
def k8s_subject(obj): return subject_factory("k8s:{}".format(obj["metadata"]["selfLink"]), event_data=obj)
def test_factory(): from krules_core.providers import subject_factory test_subject = subject_factory("test-subject") assert test_subject.name == "test-subject"
def subject(): from krules_core.providers import subject_factory global counter counter += 1 return subject_factory('test-subject-{0}'.format(counter)).flush()
upsert=True) ]) ] }, }, """ Do schedules """, { rulename: "on-tick-do-schedules", subscribe_to: "krules.heartbeat", ruledata: { processing: [ SetPayloadProperty("_ids", []), WithDatabase(DATABASE), WithCollection(COLLECTION, indexes=INDEXES), MongoDBFind( lambda self: {"_when": { "$lt": datetime.now() }}, # query lambda x, self: ( # foreach message_router_factory().route( x["message"], subject_factory(x["subject"]), x[ "payload"]), self.payload["_ids"].append( str(x["_id"]))), ), MongoDBDeleteByIds(payload_from="_ids") ] } }, ]
def test_set_get_del(subject): from krules_core.providers import subject_factory, subject_storage_factory subject.flush() # store nothing subject.store() global _test_events _test_events = [] # USE CACHE (default) subject.set("my-prop", 1) assert subject.get("my-prop") == 1 # not yet stored subject_copy = subject_factory(subject.name) with pytest.raises(AttributeError): subject_copy.get("my-prop") subject.store() subject_copy = subject_factory(subject.name) if subject_storage_factory(subject_copy.name).is_persistent(): assert subject_copy.get("my-prop") == 1 # callables new_value, old_value = subject.set("my-prop", lambda x: x + 2) assert new_value == 3 and old_value == 1 new_value, old_value = subject.set("my-prop-2", lambda x: x is None and 1 or x + 2) assert new_value == 1 and old_value is None # events assert len(_test_events) == 3 from krules_core import event_types # type assert _test_events[0][0] == _test_events[1][0] == _test_events[2][ 0] == event_types.SUBJECT_PROPERTY_CHANGED # subject assert _test_events[0][1].name == _test_events[1][1].name == _test_events[ 2][1].name == subject.name # payload payload = _test_events[0][2] assert payload[PayloadConst.PROPERTY_NAME] == "my-prop" and payload[PayloadConst.OLD_VALUE] is None \ and payload[PayloadConst.VALUE] == 1 payload = _test_events[1][2] assert payload[PayloadConst.PROPERTY_NAME] == "my-prop" and payload[PayloadConst.OLD_VALUE] == 1 \ and payload[PayloadConst.VALUE] == 3 payload = _test_events[2][2] assert payload[PayloadConst.PROPERTY_NAME] == "my-prop-2" and payload[PayloadConst.OLD_VALUE] is None \ and payload[PayloadConst.VALUE] == 1 # old the same with extended properties except that they are mute _test_events = [] subject.set_ext("my-prop", 1) assert subject.get_ext("my-prop") == 1 # not yet stored subject_copy = subject_factory(subject.name) with pytest.raises(AttributeError): subject_copy.get_ext("my-prop") subject.store() if subject_storage_factory(subject.name).is_persistent(): subject_copy = subject_factory(subject.name) assert subject_copy.get_ext("my-prop") == 1 # callables new_value, old_value = subject.set_ext("my-prop", lambda x: x + 2) assert new_value == 3 and old_value == 1 new_value, old_value = subject.set_ext("my-prop-2", lambda x: x is None and 1 or x + 2) assert new_value == 1 and old_value is None # events assert len(_test_events) == 0 # muted val, _ = subject.set("my-prop", "silent", muted=True) assert val == "silent" and len(_test_events) == 0 # NO CACHE subject.set("my-prop", 0, use_cache=False) # not calling store if subject_storage_factory(subject.name).is_persistent(): subject = subject_factory(subject.name) val = subject.get("my-prop", use_cache=False) assert val == 0 # with callables val, old_val = subject.set("my-prop", lambda x: x + 5, use_cache=False) assert old_val == 0 and val == 5 # events produced assert len(_test_events) == 2 # same with exts _test_events = [] subject.set_ext("my-prop", 0, use_cache=False) # not calling store if subject_storage_factory(subject.name).is_persistent(): subject = subject_factory(subject.name) val = subject.get_ext("my-prop", use_cache=False) assert val == 0 # with callables val, old_val = subject.set_ext("my-prop", lambda x: x + 5, use_cache=False) assert old_val == 0 and val == 5 # events NOT produced assert len(_test_events) == 0 # with cached if subject_storage_factory(subject.name).is_persistent(): subject = subject_factory(subject.name) val = subject.get("my-prop") assert val == 5 # prop cached subject.set("my-prop", 1, use_cache=False) val = subject.get("my-prop") # from cache assert val == 1 subject.store() # update cache subject = subject_factory(subject.name) val = subject.get("my-prop") assert val == 1 # prop cached subject.set("my-prop", 8, use_cache=True) val = subject.get("my-prop", use_cache=False) # update cache assert val == 1 val = subject.get("my-prop", use_cache=True) assert val == 1 subject.store() # deletes _test_events = [] # cache not loaded yet subject.delete("my-prop", use_cache=False) assert len(_test_events) == 1 and \ _test_events[0][0] == event_types.SUBJECT_PROPERTY_DELETED and \ _test_events[0][1].name == subject.name and \ _test_events[0][2][PayloadConst.PROPERTY_NAME] == "my-prop" with pytest.raises(AttributeError): subject.get("my-prop") with pytest.raises(AttributeError): subject.delete("my-prop") # add prop bypassing cache subject.set("my-prop", 0, use_cache=False) subject.delete("my-prop", use_cache=True) subject.store() with pytest.raises(AttributeError): subject.get("my-prop") # add prop in cache remove directly subject.set("my-prop", 0, use_cache=True) subject.delete("my-prop", use_cache=False) subject.store() with pytest.raises(AttributeError): subject.get("my-prop") # all in cache subject.set("my-prop", 0, use_cache=True) subject.delete("my-prop", use_cache=True) subject.store() with pytest.raises(AttributeError): subject.get("my-prop") # no cache subject.set("my-prop", 0, use_cache=False) subject.delete("my-prop", use_cache=False) subject.store() with pytest.raises(AttributeError): subject.get("my-prop")
def execute(self, prop, expected_value): if not subject_storage_factory( self.subject.name).is_concurrency_safe(): return True # skip test subject = subject_factory(self.subject.name) return subject.get(prop, cached=False) == expected_value