mirror of
https://github.com/jkingsman/Remote-Terminal-for-MeshCore.git
synced 2026-08-08 09:43:03 +02:00
Add path_bytes_per_hop to bot kwargs and encourage kwargs-only going forward
This commit is contained in:
+101
-1
@@ -312,6 +312,67 @@ def bot(sender_name, sender_key, message_text, is_dm, channel_key, channel_name,
|
||||
)
|
||||
assert result == "outgoing=True"
|
||||
|
||||
def test_new_10_param_bot_receives_path_bytes_per_hop(self):
|
||||
"""Bots that declare path_bytes_per_hop receive it positionally."""
|
||||
code = """
|
||||
def bot(sender_name, sender_key, message_text, is_dm, channel_key, channel_name, sender_timestamp, path, is_outgoing, path_bytes_per_hop):
|
||||
return f"bytes={path_bytes_per_hop}"
|
||||
"""
|
||||
result = execute_bot_code(
|
||||
code=code,
|
||||
sender_name="Alice",
|
||||
sender_key="abc123",
|
||||
message_text="Hi",
|
||||
is_dm=True,
|
||||
channel_key=None,
|
||||
channel_name=None,
|
||||
sender_timestamp=None,
|
||||
path="aabb",
|
||||
path_bytes_per_hop=2,
|
||||
)
|
||||
assert result == "bytes=2"
|
||||
|
||||
def test_9_param_bot_with_path_bytes_only_receives_it(self):
|
||||
"""Bots may opt into path_bytes_per_hop without also declaring is_outgoing."""
|
||||
code = """
|
||||
def bot(sender_name, sender_key, message_text, is_dm, channel_key, channel_name, sender_timestamp, path, path_bytes_per_hop):
|
||||
return f"bytes={path_bytes_per_hop}"
|
||||
"""
|
||||
result = execute_bot_code(
|
||||
code=code,
|
||||
sender_name="Alice",
|
||||
sender_key="abc123",
|
||||
message_text="Hi",
|
||||
is_dm=True,
|
||||
channel_key=None,
|
||||
channel_name=None,
|
||||
sender_timestamp=None,
|
||||
path="aabb",
|
||||
is_outgoing=True,
|
||||
path_bytes_per_hop=2,
|
||||
)
|
||||
assert result == "bytes=2"
|
||||
|
||||
def test_legacy_bot_with_kwargs_receives_path_bytes_per_hop(self):
|
||||
"""Bots using **kwargs receive the new path_bytes_per_hop field."""
|
||||
code = """
|
||||
def bot(sender_name, sender_key, message_text, is_dm, channel_key, channel_name, sender_timestamp, path, **kwargs):
|
||||
return f"bytes={kwargs.get('path_bytes_per_hop', 'missing')}"
|
||||
"""
|
||||
result = execute_bot_code(
|
||||
code=code,
|
||||
sender_name="Alice",
|
||||
sender_key="abc123",
|
||||
message_text="Hi",
|
||||
is_dm=True,
|
||||
channel_key=None,
|
||||
channel_name=None,
|
||||
sender_timestamp=None,
|
||||
path="aabb",
|
||||
path_bytes_per_hop=2,
|
||||
)
|
||||
assert result == "bytes=2"
|
||||
|
||||
def test_channel_message_with_none_sender_key(self):
|
||||
"""Channel messages correctly pass None for sender_key."""
|
||||
code = """
|
||||
@@ -419,7 +480,14 @@ class TestBotCodeValidation:
|
||||
from app.routers.fanout import _validate_bot_config
|
||||
|
||||
# Should not raise
|
||||
_validate_bot_config({"code": "def bot(): return 'hello'"})
|
||||
_validate_bot_config(
|
||||
{
|
||||
"code": (
|
||||
"def bot(sender_name, sender_key, message_text, is_dm, channel_key, "
|
||||
"channel_name, sender_timestamp, path):\n return 'hello'"
|
||||
)
|
||||
}
|
||||
)
|
||||
|
||||
def test_syntax_error_raises(self):
|
||||
"""Syntax error in code raises HTTPException."""
|
||||
@@ -456,6 +524,38 @@ class TestBotCodeValidation:
|
||||
|
||||
assert exc_info.value.status_code == 400
|
||||
|
||||
def test_missing_bot_function_raises(self):
|
||||
"""Code must define a callable bot() function."""
|
||||
from fastapi import HTTPException
|
||||
|
||||
from app.routers.fanout import _validate_bot_config
|
||||
|
||||
with pytest.raises(HTTPException) as exc_info:
|
||||
_validate_bot_config({"code": "def helper():\n return 'hello'"})
|
||||
|
||||
assert exc_info.value.status_code == 400
|
||||
assert "callable bot() function" in exc_info.value.detail
|
||||
|
||||
def test_unsupported_signature_raises(self):
|
||||
"""Unsupported bot signatures are rejected with guidance."""
|
||||
from fastapi import HTTPException
|
||||
|
||||
from app.routers.fanout import _validate_bot_config
|
||||
|
||||
with pytest.raises(HTTPException) as exc_info:
|
||||
_validate_bot_config(
|
||||
{
|
||||
"code": (
|
||||
"def bot(sender_name, sender_key, message_text, is_dm, channel_key, "
|
||||
"channel_name, sender_timestamp, path, *, extra_required):\n"
|
||||
" return extra_required"
|
||||
)
|
||||
}
|
||||
)
|
||||
|
||||
assert exc_info.value.status_code == 400
|
||||
assert "signature is not supported" in exc_info.value.detail.lower()
|
||||
|
||||
|
||||
class TestBotMessageRateLimiting:
|
||||
"""Test bot message rate limiting for repeater compatibility."""
|
||||
|
||||
@@ -36,6 +36,7 @@ class TestBotModuleParameterExtraction:
|
||||
sender_timestamp,
|
||||
path,
|
||||
is_outgoing,
|
||||
path_bytes_per_hop,
|
||||
):
|
||||
captured["is_outgoing"] = is_outgoing
|
||||
captured["is_dm"] = is_dm
|
||||
@@ -84,6 +85,7 @@ class TestBotModuleParameterExtraction:
|
||||
sender_timestamp,
|
||||
path,
|
||||
is_outgoing,
|
||||
path_bytes_per_hop,
|
||||
):
|
||||
captured["is_outgoing"] = is_outgoing
|
||||
return None
|
||||
@@ -129,8 +131,10 @@ class TestBotModuleParameterExtraction:
|
||||
sender_timestamp,
|
||||
path,
|
||||
is_outgoing,
|
||||
path_bytes_per_hop,
|
||||
):
|
||||
captured["path"] = path
|
||||
captured["path_bytes_per_hop"] = path_bytes_per_hop
|
||||
return None
|
||||
|
||||
mod = BotModule("test", {"code": "def bot(**k): pass"}, name="Test")
|
||||
@@ -150,11 +154,12 @@ class TestBotModuleParameterExtraction:
|
||||
"type": "PRIV",
|
||||
"conversation_key": "pk1",
|
||||
"text": "hello",
|
||||
"paths": [{"path": "aabb", "rssi": -50}],
|
||||
"paths": [{"path": "aabbccdd", "path_len": 2, "rssi": -50}],
|
||||
}
|
||||
)
|
||||
|
||||
assert captured["path"] == "aabb"
|
||||
assert captured["path"] == "aabbccdd"
|
||||
assert captured["path_bytes_per_hop"] == 2
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_channel_sender_prefix_stripped(self):
|
||||
@@ -174,6 +179,7 @@ class TestBotModuleParameterExtraction:
|
||||
sender_timestamp,
|
||||
path,
|
||||
is_outgoing,
|
||||
path_bytes_per_hop,
|
||||
):
|
||||
captured["message_text"] = message_text
|
||||
captured["sender_name"] = sender_name
|
||||
@@ -221,6 +227,7 @@ class TestBotModuleParameterExtraction:
|
||||
sender_timestamp,
|
||||
path,
|
||||
is_outgoing,
|
||||
path_bytes_per_hop,
|
||||
):
|
||||
captured["channel_name"] = channel_name
|
||||
return None
|
||||
@@ -267,6 +274,7 @@ class TestBotModuleParameterExtraction:
|
||||
sender_timestamp,
|
||||
path,
|
||||
is_outgoing,
|
||||
path_bytes_per_hop,
|
||||
):
|
||||
captured["sender_name"] = sender_name
|
||||
captured["sender_key"] = sender_key
|
||||
|
||||
Reference in New Issue
Block a user