206 lines
8.1 KiB
Python
206 lines
8.1 KiB
Python
import pytest
|
|
from core.builtin_concepts import BuiltinConcepts
|
|
from parsers.BaseParser import UnexpectedTokenErrorNode, UnexpectedEof
|
|
from parsers.ExplainParser import ExplainParser, ExplanationNode, MultipleDigestError, ValueErrorNode, \
|
|
RecurseDefNode, FormatLNode, UnionNode, FilterNode, FormatDNode
|
|
from parsers.ExpressionParser import PropertyContainsNode, PropertyEqualsNode, TrueNode, AndNode, OrNode
|
|
|
|
from tests.TestUsingMemoryBasedSheerka import TestUsingMemoryBasedSheerka
|
|
|
|
|
|
class TestExplainParser(TestUsingMemoryBasedSheerka):
|
|
def init_parser(self, **kwargs):
|
|
sheerka = self.get_sheerka(singleton=True, **kwargs)
|
|
context = self.get_context(sheerka)
|
|
parser = ExplainParser()
|
|
return sheerka, context, parser
|
|
|
|
def test_i_cannot_parse_empty_string(self):
|
|
sheerka, context, parser = self.init_parser()
|
|
|
|
res = parser.parse(context, "")
|
|
|
|
assert not res.status
|
|
assert sheerka.isinstance(res.body, BuiltinConcepts.NOT_FOR_ME)
|
|
|
|
def test_i_cannot_parse_if_not_for_me(self):
|
|
sheerka, context, parser = self.init_parser()
|
|
|
|
text = "foo"
|
|
res = parser.parse(context, text)
|
|
not_for_me = res.body
|
|
|
|
assert not res.status
|
|
assert sheerka.isinstance(not_for_me, BuiltinConcepts.NOT_FOR_ME)
|
|
assert not_for_me.body == text
|
|
assert isinstance(not_for_me.reason[0], UnexpectedTokenErrorNode)
|
|
|
|
@pytest.mark.parametrize("text, digest, command, directives", [
|
|
# ("explain", "", "explain", []),
|
|
("explain digest", "digest", "explain digest", []),
|
|
("explain -r 3", "", "explain -r 3", [RecurseDefNode(3)]),
|
|
("explain digest -r 3", "digest", "explain digest -r 3", [RecurseDefNode(3)]),
|
|
])
|
|
def test_i_can_parse_explain_without_filter(self, text, digest, command, directives):
|
|
sheerka, context, parser = self.init_parser()
|
|
|
|
res = parser.parse(context, text)
|
|
parser_result = res.body
|
|
explanation_node = res.body.body
|
|
|
|
assert res.status
|
|
assert sheerka.isinstance(parser_result, BuiltinConcepts.PARSER_RESULT)
|
|
assert parser_result.parser.name == "parsers.Explain"
|
|
assert parser_result.source == text
|
|
|
|
assert explanation_node.digest == digest
|
|
assert explanation_node.command == command
|
|
assert explanation_node.expr == UnionNode([FilterNode(TrueNode(), directives)])
|
|
|
|
def test_i_can_parse_using_filter(self):
|
|
sheerka, context, parser = self.init_parser()
|
|
|
|
text = "explain -f a=b"
|
|
res = parser.parse(context, text)
|
|
parser_result = res.body
|
|
explanation_node = res.body.body
|
|
|
|
assert res.status
|
|
assert sheerka.isinstance(parser_result, BuiltinConcepts.PARSER_RESULT)
|
|
assert parser_result.parser.name == "parsers.Explain"
|
|
assert parser_result.source == text
|
|
|
|
assert explanation_node.expr == UnionNode([
|
|
FilterNode(TrueNode()),
|
|
FilterNode(PropertyContainsNode("a", "b"))])
|
|
|
|
@pytest.mark.parametrize("text, expected", [
|
|
("-f a==b", PropertyEqualsNode("a", "b")),
|
|
("--filter a==b", PropertyEqualsNode("a", "b")),
|
|
("-f a==b and c=d", AndNode(PropertyEqualsNode("a", "b"), PropertyContainsNode("c", "d"))),
|
|
("-f a==b or c=d", OrNode(PropertyEqualsNode("a", "b"), PropertyContainsNode("c", "d"))),
|
|
("-f a==b or c==d and e==f", OrNode(
|
|
PropertyEqualsNode("a", "b"),
|
|
AndNode(PropertyEqualsNode("c", "d"), PropertyEqualsNode("e", "f")))),
|
|
("-f a==b and c==d or e==f", OrNode(
|
|
AndNode(PropertyEqualsNode("a", "b"), PropertyEqualsNode("c", "d")),
|
|
PropertyEqualsNode("e", "f"))),
|
|
("-f (a==b or c==d) and e==f", AndNode(
|
|
OrNode(PropertyEqualsNode("a", "b"), PropertyEqualsNode("c", "d")),
|
|
PropertyEqualsNode("e", "f"))),
|
|
])
|
|
def test_i_can_parse_filter_expressions(self, text, expected):
|
|
sheerka, context, parser = self.init_parser()
|
|
|
|
res = parser.parse(context, "explain " + text)
|
|
parser_result = res.body
|
|
explanation_node = res.body.body
|
|
expr_node = explanation_node.expr.filters[-1].expr
|
|
|
|
assert res.status
|
|
assert sheerka.isinstance(parser_result, BuiltinConcepts.PARSER_RESULT)
|
|
assert isinstance(explanation_node, ExplanationNode)
|
|
|
|
assert expr_node == expected
|
|
|
|
@pytest.mark.parametrize("text, expected", [
|
|
("-r 2", [
|
|
FilterNode(TrueNode(), [RecurseDefNode(2)])
|
|
]),
|
|
("--format_l 'abc'", [
|
|
FilterNode(TrueNode(), [FormatLNode('abc')])
|
|
]),
|
|
("--format_d 'abc'", [
|
|
FilterNode(TrueNode(), [FormatDNode({"abc": "{abc}"})])
|
|
]),
|
|
("--format_d a,b,c", [
|
|
FilterNode(TrueNode(), [FormatDNode({"a": "{a}", "b": "{b}", "c": "{c}"})])
|
|
]),
|
|
("--format_d a , b , c", [
|
|
FilterNode(TrueNode(), [FormatDNode({"a": "{a}", "b": "{b}", "c": "{c}"})])
|
|
]),
|
|
("-r 2 --format_l 'abc'", [
|
|
FilterNode(TrueNode(), [RecurseDefNode(2), FormatLNode('abc')])
|
|
]),
|
|
("--format_d a, b -r 2", [
|
|
FilterNode(TrueNode(), [FormatDNode({"a": "{a}", "b": "{b}"}), RecurseDefNode(2)])
|
|
]),
|
|
("-f a==b -r 3", [
|
|
FilterNode(TrueNode()),
|
|
FilterNode(PropertyEqualsNode("a", "b"), [RecurseDefNode(3)]),
|
|
]),
|
|
("-f a==b --format_l 'abc'", [
|
|
FilterNode(TrueNode()),
|
|
FilterNode(PropertyEqualsNode("a", "b"), [FormatLNode("abc")]),
|
|
]),
|
|
("-r 3 -f a==b", [
|
|
FilterNode(TrueNode(), [RecurseDefNode(3)]),
|
|
FilterNode(PropertyEqualsNode("a", "b"), []),
|
|
]),
|
|
("--format_l 'abc' -f a==b", [
|
|
FilterNode(TrueNode(), [FormatLNode("abc")]),
|
|
FilterNode(PropertyEqualsNode("a", "b"), []),
|
|
]),
|
|
("-f a==b -f c==d", [
|
|
FilterNode(TrueNode()),
|
|
FilterNode(PropertyEqualsNode("a", "b")),
|
|
FilterNode(PropertyEqualsNode("c", "d"))
|
|
]),
|
|
("-r 1 -f a==b -r 2 -f c==d -r 3", [
|
|
FilterNode(TrueNode(), [RecurseDefNode(1)]),
|
|
FilterNode(PropertyEqualsNode("a", "b"), [RecurseDefNode(2)]),
|
|
FilterNode(PropertyEqualsNode("c", "d"), [RecurseDefNode(3)])
|
|
]),
|
|
])
|
|
def test_i_can_parse_other_directives(self, text, expected):
|
|
sheerka, context, parser = self.init_parser()
|
|
|
|
res = parser.parse(context, "explain " + text)
|
|
parser_result = res.body
|
|
explanation_node = res.body.body
|
|
expr_node = explanation_node.expr
|
|
|
|
assert res.status
|
|
assert sheerka.isinstance(parser_result, BuiltinConcepts.PARSER_RESULT)
|
|
assert isinstance(explanation_node, ExplanationNode)
|
|
|
|
assert expr_node.filters == expected
|
|
|
|
@pytest.mark.parametrize("text, expected", [
|
|
("explain -d digest", "digest"),
|
|
("explain -d", ""),
|
|
("explain -d -f a=b", "")
|
|
])
|
|
def test_i_can_parse_record_digest(self, text, expected):
|
|
sheerka, context, parser = self.init_parser()
|
|
|
|
res = parser.parse(context, text)
|
|
explanation_node = res.body.body
|
|
|
|
assert explanation_node.digest == expected
|
|
assert explanation_node.record_digest
|
|
|
|
@pytest.mark.parametrize("text, expected_error_type", [
|
|
("explain digest1 digest2", MultipleDigestError),
|
|
("explain -r", UnexpectedEof),
|
|
("explain -r foo", ValueErrorNode),
|
|
("explain -r 1.2", ValueErrorNode),
|
|
("explain -f -r 1.2", UnexpectedTokenErrorNode),
|
|
("explain -f", UnexpectedEof),
|
|
("explain --format_d", UnexpectedEof),
|
|
("explain --format_l", UnexpectedEof),
|
|
("explain --format_l -r foo", UnexpectedTokenErrorNode),
|
|
("explain --format_d -r foo", UnexpectedTokenErrorNode),
|
|
])
|
|
def test_i_cannot_parse(self, text, expected_error_type):
|
|
sheerka, context, parser = self.init_parser()
|
|
|
|
res = parser.parse(context, text)
|
|
error = res.body
|
|
errors = res.body.body
|
|
|
|
assert not res.status
|
|
assert sheerka.isinstance(error, BuiltinConcepts.ERROR)
|
|
assert len(errors) == 1
|
|
assert isinstance(errors[0], expected_error_type)
|