Files
Sheerka-Old/tests/parsers/test_FunctionParser.py
T
kodjo cac2dad17f Implemented some enhancement request and fixed some bugs
Fixed #2 : Variables are not recognized when inside a rule token
Fixed #15 : Rule: rete attributes are lost when a new ontology is created
Fixed #14 : ReteNetwork: Format rules must not be added to Rete network
Fixed #16 : DefConcept: Variables are not recognized when they are keyword arguments
Fixed #4 : Comparison are not correctly set when comparison property is a concept
Fixed #14 : Parser: merge FunctionParser.NamesNode and ExpressionParser.NamesNode
Fixed #18 : Parser: Add SourceCodeNode test to UnrecognizedNodeParser
Fixed #20 : At startup Number concept is saved in db a numerous number of time
Fixed #21 : CacheManager: I can remove all elements from a ListIfNeededCache and fill it again
Fixed #22 : CacheManager: I can remove all elements from a SetCache and fill it again
Fixed #23 : HistoryManager: history() no longer works
Fixed #24 : HistoryManager: history() no longer works after creating an exec rule
Fixed #25 : SheerkaMemory: Use MemoryObject instead of sheerka.local
Fixed #26 : Debugger: add the list all available services..
Fixed #27 : CONCEPTS_GRAMMARS_ENTRY does not seems to be in use any more
Fixed #28 : Give order to services
2021-02-12 15:15:31 +01:00

253 lines
9.9 KiB
Python

