mirror of
https://github.com/agessaman/meshcore-bot.git
synced 2026-11-04 03:52:34 +00:00
The packaging test checks pyproject.toml against git ls-files: every directory under modules/ with Python files must be a regular package, and every tracked runtime data file must match a package-data glob, since include-package-data is off and a new subpackage or data file would otherwise silently miss the wheel. The endpoint inventory records all 104 routes with their methods and endpoint names, plus the status, content type, redirect target, script-src CSP (nonce normalized) and framing headers of anonymous requests with and without a password, and of anonymous mutating requests when locked. Endpoint names feed the CSP nonce allowlist and url_for, so a helper extraction that renames or reroutes anything shows up here.
87 lines
3.1 KiB
Python
87 lines
3.1 KiB
Python
"""Characterization: every node-name lookup against every ``self_info`` shape.
|
|
|
|
The bot reads its own name in several places with different fallback orders and
|
|
different presence/truthiness rules (budget paths read ``name``/``user_name``,
|
|
mention matching reads ``name``/``adv_name``, and BaseCommand's object branch
|
|
tests attribute presence rather than truthiness). Consolidating them must keep
|
|
each caller's current answer; this golden file records it.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import configparser
|
|
import itertools
|
|
from types import SimpleNamespace
|
|
from unittest.mock import MagicMock, Mock
|
|
|
|
from modules.command_manager import CommandManager
|
|
from modules.commands.base_command import BaseCommand
|
|
from modules.models import MeshMessage
|
|
from modules.scheduler import MessageScheduler
|
|
from tests.characterization.golden_util import assert_golden
|
|
|
|
FIELDS = ("name", "user_name", "adv_name")
|
|
VALUES = (None, "", "Dev") # None = field absent
|
|
|
|
|
|
class _Cmd(BaseCommand):
|
|
name = "probe"
|
|
keywords = ["probe"]
|
|
|
|
async def execute(self, message): # pragma: no cover - abstract stub
|
|
return True
|
|
|
|
|
|
def _shapes():
|
|
yield "self_info=None", None
|
|
for combo in itertools.product(VALUES, repeat=len(FIELDS)):
|
|
present = {f: (f"{v}-{f}" if v == "Dev" else v) for f, v in zip(FIELDS, combo, strict=True) if v is not None}
|
|
label = ",".join(f"{k}={v!r}" for k, v in present.items()) or "empty"
|
|
yield f"dict[{label}]", dict(present)
|
|
yield f"obj[{label}]", SimpleNamespace(**present)
|
|
|
|
|
|
def _bot(self_info, config_name):
|
|
cfg = configparser.ConfigParser()
|
|
cfg.add_section("Bot")
|
|
if config_name is not None:
|
|
cfg.set("Bot", "bot_name", config_name)
|
|
cfg.add_section("Channels")
|
|
bot = MagicMock()
|
|
bot.config = cfg
|
|
bot.logger = Mock()
|
|
bot.meshcore = MagicMock()
|
|
bot.meshcore.self_info = self_info
|
|
return bot
|
|
|
|
|
|
def _safe(fn):
|
|
try:
|
|
return fn()
|
|
except Exception as exc: # noqa: BLE001 - the exception type is the behavior
|
|
return f"<raises {type(exc).__name__}>"
|
|
|
|
|
|
def test_node_name_lookups():
|
|
results = {}
|
|
for (label, self_info), config_name in itertools.product(list(_shapes()), [None, "", "CfgBot"]):
|
|
bot = _bot(self_info, config_name)
|
|
cm = object.__new__(CommandManager)
|
|
cm.bot = bot
|
|
cm.logger = bot.logger
|
|
cmd = object.__new__(_Cmd)
|
|
cmd.bot = bot
|
|
cmd.logger = bot.logger
|
|
sched = object.__new__(MessageScheduler)
|
|
sched.bot = bot
|
|
sched.logger = bot.logger
|
|
channel_msg = MeshMessage(content="x", channel="general", is_dm=False)
|
|
results[f"{label} config_bot_name={config_name!r}"] = {
|
|
"cm.get_max_message_length": _safe(lambda: cm.get_max_message_length(channel_msg)),
|
|
"cm.channel_body_budget": _safe(lambda: cm.channel_body_budget(channel="general")),
|
|
"cmd.get_max_message_length": _safe(lambda: cmd.get_max_message_length(channel_msg)),
|
|
"cmd._get_bot_name": _safe(cmd._get_bot_name),
|
|
"scheduler._channel_body_budget": _safe(lambda: sched._channel_body_budget(None)),
|
|
}
|
|
assert_golden("bot_identity_matrix", results)
|