Initial Commit
Working base grammar, visitor, client, context. Good test coverage for grammar constructs.
This commit is contained in:
@@ -0,0 +1,227 @@
|
||||
from parsimonious.grammar import Grammar
|
||||
from customcmd.client import ExecClient
|
||||
from customcmd.parser import Execuitor
|
||||
from customcmd.context import ExecContext
|
||||
|
||||
import pytest
|
||||
import asyncio
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def grammar():
|
||||
with open("assets/grammar.ppeg") as f:
|
||||
return Grammar(f.read())
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def executor():
|
||||
return Execuitor()
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def context():
|
||||
ctx = ExecContext(
|
||||
alias="test_cmd", args=["testarg1", "testarg2"], content="Base content"
|
||||
)
|
||||
return ctx
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def client():
|
||||
return ExecClient()
|
||||
|
||||
|
||||
class TestObject:
|
||||
_exec_attr_name = "testingobj"
|
||||
_exec_attr_number = 7
|
||||
|
||||
async def _exec_attr_functor(self, ctx, arg1):
|
||||
return f"Rec {arg1}"
|
||||
|
||||
async def _exec_attr_functown(self, ctx, arg1):
|
||||
return TestObject()
|
||||
|
||||
def __call__(self, ctx, arg1):
|
||||
return self.dummy_call(ctx, arg1)
|
||||
|
||||
async def dummy_call(self, ctx, arg1):
|
||||
return TestObject()
|
||||
|
||||
def __str__(self):
|
||||
return "Testing Object"
|
||||
|
||||
|
||||
class TestGrammar:
|
||||
async def run_command(self, grammar, executor, context, command):
|
||||
tree = grammar.parse(command)
|
||||
lazyterm = executor.visit(tree)
|
||||
return await lazyterm.execute(context)
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_literals(self, grammar, executor, context):
|
||||
expected_results = [
|
||||
('${""}', ""),
|
||||
('${"abc"}', "abc"),
|
||||
('${ "abc" }', "abc"),
|
||||
("${1}", "1"),
|
||||
("${True}", "True"),
|
||||
("${False}", "False"),
|
||||
]
|
||||
for command, expected in expected_results:
|
||||
actual = await self.run_command(grammar, executor, context, command)
|
||||
assert actual == expected
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_ternary(self, grammar, executor, context):
|
||||
expected_results = [
|
||||
('${"a"?"b":"c"}', "b"),
|
||||
('${""?"b":"c"}', "c"),
|
||||
('${ "a" ? "b" : "c" }', "b"),
|
||||
('${ 1 ? "b" : "c" }', "b"),
|
||||
('${ 0 ? "b" : "c" }', "c"),
|
||||
]
|
||||
for command, expected in expected_results:
|
||||
actual = await self.run_command(grammar, executor, context, command)
|
||||
assert actual == expected
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_cmdarg(self, grammar, executor, context):
|
||||
expected_results = [
|
||||
("${$0}", "test_cmd"),
|
||||
("${$1}", "testarg1"),
|
||||
("${$1*}", "testarg1 testarg2"),
|
||||
("${$3}", ""),
|
||||
("${ $2 }", "testarg2"),
|
||||
]
|
||||
for command, expected in expected_results:
|
||||
actual = await self.run_command(grammar, executor, context, command)
|
||||
assert actual == expected
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_cascade(self, grammar, executor, context):
|
||||
expected_results = [
|
||||
('${""|"result"}', "result"),
|
||||
('${"first"|"result"}', "first"),
|
||||
('${"first"|"second"|"result"}', "first"),
|
||||
('${""|"second"|"result"}', "second"),
|
||||
('${""|""|"result"}', "result"),
|
||||
('${""|0|"result"}', "result"),
|
||||
('${0|1|"result"}', "1"),
|
||||
]
|
||||
for command, expected in expected_results:
|
||||
actual = await self.run_command(grammar, executor, context, command)
|
||||
assert actual == expected
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_define_equals(self, grammar, executor, context):
|
||||
expected_results = [
|
||||
("${a}", "a"),
|
||||
("${(b = 1) | b}", "1"),
|
||||
("${(d = 1) | (c = d) | c}", "1"),
|
||||
("${(e = f) | (f = 1) | e}", "f"),
|
||||
]
|
||||
for command, expected in expected_results:
|
||||
actual = await self.run_command(grammar, executor, context, command)
|
||||
assert actual == expected
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_define_walrus(self, grammar, executor, context):
|
||||
expected_results = [
|
||||
("${a}", "a"),
|
||||
("${b := 1}", "1"),
|
||||
]
|
||||
for command, expected in expected_results:
|
||||
actual = await self.run_command(grammar, executor, context, command)
|
||||
assert actual == expected
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_define_term(self, grammar, executor, context):
|
||||
expected_results = [
|
||||
("${a}", "a"),
|
||||
("${(b ::= 1) | b}", "1"),
|
||||
("${(d ::= 1) | (c ::= d) | c}", "1"),
|
||||
("${(e ::= f) | (f ::= 1) | e}", "1"),
|
||||
]
|
||||
for command, expected in expected_results:
|
||||
actual = await self.run_command(grammar, executor, context, command)
|
||||
assert actual == expected
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_basic_obj(self, grammar, executor, context):
|
||||
context.scope["obj"] = TestObject()
|
||||
|
||||
expected_results = [
|
||||
("${obj}", "Testing Object"),
|
||||
("${obj.name}", "testingobj"),
|
||||
("${obj.number}", "7"),
|
||||
('${obj.functor "abc"}', "Rec abc"),
|
||||
("${(obj.functown abc).functor abc}", "Rec abc"),
|
||||
("${(obj abc).functor abc}", "Rec abc"),
|
||||
]
|
||||
for command, expected in expected_results:
|
||||
actual = await self.run_command(grammar, executor, context, command)
|
||||
assert actual == expected
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_compare(self, grammar, executor, context):
|
||||
expected_results = [
|
||||
("${1 == 1}", "True"),
|
||||
("${1 != 2}", "True"),
|
||||
("${1 <= 2}", "True"),
|
||||
("${1 <= 1}", "True"),
|
||||
("${1 < 2}", "True"),
|
||||
("${1 > 2}", "False"),
|
||||
("${1 >= 2}", "False"),
|
||||
("${1 == 2}", "False"),
|
||||
('${(1 == 2)?"a":"b"}', "b"),
|
||||
('${(1 == 1)?"a":"b"}', "a"),
|
||||
]
|
||||
for command, expected in expected_results:
|
||||
actual = await self.run_command(grammar, executor, context, command)
|
||||
assert actual == expected
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_ops(self, grammar, executor, context):
|
||||
expected_results = [
|
||||
("${1 + 1}", "2"),
|
||||
("${1 + 2 + 3}", "6"),
|
||||
("${1 - 1}", "0"),
|
||||
("${4 / 2}", "2.0"),
|
||||
("${5 % 2}", "1"),
|
||||
("${5 * 2}", "10"),
|
||||
("${5 * 2 * 3}", "30"),
|
||||
("${5 // 2}", "2"),
|
||||
("${2 ** 3}", "8"),
|
||||
("${2 ** 3}", "8"),
|
||||
("${True && False}", "False"),
|
||||
("${True || False}", "True"),
|
||||
("${True && True}", "True"),
|
||||
("${False || False}", "False"),
|
||||
('${"abc" + "def"}', "abcdef"),
|
||||
]
|
||||
for command, expected in expected_results:
|
||||
actual = await self.run_command(grammar, executor, context, command)
|
||||
assert actual == expected
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_compound(self, grammar, executor, context):
|
||||
expected_results = [
|
||||
('${(a = 1) | (b = 1) | ((a == b)? 1 :"Failed")}', "1"),
|
||||
]
|
||||
for command, expected in expected_results:
|
||||
actual = await self.run_command(grammar, executor, context, command)
|
||||
assert actual == expected
|
||||
|
||||
|
||||
class TestClient:
|
||||
@pytest.mark.asyncio
|
||||
async def test_command_1(self, client, context):
|
||||
actual = await client.run_command(
|
||||
context, '${(a = 1) | (b = 1) | ((a == b)? 1 :"Failed")}'
|
||||
)
|
||||
assert actual == "1"
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_command_2(self, client, context):
|
||||
actual = await client.run_command(context, "A test ${2} of the client ${$2}")
|
||||
assert actual == "A test 2 of the client testarg2"
|
||||
Reference in New Issue
Block a user