Files
lilac-customcmd-plugin/tests/grammar.py
T
conatum 19da69b3e8 Initial Commit
Working base grammar, visitor, client, context.
Good test coverage for grammar constructs.
2026-05-30 04:57:04 +10:00

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"