mirror of
https://git.quad4.io/RNS-Things/MeshChatX.git
synced 2026-09-16 20:42:41 +00:00
199 lines
6.0 KiB
Python
199 lines
6.0 KiB
Python
import os
|
|
import stat
|
|
import tempfile
|
|
from pathlib import Path
|
|
from unittest.mock import MagicMock, patch
|
|
|
|
import pytest
|
|
|
|
from lxmfy import BotConfig, LXMFBot
|
|
from lxmfy.cogs_core import _get_sandbox_command, load_cogs_from_directory
|
|
|
|
|
|
@pytest.fixture
|
|
def external_cog_setup():
|
|
"""Set up a temporary directory with an external script cog."""
|
|
with tempfile.TemporaryDirectory() as temp_dir:
|
|
temp_path = Path(temp_dir)
|
|
cogs_dir = temp_path / "cogs"
|
|
cogs_dir.mkdir()
|
|
|
|
# Create a simple bash script
|
|
script_path = cogs_dir / "test_cmd.sh"
|
|
script_content = """#!/bin/bash
|
|
echo "Hello from external script! Sender: $1 Content: $2"
|
|
"""
|
|
script_path.write_text(script_content)
|
|
|
|
# Make it executable
|
|
st = os.stat(script_path)
|
|
os.chmod(script_path, st.st_mode | stat.S_IEXEC)
|
|
|
|
yield temp_path
|
|
|
|
|
|
def test_cog_external_loading(external_cog_setup):
|
|
"""Test that external script cogs are loaded correctly."""
|
|
config = BotConfig(
|
|
name="TestBot",
|
|
test_mode=True,
|
|
external_cogs_enabled=True,
|
|
config_path=str(external_cog_setup),
|
|
storage_path=str(external_cog_setup / "storage"),
|
|
)
|
|
bot = LXMFBot(**config.__dict__)
|
|
bot.config_path = str(external_cog_setup)
|
|
|
|
# Load cogs
|
|
load_cogs_from_directory(bot)
|
|
|
|
assert "test_cmd" in bot.commands
|
|
cmd = bot.commands["test_cmd"]
|
|
assert cmd.name == "test_cmd"
|
|
assert cmd.threaded is True # Should always be threaded
|
|
assert "External script command" in cmd.description
|
|
|
|
|
|
def test_cog_external_execution(external_cog_setup):
|
|
"""Test that external script cogs execute and return output."""
|
|
config = BotConfig(
|
|
name="TestBot",
|
|
test_mode=True,
|
|
external_cogs_enabled=True,
|
|
external_cogs_sandbox_enabled=False,
|
|
config_path=str(external_cog_setup),
|
|
storage_path=str(external_cog_setup / "storage"),
|
|
)
|
|
bot = LXMFBot(**config.__dict__)
|
|
bot.config_path = str(external_cog_setup)
|
|
|
|
# Load cogs
|
|
load_cogs_from_directory(bot)
|
|
|
|
cmd = bot.commands["test_cmd"]
|
|
|
|
# Mock message
|
|
msg = MagicMock()
|
|
msg.sender = "test_sender"
|
|
msg.content = "/test_cmd hello world"
|
|
msg.args = ["hello", "world"]
|
|
|
|
# Execute callback
|
|
cmd.callback(msg)
|
|
|
|
# Check if msg.reply was called with expected output
|
|
msg.reply.assert_called_once()
|
|
args, _ = msg.reply.call_args
|
|
output = args[0]
|
|
assert "Hello from external script!" in output
|
|
assert "Sender: test_sender" in output
|
|
assert "Content: /test_cmd hello world" in output
|
|
|
|
|
|
def test_cog_external_disabled(external_cog_setup):
|
|
"""Test that external script cogs are NOT loaded when disabled."""
|
|
config = BotConfig(
|
|
name="TestBot",
|
|
test_mode=True,
|
|
external_cogs_enabled=False,
|
|
config_path=str(external_cog_setup),
|
|
storage_path=str(external_cog_setup / "storage"),
|
|
)
|
|
bot = LXMFBot(**config.__dict__)
|
|
bot.config_path = str(external_cog_setup)
|
|
|
|
# Load cogs
|
|
load_cogs_from_directory(bot)
|
|
|
|
assert "test_cmd" not in bot.commands
|
|
|
|
|
|
def test_sandbox_detection_bwrap():
|
|
"""Test bubblewrap sandbox detection."""
|
|
bot = MagicMock()
|
|
bot.config.external_cogs_sandbox_enabled = True
|
|
bot.config.external_cogs_sandbox_type = "auto"
|
|
|
|
with (
|
|
patch("shutil.which") as mock_which,
|
|
patch("sys.platform", "linux"),
|
|
patch("os.path.exists", return_value=True),
|
|
):
|
|
mock_which.side_effect = lambda x: f"/usr/bin/{x}" if x == "bwrap" else None
|
|
|
|
cmd = _get_sandbox_command(bot, "/path/to/script")
|
|
assert cmd is not None
|
|
assert "/usr/bin/bwrap" in cmd
|
|
|
|
|
|
def test_sandbox_detection_firejail():
|
|
"""Test firejail sandbox detection."""
|
|
bot = MagicMock()
|
|
bot.config.external_cogs_sandbox_enabled = True
|
|
bot.config.external_cogs_sandbox_type = "auto"
|
|
|
|
with patch("shutil.which") as mock_which, patch("sys.platform", "linux"):
|
|
mock_which.side_effect = lambda x: f"/usr/bin/{x}" if x == "firejail" else None
|
|
|
|
cmd = _get_sandbox_command(bot, "/path/to/script")
|
|
assert cmd is not None
|
|
assert "/usr/bin/firejail" in cmd
|
|
|
|
|
|
def test_cog_external_timeout_enforcement(external_cog_setup):
|
|
"""Test that external script cogs time out correctly."""
|
|
# Create a script that sleeps forever
|
|
cogs_dir = external_cog_setup / "cogs"
|
|
timeout_script = cogs_dir / "timeout.sh"
|
|
timeout_script.write_text("#!/bin/bash\nsleep 10")
|
|
os.chmod(timeout_script, os.stat(timeout_script).st_mode | stat.S_IEXEC)
|
|
|
|
config = BotConfig(
|
|
name="TestBot",
|
|
test_mode=True,
|
|
external_cogs_enabled=True,
|
|
external_cogs_sandbox_enabled=False,
|
|
external_cogs_timeout=1, # 1 second timeout
|
|
config_path=str(external_cog_setup),
|
|
storage_path=str(external_cog_setup / "storage"),
|
|
)
|
|
bot = LXMFBot(**config.__dict__)
|
|
bot.config_path = str(external_cog_setup)
|
|
|
|
load_cogs_from_directory(bot)
|
|
cmd = bot.commands["timeout"]
|
|
|
|
msg = MagicMock()
|
|
cmd.callback(msg)
|
|
|
|
msg.reply.assert_called_with("Error: Command timeout.sh timed out.")
|
|
|
|
|
|
def test_cog_external_timeout_disabled(external_cog_setup):
|
|
"""Test that external script cogs don't time out when timeout is 0."""
|
|
# Create a script that sleeps for 2 seconds
|
|
cogs_dir = external_cog_setup / "cogs"
|
|
sleep_script = cogs_dir / "sleep.sh"
|
|
sleep_script.write_text("#!/bin/bash\nsleep 1.5\necho 'Done sleeping'")
|
|
os.chmod(sleep_script, os.stat(sleep_script).st_mode | stat.S_IEXEC)
|
|
|
|
config = BotConfig(
|
|
name="TestBot",
|
|
test_mode=True,
|
|
external_cogs_enabled=True,
|
|
external_cogs_sandbox_enabled=False,
|
|
external_cogs_timeout=0, # Infinite timeout
|
|
config_path=str(external_cog_setup),
|
|
storage_path=str(external_cog_setup / "storage"),
|
|
)
|
|
bot = LXMFBot(**config.__dict__)
|
|
bot.config_path = str(external_cog_setup)
|
|
|
|
load_cogs_from_directory(bot)
|
|
cmd = bot.commands["sleep"]
|
|
|
|
msg = MagicMock()
|
|
cmd.callback(msg)
|
|
|
|
msg.reply.assert_called_with("Done sleeping")
|