from core.builtin_concepts_ids import BuiltinConcepts from core.concept import Concept, DEFINITION_TYPE_DEF from core.sheerka.services.sheerka_service import ChickenAndEggException from evaluators.PreventCircularReferenceEvaluator import PreventCircularReferenceEvaluator from tests.TestUsingMemoryBasedSheerka import TestUsingMemoryBasedSheerka from tests.evaluators.EvaluatorTestsUtils import cnode_ret_val, concept_ret_val, python_ret_val class TestPreventCircularReferenceEvaluator(TestUsingMemoryBasedSheerka): def test_i_can_match(self): sheerka, context, foo = self.init_concepts("foo") level1 = context.push(BuiltinConcepts.TESTING, None) level2 = level1.push(BuiltinConcepts.EVALUATING_CONCEPT, foo) level3 = level2.push(BuiltinConcepts.TESTING, None) level4 = level3.push(BuiltinConcepts.TESTING, None) assert not PreventCircularReferenceEvaluator().matches(context, []) assert not PreventCircularReferenceEvaluator().matches(level1, []) assert not PreventCircularReferenceEvaluator().matches(level2, []) # only detect sub context assert PreventCircularReferenceEvaluator().matches(level3, []) assert PreventCircularReferenceEvaluator().matches(level4, []) def test_i_can_eval(self): sheerka, context, foo, bar = self.init_concepts("foo", "bar") level1 = context.push(BuiltinConcepts.EVALUATING_CONCEPT, foo) level2 = level1.push(BuiltinConcepts.TESTING, None) python = python_ret_val("1 + 1") cnode_foo = cnode_ret_val(foo) exact_foo = concept_ret_val(foo) exact_bar = concept_ret_val(bar) # no circular return_values = [python, exact_bar] evaluator = PreventCircularReferenceEvaluator() assert evaluator.matches(level2, return_values) assert evaluator.eval(level2, return_values) is None # circular with exact concept parser return_values = [python, exact_foo] evaluator = PreventCircularReferenceEvaluator() assert evaluator.matches(level2, return_values) ret = evaluator.eval(level2, return_values) assert not ret.status assert sheerka.isinstance(ret.body, BuiltinConcepts.FILTERED) assert ret.body.filtered == [exact_foo] assert isinstance(ret.body.reason, ChickenAndEggException) assert ret.parents == [exact_foo] # circular with node concept (can by Sya or Sequence. It does not matter) return_values = [python, cnode_foo] evaluator = PreventCircularReferenceEvaluator() assert evaluator.matches(level2, return_values) ret = evaluator.eval(level2, return_values) assert not ret.status assert sheerka.isinstance(ret.body, BuiltinConcepts.FILTERED) assert ret.body.filtered == [cnode_foo] assert isinstance(ret.body.reason, ChickenAndEggException) assert ret.parents == [cnode_foo] # circular when multiple concepts return_values = [python, exact_foo, cnode_foo] evaluator = PreventCircularReferenceEvaluator() assert evaluator.matches(level2, return_values) ret = evaluator.eval(level2, return_values) assert not ret.status assert sheerka.isinstance(ret.body, BuiltinConcepts.FILTERED) assert ret.body.filtered == [exact_foo, cnode_foo] assert isinstance(ret.body.reason, ChickenAndEggException) assert ret.parents == [exact_foo, cnode_foo] def test_i_cannot_eval_when_the_name_of_the_concept_is_also_a_parameter_of_the_concept(self): sheerka, context, q = self.init_concepts( Concept("q", definition="q ?", definition_type=DEFINITION_TYPE_DEF).def_var("q") ) level1 = context.push(BuiltinConcepts.EVALUATING_CONCEPT, q) level2 = level1.push(BuiltinConcepts.TESTING, None) python = python_ret_val("1 + 1") cnode_q = cnode_ret_val(q) exact_q = concept_ret_val(q) return_values = [python, cnode_q, exact_q] evaluator = PreventCircularReferenceEvaluator() assert evaluator.matches(level2, return_values) assert evaluator.eval(level2, return_values) is None