import pytest
from core.builtin_concepts import BuiltinConcepts
from core.concept import Concept
from core.sheerka.services.SheerkaExecute import ParserInput
from parsers.BaseNodeParser import SCN, SCWC, CN, UTN, CNC, RN
from parsers.FunctionParser import FunctionParser, FN
from tests.TestUsingMemoryBasedSheerka import TestUsingMemoryBasedSheerka
from tests.parsers.parsers_utils import compute_expected_array
cmap = {
"one": Concept("one"),
"two": Concept("two"),
"twenties": Concept("twenties", definition="'twenty' (one|two)=unit").def_var("unit"),
"plus": Concept("a plus b").def_var("a").def_var("b"),
}
class TestFunctionParser(TestUsingMemoryBasedSheerka):
shared_ontology = None
@classmethod
def setup_class(cls):
init_test_helper = cls().init_test(cache_only=False, ontology="#TestFunctionParser#")
sheerka, context, *updated = init_test_helper.with_concepts(*cmap.values(), create_new=True).unpack()
for i, concept_name in enumerate(cmap):
cmap[concept_name] = updated[i]
cls.shared_ontology = sheerka.get_ontology(context)
sheerka.pop_ontology(context)
def init_parser(self, my_concepts_map=None, **kwargs):
if my_concepts_map is None:
sheerka, context = self.init_test().unpack()
sheerka.add_ontology(context, self.shared_ontology)
else:
sheerka, context, *updated = self.init_test().with_concepts(*my_concepts_map.values(), **kwargs).unpack()
for i, pair in enumerate(my_concepts_map):
my_concepts_map[pair] = updated[i]
parser = FunctionParser()
return sheerka, context, parser
def test_i_can_detect_empty_expression(self):
sheerka, context, parser = self.init_parser()
res = parser.parse(context, ParserInput(""))
assert not res.status
assert sheerka.isinstance(res.body, BuiltinConcepts.IS_EMPTY)
def test_input_must_be_a_parser_input(self):
sheerka, context, parser = self.init_parser()
parser.parse(context, "not a parser input") is None
def test_i_cannot_parse_when_not_a_function(self):
sheerka, context, parser = self.init_parser()
res = parser.parse(context, ParserInput("not a function"))
assert not res.status
assert sheerka.isinstance(res.body, BuiltinConcepts.NOT_FOR_ME)
@pytest.mark.parametrize("expression, expected", [
("func()", FN("func(", ")", [])),
("concept(one)", FN("concept(", ")", ["one"])),
("func(one)", FN("func(", ")", ["one"])),
("func(a long two, 'three', ;:$*)", FN("func(", ")", ["a long two, ", "'three', ", ";:$*"])),
("func(func1(one), two, func2(func3(), func4(three)))", FN("func(", ")", [
(FN("func1(", ")", ["one"]), ", "),
"two, ",
(FN("func2(", ")", [
(FN("func3(", ")", []), ", "),
(FN("func4(", ")", ["three"]), None),
]), None)
])),
])
def test_i_can_parse_function(self, expression, expected):
sheerka, context, parser = self.init_parser()
parser.reset_parser(context, ParserInput(expression))
parser.parser_input.next_token()
res = parser.parse_function()
assert res == expected
def test_i_can_parse_function_when_rule(self):
sheerka, context, parser = self.init_parser()
parser.reset_parser(context, ParserInput("func(r:|1:)"))
parser.parser_input.next_token()
res = parser.parse_function()
assert res == FN("func(", ")", ["r:|1:"])
@pytest.mark.parametrize("text, expected", [
("func()", SCN("func()")),
(" func()", SCN("func()")),
("func(one)", SCWC("func(", ")", CN("one"))),
("func(one, unknown, two)", SCWC("func(", ")", CN("one"), ", ", UTN("unknown"), (", ", 1), CN("two"))),
("func(one, twenty two)", SCWC("func(", ")", "one", ", ", CN("twenties", source="twenty two"))),
("func(one plus two, three)", SCWC("func(", ")", CNC("plus", a="one", b="two"), ", ", UTN("three"))),
("func(func1(one), two)", SCWC("func(", (")", 1), SCWC("func1(", ")", "one"), ", ", "two"))
])
def test_i_can_parse(self, text, expected):
sheerka, context, parser = self.init_parser()
resolved_expected = compute_expected_array(cmap, text, [expected])[0]
res = parser.parse(context, ParserInput(text))
parser_result = res.body
expression = res.body.body
assert res.status
assert sheerka.isinstance(parser_result, BuiltinConcepts.PARSER_RESULT)
assert expression == resolved_expected
assert expression.python_node is not None
assert expression.return_value is not None
def test_i_can_parse_when_multiple_results_when_requested(self):
sheerka, context, parser = self.init_parser()
parser.longest_concepts_only = False
text = "func(one, twenty two)"
expected = [SCWC("func(", ")", "one", ", ", "twenty ", "two"),
SCWC("func(", ")", "one", ", ", CN("twenties", source="twenty two"))]
all_resolved_expected = compute_expected_array(cmap, text, expected)
results = parser.parse(context, ParserInput(text))
assert len(results) == 2
for res, resolved_expected in zip(results, all_resolved_expected):
parser_result = res.body
expressions = res.body.body
assert sheerka.isinstance(parser_result, BuiltinConcepts.PARSER_RESULT)
assert expressions == resolved_expected
def test_i_can_parse_when_the_parameter_is_not_a_concept(self):
"""
It's not a concept, but it can be a valid short term memory object
:return:
"""
sheerka, context, parser = self.init_parser()
text = "func(unknown_concept)"
res = parser.parse(context, ParserInput(text))
assert res.status
def test_i_cannot_parse_when_the_concept_is_not_found(self):
"""
We do not check yet if it's a valid concept
If you find a cheap way to do so, simply remove this test
:return:
"""
sheerka, context, parser = self.init_parser()
text = "func(c:|xxx:)"
res = parser.parse(context, ParserInput(text))
assert res.status
def test_i_can_parse_when_rules(self):
sheerka, context, parser = self.init_parser()
text = "func(r:|1:)"
expected = SCWC("func(", ")", RN("1"))
resolved_expected = compute_expected_array(cmap, text, [expected])[0]
res = parser.parse(context, ParserInput(text))
parser_result = res.body
expression = res.body.body
assert res.status
assert sheerka.isinstance(parser_result, BuiltinConcepts.PARSER_RESULT)
assert expression == resolved_expected
assert expression.python_node is not None
assert expression.return_value is not None
# def test_i_cannot_parse_when_rule_not_found(self):
# sheerka, context, parser = self.init_parser()
# text = "func(r:|fake:)"
# expected = SCWC("func(", ")", RN("fake"))
# resolved_expected = compute_expected_array(cmap, text, [expected])[0]
#
# res = parser.parse(context, ParserInput(text))
# parser_result = res.body
# expression = res.body.body
#
# assert not res.status
# assert sheerka.isinstance(parser_result, BuiltinConcepts.PARSER_RESULT)
# assert expression == resolved_expected
# assert expression.python_node is not None
# assert expression.return_value is not None
@pytest.mark.parametrize("text, expected_error_type", [
("one", BuiltinConcepts.NOT_FOR_ME),
("$*!", BuiltinConcepts.NOT_FOR_ME),
("func(", BuiltinConcepts.ERROR),
("func(one", BuiltinConcepts.ERROR),
("func(one, two, ", BuiltinConcepts.ERROR),
("func(one) and func(two)", BuiltinConcepts.ERROR),
("one func(one)", BuiltinConcepts.NOT_FOR_ME),
])
def test_i_cannot_parse(self, text, expected_error_type):
sheerka, context, parser = self.init_parser()
res = parser.parse(context, ParserInput(text))
assert not res.status
assert sheerka.isinstance(res.body, expected_error_type)
@pytest.mark.parametrize("text, expected", [
("func(one two)", SCWC("func(", ")", "one", "two")),
])
def test_i_can_detect_none_function(self, text, expected):
sheerka, context, parser = self.init_parser()
resolved_expected = compute_expected_array(cmap, text, [expected])[0]
res = parser.parse(context, ParserInput(text))
parser_result = res.body
expression = res.body.body
assert not res.status
assert sheerka.isinstance(parser_result, BuiltinConcepts.PARSER_RESULT)
assert expression == resolved_expected
assert expression.python_node is None
assert expression.return_value is None
@pytest.mark.parametrize("sequence, expected", [
(None, None),
([["a"]], [["a"]]),
([["a"], ["b", "c"]], [["a"]]),
([["b", "c"], ["a"]], [["a"]]),
([["b", "c"], ["a"], ["d", "e"], ["f"]], [["a"], ["f"]]),
])
def test_i_can_get_the_longest_concept_sequence(self, sequence, expected):
assert FunctionParser.get_longest_concepts(sequence) == expected
def test_concepts_found_are_fully_initialized(self):
sheerka, context, parser = self.init_parser()
res = parser.parse(context, ParserInput("func(one plus three)"))
concept = res.body.body.nodes[0].concept
assert res.status
assert isinstance(concept.get_compiled()["a"], Concept)
# three is not recognized,
# so it will be transformed into list of ReturnValueConcept that indicate how to recognized it
assert isinstance(concept.get_compiled()["b"], list)
for item in concept.get_compiled()["b"]:
assert sheerka.isinstance(item, BuiltinConcepts.RETURN_VALUE)