Files
Sheerka-Old/tests/core/test_SheerkaComparisonManager.py
T

484 lines
23 KiB
Python

import pytest
from core.builtin_concepts import BuiltinConcepts
from core.concept import Concept
from core.global_symbols import CONCEPT_PRECEDENCE_MODIFIED, CONCEPT_COMPARISON_CONTEXT, RULE_PRECEDENCE_MODIFIED, \
RULE_COMPARISON_CONTEXT
from core.sheerka.services.SheerkaComparisonManager import SheerkaComparisonManager, ComparisonObj
from tests.TestUsingMemoryBasedSheerka import TestUsingMemoryBasedSheerka
class TestSheerkaGreaterThanManager(TestUsingMemoryBasedSheerka):
@staticmethod
def execution_definition(context, service, concepts_map, definition):
if ">>" in definition:
a = concepts_map[definition.split(">>")[0].strip()]
return service.set_is_greatest(context, "prop_name", a)
if "<<" in definition:
a = concepts_map[definition.split("<<")[0].strip()]
return service.set_is_lesser(context, "prop_name", a)
if ">" in definition:
a, b = [concepts_map[e.strip()] for e in definition.split(">")]
return service.set_is_greater_than(context, "prop_name", a, b)
if "<" in definition:
a, b = [concepts_map[e.strip()] for e in definition.split("<")]
return service.set_is_less_than(context, "prop_name", a, b)
def test_i_can_add_a_is_greater_than(self):
sheerka, context, one, two = self.init_concepts("one", "two", cache_only=False)
service = sheerka.services[SheerkaComparisonManager.NAME]
res = service.set_is_greater_than(context, "prop_name", two, one)
assert res.status
assert sheerka.isinstance(res.body, BuiltinConcepts.SUCCESS)
in_cache = sheerka.cache_manager.get(SheerkaComparisonManager.COMPARISON_ENTRY, "prop_name|#")
assert in_cache == [ComparisonObj(context.event.get_digest(), "prop_name", two.str_id, one.str_id, ">", "#")]
weighted = sheerka.cache_manager.get(SheerkaComparisonManager.RESOLVED_COMPARISON_ENTRY, "prop_name|#")
assert weighted == {"c:one|1001:": 1, "c:two|1002:": 2}
# I can commit
sheerka.cache_manager.commit(context)
in_db = sheerka.sdp.get(SheerkaComparisonManager.COMPARISON_ENTRY, "prop_name|#")
assert in_db == [ComparisonObj(context.event.get_digest(), "prop_name", two.str_id, one.str_id, ">", "#")]
def test_i_can_add_is_greater_than_for_rules(self):
sheerka, context, r1, r2 = self.init_format_rules(("True", "true"), ("False", "false"),
cache_only=False,
compile_rule=False)
service = sheerka.services[SheerkaComparisonManager.NAME]
res = service.set_is_greater_than(context, "prop_name", r2, r1)
assert res.status
assert sheerka.isinstance(res.body, BuiltinConcepts.SUCCESS)
in_cache = sheerka.cache_manager.get(SheerkaComparisonManager.COMPARISON_ENTRY, "prop_name|#")
assert in_cache == [ComparisonObj(context.event.get_digest(), "prop_name", r2.str_id, r1.str_id, ">", "#")]
weighted = sheerka.cache_manager.get(SheerkaComparisonManager.RESOLVED_COMPARISON_ENTRY, "prop_name|#")
assert weighted == {"r:|1:": 1, "r:|2:": 2}
# I can commit
sheerka.cache_manager.commit(context)
in_db = sheerka.sdp.get(SheerkaComparisonManager.COMPARISON_ENTRY, "prop_name|#")
assert in_db == [ComparisonObj(context.event.get_digest(), "prop_name", r2.str_id, r1.str_id, ">", "#")]
def test_i_can_add_a_is_less_than(self):
sheerka, context, one, two = self.init_concepts("one", "two", cache_only=False)
service = sheerka.services[SheerkaComparisonManager.NAME]
res = service.set_is_less_than(context, "prop_name", one, two)
assert res.status
assert sheerka.isinstance(res.body, BuiltinConcepts.SUCCESS)
in_cache = sheerka.cache_manager.get(SheerkaComparisonManager.COMPARISON_ENTRY, "prop_name|#")
assert in_cache == [ComparisonObj(context.event.get_digest(), "prop_name", one.str_id, two.str_id, "<", "#")]
weighted = sheerka.cache_manager.get(SheerkaComparisonManager.RESOLVED_COMPARISON_ENTRY, "prop_name|#")
assert weighted == {"c:one|1001:": 1, "c:two|1002:": 2}
# I can commit
sheerka.cache_manager.commit(context)
in_db = sheerka.sdp.get(SheerkaComparisonManager.COMPARISON_ENTRY, "prop_name|#")
assert in_db == [ComparisonObj(context.event.get_digest(), "prop_name", one.str_id, two.str_id, "<", "#")]
def test_i_can_add_is_less_than_for_rules(self):
sheerka, context, r1, r2 = self.init_format_rules(("True", "true"), ("False", "false"),
cache_only=False,
compile_rule=False)
service = sheerka.services[SheerkaComparisonManager.NAME]
res = service.set_is_less_than(context, "prop_name", r1, r2)
assert res.status
assert sheerka.isinstance(res.body, BuiltinConcepts.SUCCESS)
in_cache = sheerka.cache_manager.get(SheerkaComparisonManager.COMPARISON_ENTRY, "prop_name|#")
assert in_cache == [ComparisonObj(context.event.get_digest(), "prop_name", r1.str_id, r2.str_id, "<", "#")]
weighted = sheerka.cache_manager.get(SheerkaComparisonManager.RESOLVED_COMPARISON_ENTRY, "prop_name|#")
assert weighted == {"r:|1:": 1, "r:|2:": 2}
# I can commit
sheerka.cache_manager.commit(context)
in_db = sheerka.sdp.get(SheerkaComparisonManager.COMPARISON_ENTRY, "prop_name|#")
assert in_db == [ComparisonObj(context.event.get_digest(), "prop_name", r1.str_id, r2.str_id, "<", "#")]
def test_i_can_add_multiples_constraints(self):
sheerka, context, one, two, three, four = self.init_concepts("one", "two", "three", "four", cache_only=False)
service = sheerka.services[SheerkaComparisonManager.NAME]
service.set_is_greater_than(context, "prop_name", two, one)
service.set_is_greater_than(context, "prop_name", three, two)
in_cache = sheerka.cache_manager.get(SheerkaComparisonManager.COMPARISON_ENTRY, "prop_name|#")
assert in_cache == [
ComparisonObj(context.event.get_digest(), "prop_name", two.str_id, one.str_id, ">", "#"),
ComparisonObj(context.event.get_digest(), "prop_name", three.str_id, two.str_id, ">", "#")
]
# I can commit
sheerka.cache_manager.commit(context)
in_db = sheerka.sdp.get(SheerkaComparisonManager.COMPARISON_ENTRY, "prop_name|#")
assert in_db == [
ComparisonObj(context.event.get_digest(), "prop_name", two.str_id, one.str_id, ">", "#"),
ComparisonObj(context.event.get_digest(), "prop_name", three.str_id, two.str_id, ">", "#")
]
sheerka.cache_manager.clear(SheerkaComparisonManager.COMPARISON_ENTRY) # reset the cache
service.set_is_greater_than(context, "prop_name", four, three)
in_cache = sheerka.cache_manager.get(SheerkaComparisonManager.COMPARISON_ENTRY, "prop_name|#")
assert in_cache == [
ComparisonObj(context.event.get_digest(), "prop_name", two.str_id, one.str_id, ">", "#"),
ComparisonObj(context.event.get_digest(), "prop_name", three.str_id, two.str_id, ">", "#"),
ComparisonObj(context.event.get_digest(), "prop_name", four.str_id, three.str_id, ">", "#"),
]
weighted = sheerka.cache_manager.get(SheerkaComparisonManager.RESOLVED_COMPARISON_ENTRY, "prop_name|#")
assert weighted == {"c:one|1001:": 1, "c:two|1002:": 2, "c:three|1003:": 3, "c:four|1004:": 4}
def test_i_can_add_multiple_constraints_2(self):
sheerka, context, one, two, three = self.init_concepts("one", "two", "three")
service = sheerka.services[SheerkaComparisonManager.NAME]
service.set_is_greater_than(context, "prop_name", two, one)
service.set_is_greater_than(context, "prop_name", three, two)
weighted = sheerka.cache_manager.get(SheerkaComparisonManager.RESOLVED_COMPARISON_ENTRY, "prop_name|#")
assert weighted == {"c:one|1001:": 1, "c:two|1002:": 2, "c:three|1003:": 3}
service.set_is_greater_than(context, "prop_name", three, one) # should not change order
weighted = sheerka.cache_manager.get(SheerkaComparisonManager.RESOLVED_COMPARISON_ENTRY, "prop_name|#")
assert weighted == {"c:one|1001:": 1, "c:two|1002:": 2, "c:three|1003:": 3}
def test_i_lesser_than_and_opposite_greater_than(self):
sheerka, context, one, two = self.init_concepts("one", "two")
service = sheerka.services[SheerkaComparisonManager.NAME]
service.set_is_greater_than(context, "prop_name", two, one)
service.set_is_less_than(context, "prop_name", one, two)
weighted = sheerka.cache_manager.get(SheerkaComparisonManager.RESOLVED_COMPARISON_ENTRY, "prop_name|#")
assert weighted == {"c:one|1001:": 1, "c:two|1002:": 2}
@pytest.mark.parametrize("entries, expected", [
(["two > one"], {'c:one|1001:': 1, 'c:two|1002:': 2}),
(["one < two"], {'c:one|1001:': 1, 'c:two|1002:': 2}),
(["three > two", "one < two"], {'c:one|1001:': 1, 'c:two|1002:': 2, 'c:three|1003:': 3}),
(["three > one", "one < two"], {'c:one|1001:': 1, 'c:two|1002:': 2, 'c:three|1003:': 2}),
(["three >>"], {'c:three|1003:': 2}),
(["one <<"], {'c:one|1001:': 0}),
])
def test_i_can_get_concept_weight(self, entries, expected):
sheerka, context, *concepts = self.init_concepts("one", "two", "three")
service = sheerka.services[SheerkaComparisonManager.NAME]
concepts_map = dict(zip(["one", "two", "three"], concepts))
for entry in entries:
self.execution_definition(context, service, concepts_map, entry)
assert service.get_concepts_weights("prop_name") == expected
def test_i_can_get_concept_weight_when_no_comparison_is_defined(self):
sheerka, context = self.init_concepts()
service = sheerka.services[SheerkaComparisonManager.NAME]
assert service.get_concepts_weights("prop_name") == {}
def test_i_can_recover_from_deleted_weight(self):
sheerka, context, one = self.init_concepts("one")
service = sheerka.services[SheerkaComparisonManager.NAME]
service.set_is_lesser(context, "prop_name", one)
sheerka.cache_manager.clear(service.RESOLVED_COMPARISON_ENTRY)
assert service.get_concepts_weights("prop_name") == {"c:one|1001:": 0}
def test_i_can_get_partition(self):
sheerka, context, one, two, three = self.init_concepts("one", "two", "three")
service = sheerka.services[SheerkaComparisonManager.NAME]
service.set_is_greater_than(context, "prop_name", two, one)
service.set_is_less_than(context, "prop_name", two, three)
res = service.get_partition("prop_name")
assert res == {
1: ["c:one|1001:"],
2: ["c:two|1002:"],
3: ["c:three|1003:"],
}
def test_i_can_detect_chicken_and_egg(self):
sheerka, context, one, two = self.init_concepts("one", "two")
service = sheerka.services[SheerkaComparisonManager.NAME]
service.set_is_greater_than(context, "prop_name", two, one)
res = service.set_is_greater_than(context, "prop_name", one, two)
assert not res.status
assert sheerka.isinstance(res.body, BuiltinConcepts.CHICKEN_AND_EGG)
assert set(res.body.body) == {one, two}
def test_i_can_detect_more_complex_chicken_and_egg(self):
sheerka, context, one, two, three, four, five = self.init_concepts("one", "two", "three", "four", "five")
service = sheerka.services[SheerkaComparisonManager.NAME]
service.set_is_greater_than(context, "prop_name", two, one)
service.set_is_greater_than(context, "prop_name", five, four)
service.set_is_greater_than(context, "prop_name", four, three)
service.set_is_greater_than(context, "prop_name", five, two)
res = service.set_is_greater_than(context, "prop_name", one, five)
assert not res.status
assert sheerka.isinstance(res.body, BuiltinConcepts.CHICKEN_AND_EGG)
assert set(res.body.body) == {one, two, five}
def test_i_can_give_the_same_information_in_many_ways(self):
sheerka, context, one, two = self.init_concepts("one", "two")
service = sheerka.services[SheerkaComparisonManager.NAME]
service.set_is_greater_than(context, "prop_name", two, one)
service.set_is_less_than(context, "prop_name", one, two)
weighted = sheerka.cache_manager.get(SheerkaComparisonManager.RESOLVED_COMPARISON_ENTRY, "prop_name|#")
assert weighted == {"c:one|1001:": 1, "c:two|1002:": 2}
def test_methods_are_correctly_bound(self):
sheerka, context, one, two = self.init_concepts("one", "two")
res = sheerka.set_is_greater_than(context, "prop_name", two, one)
assert res.status
def test_a_lesser_concept_has_the_lowest_weight(self):
sheerka, context, one, two, three = self.init_concepts("one", "two", "three", cache_only=False)
service = sheerka.services[SheerkaComparisonManager.NAME]
service.set_is_lesser(context, "prop_name", one)
assert service.get_concepts_weights("prop_name") == {"c:one|1001:": 0} # DEFAULT_COMPARISON_VALUE - 1
sheerka.set_is_greater_than(context, "prop_name", three, two)
assert service.get_concepts_weights("prop_name") == {"c:one|1001:": 0, "c:two|1002:": 1, "c:three|1003:": 2}
# I can commit
sheerka.cache_manager.commit(context)
in_db = sheerka.sdp.get(SheerkaComparisonManager.COMPARISON_ENTRY, "prop_name|#")
assert in_db == [
ComparisonObj(context.event.get_digest(), "prop_name", one.str_id, None, "<<", "#"),
ComparisonObj(context.event.get_digest(), "prop_name", three.str_id, two.str_id, ">", "#")
]
def test_i_can_define_an_order_for_lesser_concepts(self):
sheerka, context, lesser, less_l, even_more_l = self.init_concepts("lesser", "less_l", "even_less_l")
service = sheerka.services[SheerkaComparisonManager.NAME]
service.set_is_lesser(context, "prop_name", lesser)
service.set_is_lesser(context, "prop_name", less_l)
service.set_is_lesser(context, "prop_name", even_more_l)
sheerka.set_is_less_than(context, "prop_name", less_l, lesser)
sheerka.set_is_greater_than(context, "prop_name", less_l, even_more_l)
assert service.get_concepts_weights("prop_name") == {"c:lesser|1001:": 0,
"c:less_l|1002:": -1,
"c:even_less_l|1003:": -2}
def test_i_cannot_define_less_than_a_lesser_if_not_a_lesser_itself(self):
"""
minus_one cannot be defined as less that one is one is defined as lesser
unless minus_one is defined as lesser itself
:return:
"""
sheerka, context, lesser, foo = self.init_concepts("lesser", "foo")
service = sheerka.services[SheerkaComparisonManager.NAME]
service.set_is_lesser(context, "prop_name", lesser)
res = sheerka.set_is_less_than(context, "prop_name", foo, lesser)
assert not res.status
assert sheerka.isinstance(res.body, BuiltinConcepts.INVALID_LESSER_OPERATION)
res = sheerka.set_is_greater_than(context, "prop_name", foo, lesser)
assert not res.status
assert sheerka.isinstance(res.body, BuiltinConcepts.INVALID_LESSER_OPERATION)
def test_a_greatest_concept_has_the_highest_weight(self):
sheerka, context, one, two, three = self.init_concepts("one", "two", "three")
service = sheerka.services[SheerkaComparisonManager.NAME]
service.set_is_greatest(context, "prop_name", three)
assert service.get_concepts_weights("prop_name") == {"c:three|1003:": 2} # DEFAULT_COMPARISON_VALUE + 1
sheerka.set_is_greater_than(context, "prop_name", two, one)
assert service.get_concepts_weights("prop_name") == {"c:one|1001:": 1, "c:two|1002:": 2, "c:three|1003:": 3}
def test_i_cannot_define_greater_than_a_greatest_if_not_a_greater_itself(self):
sheerka, context, greatest, foo = self.init_concepts("greatest", "foo")
service = sheerka.services[SheerkaComparisonManager.NAME]
service.set_is_greatest(context, "prop_name", greatest)
res = sheerka.set_is_less_than(context, "prop_name", foo, greatest)
assert not res.status
assert sheerka.isinstance(res.body, BuiltinConcepts.INVALID_GREATEST_OPERATION)
res = sheerka.set_is_greater_than(context, "prop_name", foo, greatest)
assert not res.status
assert sheerka.isinstance(res.body, BuiltinConcepts.INVALID_GREATEST_OPERATION)
@pytest.mark.parametrize("definitions, expected", [
(["foo >>", "foo <<"], BuiltinConcepts.INVALID_GREATEST_OPERATION),
(["foo <<", "foo >>"], BuiltinConcepts.INVALID_LESSER_OPERATION),
])
def test_i_cannot_define_a_concept_as_lesser_and_greatest_at_the_same_time(self, definitions, expected):
sheerka, context, foo = self.init_concepts("foo")
service = sheerka.services[SheerkaComparisonManager.NAME]
concepts_map = {"foo": foo}
self.execution_definition(context, service, concepts_map, definitions[0])
res = self.execution_definition(context, service, concepts_map, definitions[1])
assert not res.status
assert sheerka.isinstance(res.body, expected)
def test_i_can_define_an_order_for_greatest_concepts(self):
sheerka, context, greatest, more_g, even_more_g = self.init_concepts("greatest", "more_g", "even_more_g")
service = sheerka.services[SheerkaComparisonManager.NAME]
service.set_is_greatest(context, "prop_name", greatest)
service.set_is_greatest(context, "prop_name", more_g)
service.set_is_greatest(context, "prop_name", even_more_g)
sheerka.set_is_less_than(context, "prop_name", greatest, more_g)
sheerka.set_is_greater_than(context, "prop_name", even_more_g, more_g)
assert service.get_concepts_weights("prop_name") == {"c:greatest|1001:": 2,
"c:more_g|1002:": 3,
"c:even_more_g|1003:": 4}
def test_i_can_mix_all_comparisons(self):
sheerka, context, one, two, three, four, five, six, three_and_half = self.init_concepts(
"one", "two", "three", "four", "five", "six", "two_and_half")
service = sheerka.services[SheerkaComparisonManager.NAME]
service.set_is_lesser(context, "prop_name", one)
service.set_is_lesser(context, "prop_name", two)
sheerka.set_is_less_than(context, "prop_name", one, two)
service.set_is_greatest(context, "prop_name", five)
service.set_is_greatest(context, "prop_name", six)
sheerka.set_is_greater_than(context, "prop_name", six, five)
sheerka.set_is_less_than(context, "prop_name", three, four)
assert service.get_concepts_weights("prop_name") == {
"c:one|1001:": -1,
"c:two|1002:": 0,
"c:three|1003:": 1,
"c:four|1004:": 2,
"c:five|1005:": 3,
"c:six|1006:": 4
}
sheerka.set_is_less_than(context, "prop_name", three_and_half, four)
sheerka.set_is_greater_than(context, "prop_name", three_and_half, three)
assert service.get_concepts_weights("prop_name") == {
"c:one|1001:": -1,
"c:two|1002:": 0,
"c:three|1003:": 1,
"c:two_and_half|1007:": 2,
"c:four|1004:": 3,
"c:five|1005:": 4,
"c:six|1006:": 5
}
def test_i_can_mix_all_comparisons_2(self):
sheerka, context, zero, one, two, three, four, five, thousand = self.init_concepts(
"zero", "one", "two", "three", "four", "five", "thousand")
service = sheerka.services[SheerkaComparisonManager.NAME]
service.set_is_greater_than(context, "prop_name", four, one)
service.set_is_less_than(context, "prop_name", one, five)
service.set_is_less_than(context, "prop_name", one, three)
service.set_is_less_than(context, "prop_name", two, three)
service.set_is_greater_than(context, "prop_name", two, one)
service.set_is_greater_than(context, "prop_name", five, four)
service.set_is_less_than(context, "prop_name", three, four)
service.set_is_greatest(context, "prop_name", thousand)
service.set_is_lesser(context, "prop_name", zero)
service.set_is_less_than(context, "prop_name", two, five)
service.set_is_less_than(context, "prop_name", two, four)
service.set_is_greater_than(context, "prop_name", five, one)
service.set_is_greater_than(context, "prop_name", five, three)
assert service.get_concepts_weights("prop_name") == {
"c:zero|1001:": 0,
"c:one|1002:": 1,
"c:two|1003:": 2,
"c:three|1004:": 3,
"c:four|1005:": 4,
"c:five|1006:": 5,
"c:thousand|1007:": 6
}
@pytest.mark.parametrize("definition", [
"one >>",
"one <<",
"one > two",
"one < two",
])
def test_i_cannot_add_the_same_definition_twice(self, definition):
sheerka, context, *concepts = self.init_concepts("one", "two")
service = sheerka.services[SheerkaComparisonManager.NAME]
concepts_map = dict(zip(["one", "two"], concepts))
self.execution_definition(context, service, concepts_map, definition)
res = self.execution_definition(context, service, concepts_map, definition)
assert not res.status
assert sheerka.isinstance(res.body, BuiltinConcepts.CONCEPT_ALREADY_DEFINED)
def test_an_event_is_fired_when_modifying_concepts_precedence(self):
sheerka, context, one, two, foo = self.init_concepts("one", "two", "foo")
event_received = False
def receive_event(c):
nonlocal event_received
event_received = True
sheerka.subscribe(CONCEPT_PRECEDENCE_MODIFIED, receive_event)
sheerka.set_is_greater_than(context, foo, one, two)
assert not event_received
sheerka.set_is_greater_than(context, BuiltinConcepts.PRECEDENCE, foo, one, two)
assert not event_received
sheerka.set_is_greater_than(context, BuiltinConcepts.PRECEDENCE, one, two, CONCEPT_COMPARISON_CONTEXT)
assert event_received
def test_an_event_is_fired_when_modifying_rule_precedence(self):
sheerka, context, r1, r2 = self.init_format_rules(
("True", "True"),
("False", "False"),
compile_rule=False,
)
foo = Concept("foo")
event_received = False
sheerka.cache_manager.clear(SheerkaComparisonManager.COMPARISON_ENTRY)
def receive_event(c):
nonlocal event_received
event_received = True
sheerka.subscribe(RULE_PRECEDENCE_MODIFIED, receive_event)
sheerka.set_is_greater_than(context, foo, r1, r2)
assert not event_received
sheerka.set_is_greater_than(context, BuiltinConcepts.PRECEDENCE, foo, r1, r2)
assert not event_received
sheerka.set_is_greater_than(context, BuiltinConcepts.PRECEDENCE, r1, r2, RULE_COMPARISON_CONTEXT)
assert event_received