283 lines
11 KiB
Python
283 lines
11 KiB
Python
import pytest
|
|
import os
|
|
|
|
from core.builtin_concepts import BuiltinConcepts, ReturnValueConcept, UserInputConcept
|
|
from core.concept import Concept, PROPERTIES_TO_SERIALIZE
|
|
from core.sheerka.Sheerka import Sheerka
|
|
|
|
from tests.TestUsingFileBasedSheerka import TestUsingFileBasedSheerka
|
|
|
|
|
|
class ConceptWithGetValue(Concept):
|
|
def get_value(self):
|
|
return self.get_prop("my_prop")
|
|
|
|
|
|
class TestSheerka(TestUsingFileBasedSheerka):
|
|
|
|
def test_root_folder_is_created_after_initialization(self):
|
|
return_value = Sheerka().initialize(self.root_folder)
|
|
assert return_value.status, "initialisation should be successful"
|
|
assert os.path.exists(self.root_folder), "init folder should be created"
|
|
|
|
def test_i_can_list_builtin_concepts(self):
|
|
sheerka = self.get_sheerka()
|
|
builtins = list(sheerka.get_builtins_classes_as_dict())
|
|
|
|
assert str(BuiltinConcepts.ERROR) in builtins
|
|
assert str(BuiltinConcepts.RETURN_VALUE) in builtins
|
|
|
|
def test_builtin_concepts_are_initialized(self):
|
|
sheerka = self.get_sheerka(skip_builtins_in_db=False)
|
|
assert len(sheerka.cache_by_key) == len(BuiltinConcepts)
|
|
for concept_name in BuiltinConcepts:
|
|
assert str(concept_name) in sheerka.cache_by_key
|
|
assert sheerka.sdp.get_safe(sheerka.CONCEPTS_ENTRY, str(concept_name)) is not None
|
|
|
|
for key, concept_class in sheerka.get_builtins_classes_as_dict().items():
|
|
assert isinstance(sheerka.cache_by_key[key], concept_class)
|
|
|
|
def test_builtin_concepts_can_be_updated(self):
|
|
sheerka = self.get_sheerka(False, False)
|
|
loaded_sheerka = sheerka.get(BuiltinConcepts.SHEERKA)
|
|
loaded_sheerka.metadata.desc = "I have a description"
|
|
sheerka.sdp.modify("Test", sheerka.CONCEPTS_ENTRY, loaded_sheerka.key, loaded_sheerka)
|
|
|
|
sheerka = self.get_sheerka(False, False)
|
|
loaded_sheerka = sheerka.get(BuiltinConcepts.SHEERKA)
|
|
|
|
assert loaded_sheerka.metadata.desc == "I have a description"
|
|
|
|
def test_i_can_get_a_builtin_concept_by_their_enum_or_the_string(self):
|
|
"""
|
|
Checks that a concept can be found its name
|
|
even when there are variables in the name (ex 'hello + a' or 'a + b' )
|
|
:return:
|
|
"""
|
|
sheerka = self.get_sheerka()
|
|
for key in sheerka.get_builtins_classes_as_dict():
|
|
assert sheerka.get(key) is not None
|
|
assert sheerka.get(str(key)) is not None
|
|
|
|
def test_i_cannot_get_when_key_is_none(self):
|
|
sheerka = self.get_sheerka()
|
|
|
|
res = sheerka.get(None)
|
|
assert sheerka.isinstance(res, BuiltinConcepts.ERROR)
|
|
assert res.body == "Concept key is undefined."
|
|
|
|
def test_unknown_concept_is_return_when_the_concept_key_is_not_found(self):
|
|
sheerka = self.get_sheerka()
|
|
|
|
loaded = sheerka.get("key_that_does_not_exist")
|
|
|
|
assert loaded is not None
|
|
assert sheerka.isinstance(loaded, BuiltinConcepts.UNKNOWN_CONCEPT)
|
|
assert loaded.body == ("key", "key_that_does_not_exist")
|
|
assert loaded.metadata.is_evaluated
|
|
|
|
def test_unknown_concept_is_return_when_the_concept_id_is_not_found(self):
|
|
sheerka = self.get_sheerka()
|
|
|
|
loaded = sheerka.get_by_id("id_that_does_not_exist")
|
|
|
|
assert loaded is not None
|
|
assert sheerka.isinstance(loaded, BuiltinConcepts.UNKNOWN_CONCEPT)
|
|
assert loaded.body == ("id", "id_that_does_not_exist")
|
|
assert loaded.metadata.is_evaluated
|
|
|
|
def test_i_can_instantiate_a_builtin_concept_when_it_has_its_own_class(self):
|
|
sheerka = self.get_sheerka()
|
|
ret = sheerka.new(BuiltinConcepts.RETURN_VALUE, who="who", status="status", value="value", message="message")
|
|
|
|
assert isinstance(ret, ReturnValueConcept)
|
|
assert ret.key == str(BuiltinConcepts.RETURN_VALUE)
|
|
assert ret.who == "who"
|
|
assert ret.status == "status"
|
|
assert ret.value == "value"
|
|
assert ret.message == "message"
|
|
|
|
def test_i_can_instantiate_a_builtin_concept_when_no_specific_class(self):
|
|
sheerka = self.get_sheerka()
|
|
ret = sheerka.new(BuiltinConcepts.UNKNOWN_CONCEPT, body="fake_concept")
|
|
|
|
assert isinstance(ret, Concept)
|
|
assert ret.key == str(BuiltinConcepts.UNKNOWN_CONCEPT)
|
|
assert ret.body == "fake_concept"
|
|
|
|
def test_i_can_instantiate_a_concept(self):
|
|
sheerka = self.get_sheerka()
|
|
concept = self.get_default_concept()
|
|
sheerka.create_new_concept(self.get_context(sheerka), concept)
|
|
|
|
new = sheerka.new(concept.key, a=10, b="value")
|
|
|
|
assert sheerka.isinstance(new, concept)
|
|
for prop in PROPERTIES_TO_SERIALIZE:
|
|
assert getattr(new.metadata, prop) == getattr(concept.metadata, prop)
|
|
|
|
assert new.props["a"].value == 10
|
|
assert new.props["b"].value == "value"
|
|
|
|
def test_i_can_instantiate_with_the_name_and_the_id(self):
|
|
sheerka = self.get_sheerka()
|
|
sheerka.create_new_concept(self.get_context(sheerka), Concept("foo", body="foo1"))
|
|
sheerka.create_new_concept(self.get_context(sheerka), Concept("foo", body="foo2"))
|
|
|
|
concepts = sheerka.new("foo")
|
|
assert len(concepts) == 2
|
|
|
|
foo1 = sheerka.new(("foo", "1001"))
|
|
assert foo1.metadata.body == "foo1"
|
|
|
|
foo2 = sheerka.new(("foo", "1002"))
|
|
assert foo2.metadata.body == "foo2"
|
|
|
|
def test_instances_are_different_when_asking_for_new(self):
|
|
sheerka = self.get_sheerka()
|
|
concept = self.get_default_concept()
|
|
sheerka.create_new_concept(self.get_context(sheerka), concept)
|
|
|
|
new1 = sheerka.new(concept.key, a=10, b="value")
|
|
new2 = sheerka.new(concept.key, a=10, b="value")
|
|
|
|
assert new1 == new2
|
|
assert id(new1) != id(new2)
|
|
|
|
def test_i_get_the_same_instance_when_is_unique_is_true(self):
|
|
sheerka = self.get_sheerka()
|
|
concept = Concept(name="unique", is_unique=True)
|
|
sheerka.create_new_concept(self.get_context(sheerka), concept)
|
|
|
|
new1 = sheerka.new(concept.key, a=10, b="value")
|
|
new2 = sheerka.new(concept.key, a=10, b="value")
|
|
|
|
assert new1 == new2
|
|
assert id(new1) == id(new2)
|
|
|
|
def test_i_cannot_instantiate_an_unknown_concept(self):
|
|
sheerka = self.get_sheerka()
|
|
|
|
new = sheerka.new("fake_concept")
|
|
|
|
assert sheerka.isinstance(new, BuiltinConcepts.UNKNOWN_CONCEPT)
|
|
assert new.body == ('key', 'fake_concept')
|
|
|
|
def test_i_cannot_instantiate_with_invalid_id(self):
|
|
sheerka = self.get_sheerka()
|
|
sheerka.create_new_concept(self.get_context(sheerka), Concept("foo", body="foo1"))
|
|
sheerka.create_new_concept(self.get_context(sheerka), Concept("foo", body="foo2"))
|
|
|
|
new = sheerka.new(("foo", "invalid_id"))
|
|
|
|
assert sheerka.isinstance(new, BuiltinConcepts.UNKNOWN_CONCEPT)
|
|
assert new.body == [('key', 'foo'), ('id', 'invalid_id')]
|
|
|
|
def test_i_cannot_instantiate_with_invalid_key(self):
|
|
sheerka = self.get_sheerka()
|
|
sheerka.create_new_concept(self.get_context(sheerka), Concept("foo", body="foo1"))
|
|
sheerka.create_new_concept(self.get_context(sheerka), Concept("foo", body="foo2"))
|
|
|
|
new = sheerka.new(("invalid_key", "1001"))
|
|
|
|
assert sheerka.isinstance(new, BuiltinConcepts.UNKNOWN_CONCEPT)
|
|
assert new.body == [('key', 'invalid_key'), ('id', '1001')]
|
|
|
|
def test_concept_id_is_irrelevant_when_only_one_concept(self):
|
|
sheerka = self.get_sheerka()
|
|
sheerka.create_new_concept(self.get_context(sheerka), Concept("foo", body="foo1"))
|
|
|
|
new = sheerka.new(("foo", "invalid_id"))
|
|
|
|
assert sheerka.isinstance(new, "foo")
|
|
assert new.metadata.body == "foo1"
|
|
|
|
def test_i_cannot_instantiate_when_properties_are_not_recognized(self):
|
|
sheerka = self.get_sheerka()
|
|
concept = self.get_default_concept()
|
|
sheerka.create_new_concept(self.get_context(sheerka), concept)
|
|
|
|
new = sheerka.new(concept.key, a=10, c="value")
|
|
|
|
assert sheerka.isinstance(new, BuiltinConcepts.UNKNOWN_PROPERTY)
|
|
assert new.property_name == "c"
|
|
assert sheerka.isinstance(new.concept, concept)
|
|
|
|
@pytest.mark.parametrize("concept, reduce_simple_list, expected", [
|
|
(None, False, None),
|
|
(3.14, False, 3.14),
|
|
("foo", False, "foo"),
|
|
(True, False, True),
|
|
(Concept("name", body="foo"), False, "foo"),
|
|
(Concept("name"), False, Concept("name")),
|
|
(ConceptWithGetValue("name").set_prop("my_prop", "my_value"), False, "my_value"),
|
|
(ReturnValueConcept(value="return_value"), False, "return_value"),
|
|
(ReturnValueConcept(value=Concept(key=BuiltinConcepts.USER_INPUT, body="text"), status=True), False, "text"),
|
|
(ReturnValueConcept(value=UserInputConcept("text"), status=True), False, "text"),
|
|
(Concept("name", body=["foo", "bar"]), False, ["foo", "bar"]),
|
|
(Concept("name", body=["foo"]), True, "foo"),
|
|
(Concept("name", body=Concept("foo")), False, Concept("foo")),
|
|
(Concept("name", body=Concept("foo", body="value")), False, "value"),
|
|
(Concept("name", body=Concept("foo", body=Concept("bar", body="value"))), False, "value"),
|
|
(Concept("name", body=Concept("foo", body=ReturnValueConcept(value="return_value"))), False, "return_value"),
|
|
])
|
|
def test_i_can_get_value(self, concept, reduce_simple_list, expected):
|
|
sheerka = self.get_sheerka()
|
|
|
|
# I use auto_init() instead of evaluate_concept() to be quicker
|
|
c = concept
|
|
while isinstance(c, Concept):
|
|
c.auto_init()
|
|
c = c.body
|
|
|
|
assert sheerka.value(concept, reduce_simple_list) == expected
|
|
|
|
def test_list_of_concept_is_sorted_by_id(self):
|
|
sheerka = self.get_sheerka(False, False)
|
|
concepts = sheerka.concepts()
|
|
|
|
assert concepts[0].id < concepts[-1].id
|
|
|
|
def test_builtin_error_concept_are_errors(self):
|
|
# only test a random one, it will be the same for the others
|
|
sheerka = self.get_sheerka()
|
|
assert not sheerka.is_success(sheerka.new(BuiltinConcepts.TOO_MANY_SUCCESS))
|
|
|
|
def test_cache_is_updated_after_get(self):
|
|
sheerka = self.get_sheerka()
|
|
|
|
# updated when by_key returns one element
|
|
sheerka.create_new_concept(self.get_context(sheerka), Concept("foo", body="1"))
|
|
sheerka.reset_cache()
|
|
sheerka.get("foo")
|
|
assert "foo" in sheerka.cache_by_key
|
|
assert "1001" in sheerka.cache_by_id
|
|
|
|
# updated when by_key returns two elements
|
|
sheerka.create_new_concept(self.get_context(sheerka), Concept("foo", body="2"))
|
|
sheerka.reset_cache()
|
|
sheerka.get("foo")
|
|
assert "foo" in sheerka.cache_by_key
|
|
assert "1001" in sheerka.cache_by_id
|
|
assert "1002" in sheerka.cache_by_id
|
|
|
|
# updated when by_id
|
|
sheerka.reset_cache()
|
|
sheerka.get_by_id("1001")
|
|
assert "1001" in sheerka.cache_by_id
|
|
assert "foo" not in sheerka.cache_by_key # cache_by_key not updated as "1001" is not the only one
|
|
|
|
def test_i_can_get_by_key_several_times(self):
|
|
sheerka = self.get_sheerka()
|
|
sheerka.create_new_concept(self.get_context(sheerka), Concept("foo", body="1"))
|
|
sheerka.create_new_concept(self.get_context(sheerka), Concept("foo", body="2"))
|
|
|
|
sheerka.reset_cache()
|
|
sheerka.get("foo", "1001") # only one element requested. But the cache must be updated with two elements
|
|
|
|
# let's check it
|
|
concepts = sheerka.get("foo")
|
|
assert len(concepts) == 2
|
|
assert concepts[0].id == "1001"
|
|
assert concepts[1].id == "1002"
|