import pytest from core.builtin_concepts import ParserResultConcept from core.builtin_concepts_ids import BuiltinConcepts from core.concept import Concept from core.sheerka.services.SheerkaExecute import ParserInput from evaluators.BaseEvaluator import BaseEvaluator from evaluators.ValidateConceptEvaluator import ValidateConceptEvaluator from parsers.BaseNodeParser import ConceptNode from parsers.BaseParser import BaseParser from parsers.BnfNodeParser import BnfNodeParser from parsers.ExactConceptParser import ExactConceptParser from parsers.SyaNodeParser import SyaNodeParser from tests.TestUsingMemoryBasedSheerka import TestUsingMemoryBasedSheerka from tests.evaluators.EvaluatorTestsUtils import p_ret_val, pr_ret_val, ret_val class TestValidateConceptEvaluator(TestUsingMemoryBasedSheerka): @pytest.mark.parametrize("return_value, need_validation, expected", [ (pr_ret_val(Concept("foo", where="something"), status=True), True, True), (pr_ret_val(Concept("foo", pre="something"), status=True), True, True), (pr_ret_val(Concept("foo", where="something"), status=True), False, False), (pr_ret_val(Concept("foo", pre="something"), status=True), False, False), (pr_ret_val(Concept("foo"), status=True), True, False), (pr_ret_val(Concept("foo"), status=True), True, False), (pr_ret_val(Concept("foo", where=None), status=True), True, False), (pr_ret_val(Concept("foo", pre=None), status=True), True, False), (pr_ret_val(Concept("foo", where=""), status=True), True, False), (pr_ret_val(Concept("foo", pre=""), status=True), True, False), (pr_ret_val(Concept("foo", where="something"), status=False), True, False), (pr_ret_val(Concept("foo", pre="something"), status=False), True, False), (pr_ret_val("Not a concept", status=True), True, False), (pr_ret_val("Not a concept", status=False), True, False), (p_ret_val("Not a parser result", status=True), True, False), (p_ret_val("Not a parser result", status=False), True, False), ]) def test_i_can_match(self, return_value, need_validation, expected): sheerka, context = self.init_concepts() evaluator = ValidateConceptEvaluator() if (sheerka.isinstance(return_value.body, BuiltinConcepts.PARSER_RESULT) and isinstance(return_value.body.body, Concept)): return_value.body.body.get_hints().need_validation = need_validation assert evaluator.matches(context, return_value) == expected def test_i_cannot_match_when_the_return_value_is_not_a_direct_parsing_result(self): # I match only if the return_value comes from a parser (not from an after_parsing evaluator) sheerka, context = self.init_concepts() concept = Concept("foo", pre="something") parser_result = ParserResultConcept(BaseParser.get_name("parser"), source=concept.name, value=concept) return_value = ret_val(value=parser_result, who="evaluators.something", status=True) return_value.body.body.get_hints().need_validation = True evaluator = ValidateConceptEvaluator() assert not evaluator.matches(context, return_value) @pytest.mark.parametrize("concept", [ Concept("foo", pre="False"), Concept("foo", where="False"), ]) def test_i_can_eval_when_constraint_is_false(self, concept): sheerka, context, foo = self.init_concepts(concept) ret_val = pr_ret_val(foo, status=True) res = ValidateConceptEvaluator().eval(context, ret_val) assert not res.status assert res.who == BaseEvaluator.PREFIX + ValidateConceptEvaluator.NAME assert sheerka.isinstance(res.body, BuiltinConcepts.FILTERED) assert res.body.body == foo @pytest.mark.parametrize("concept", [ Concept("foo"), Concept("foo", pre="True"), Concept("foo", where="True"), ]) def test_i_can_eval_when_constraint_is_true_or_when_no_constrain(self, concept): sheerka, context, foo = self.init_concepts(concept) ret_val = pr_ret_val(foo, status=True) res = ValidateConceptEvaluator().eval(context, ret_val) assert res is None @pytest.mark.parametrize("concept", [ Concept("foo"), Concept("foo", pre="True"), Concept("foo", where="True"), ]) def test_i_can_eval_when_constraint_is_true_or_when_no_constrain_use_copy(self, concept): sheerka, context, foo = self.init_concepts(concept) foo.get_hints().use_copy = True ret_val = pr_ret_val(foo, status=True) res = ValidateConceptEvaluator().eval(context, ret_val) assert res.status assert res.who == BaseEvaluator.PREFIX + ValidateConceptEvaluator.NAME assert res.body.body.id == foo.id assert not res.body.body.get_hints().use_copy def test_i_can_eval_when_is_question(self): sheerka, context, foo = self.init_concepts(Concept("foo", pre="is_question()")) ret_val = pr_ret_val(foo, status=True) res = ValidateConceptEvaluator().eval(context, ret_val) assert not res.status context.add_to_protected_hints(BuiltinConcepts.EVAL_QUESTION_REQUESTED) res = ValidateConceptEvaluator().eval(context, ret_val) assert res is None def test_i_can_eval_when_unknown_variables_but_no_constraint(self): sheerka, context, foo = self.init_concepts(Concept("a plus b").def_var("a").def_var("b")) ret_val = pr_ret_val(foo, status=True) res = ValidateConceptEvaluator().eval(context, ret_val) assert res is None def test_i_can_eval_when_unknown_variables(self): # ValidateConceptEvaluator must filter only if all the variables are known # In this example, 'b' is not set, so the return_value must not be filtered sheerka, context, foo = self.init_concepts( Concept("a plus b", where="isinstance(b, int)").def_var("a", "10").def_var("b")) ret_val = pr_ret_val(foo, status=True) res = ValidateConceptEvaluator().eval(context, ret_val) assert res is None def test_i_can_eval_when_constraint_on_variable_fails(self): sheerka, context, foo = self.init_concepts( Concept("a plus b", where="isinstance(b, int)").def_var("a").def_var("b", "'a string'")) ret_val = pr_ret_val(foo, status=True) res = ValidateConceptEvaluator().eval(context, ret_val) assert not res.status def test_i_can_eval_bnf_concepts(self): sheerka, context, quantify_x = self.init_concepts( Concept("quantify x", definition="('one'|'two') x", where="x != 'one'").def_var("x"), create_new=True) evaluator = ValidateConceptEvaluator() # success ret_val = BnfNodeParser().parse(context, ParserInput("one 'two'")) assert evaluator.matches(context, ret_val) res = evaluator.eval(context, ret_val) assert isinstance(res.body.body, list) assert len(res.body.body) == 1 assert isinstance(res.body.body[0], ConceptNode) assert res.body.body[0].concept.id == ret_val.body.body[0].concept.id # failure ret_val = BnfNodeParser().parse(context, ParserInput("one 'one'")) assert evaluator.matches(context, ret_val) res = evaluator.eval(context, ret_val) assert not res.status assert sheerka.isinstance(res.body, BuiltinConcepts.FILTERED) assert res.body.body == ret_val.body.body def test_i_can_eval_sya_concepts(self): sheerka, context, quantify_x = self.init_concepts( Concept("a plus b", where="a < 10").def_var("a").def_var("b"), create_new=True) evaluator = ValidateConceptEvaluator() # success ret_val = SyaNodeParser().parse(context, ParserInput("5 plus 3")) assert evaluator.matches(context, ret_val) res = evaluator.eval(context, ret_val) assert isinstance(res.body.body, list) assert len(res.body.body) == 1 assert isinstance(res.body.body[0], ConceptNode) assert res.body.body[0].concept.id == ret_val.body.body[0].concept.id # failure ret_val = SyaNodeParser().parse(context, ParserInput("15 plus 3")) assert evaluator.matches(context, ret_val) res = evaluator.eval(context, ret_val) assert not res.status assert sheerka.isinstance(res.body, BuiltinConcepts.FILTERED) assert res.body.body == ret_val.body.body def test_i_can_eval_exact_parser_concepts(self): sheerka, context, explain_x = self.init_concepts( Concept("explain x", where="isinstance(x, int)").def_var("x") ) evaluator = ValidateConceptEvaluator() ret_val = ExactConceptParser().parse(context, ParserInput("explain 1"))[0] assert evaluator.matches(context, ret_val) res = evaluator.eval(context, ret_val) assert sheerka.isinstance(res.body.body, explain_x)