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(use_dict=False, skip_builtins_in_db=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(use_dict=False, skip_builtins_in_db=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(use_dict=False, skip_builtins_in_db=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(skip_builtins_in_db=False) # 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"