forked from HoloTech/customcmd-plugin
19da69b3e8
Working base grammar, visitor, client, context. Good test coverage for grammar constructs.
228 lines
7.4 KiB
Python
228 lines
7.4 KiB
Python
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"
|