#!/usr/bin/env python3 import importlib.util import py_compile import sys import tempfile import unittest from pathlib import Path PROJECT_ROOT = Path(__file__).resolve().parents[1] SDK_SRC = PROJECT_ROOT / "packages" / "jwebot-sdk" / "src" KERNEL_SRC = PROJECT_ROOT / "packages" / "jwebot-kernel" / "src" sys.path[:0] = [str(SDK_SRC), str(KERNEL_SRC)] SPEC = importlib.util.spec_from_file_location( "create_plugin", PROJECT_ROOT / "tools" / "create-plugin.py", ) MODULE = importlib.util.module_from_spec(SPEC) assert SPEC.loader is not None SPEC.loader.exec_module(MODULE) class CreatePluginTests(unittest.TestCase): def test_generator_creates_a_bounded_command_extension(self): with tempfile.TemporaryDirectory() as directory: destination = MODULE.create_plugin( Path(directory), "weather-command", "/weather", "Friend", "查询天气", ) self.assertTrue((destination / "plugin.toml").is_file()) manifest = (destination / "plugin.toml").read_text( encoding="utf-8" ) self.assertIn('description = "查询天气"', manifest) self.assertIn('help = ["/weather"]', manifest) module = destination / "src" / "weather_command.py" self.assertIn( 'context.commands.register("/weather", handle)', module.read_text(encoding="utf-8"), ) self.assertNotIn( "subprocess", module.read_text(encoding="utf-8"), ) py_compile.compile(str(module), doraise=True) py_compile.compile( str(destination / "tests" / "test_plugin.py"), doraise=True, ) def test_generator_refuses_to_overwrite_existing_plugin(self): with tempfile.TemporaryDirectory() as directory: output = Path(directory) MODULE.create_plugin( output, "weather-command", "/weather", "Friend", "查询天气", ) with self.assertRaises(FileExistsError): MODULE.create_plugin( output, "weather-command", "/weather", "Friend", "查询天气", ) def test_generator_rejects_path_traversal_plugin_id(self): with tempfile.TemporaryDirectory() as directory: with self.assertRaisesRegex(ValueError, "invalid format"): MODULE.create_plugin( Path(directory), "../outside", "/weather", "Friend", "查询天气", ) def test_generator_rejects_invalid_command(self): with tempfile.TemporaryDirectory() as directory: with self.assertRaisesRegex(ValueError, "invalid value"): MODULE.create_plugin( Path(directory), "weather-command", "weather", "Friend", "查询天气", "/weather", ) def test_generator_rejects_command_template_injection(self): with tempfile.TemporaryDirectory() as directory: with self.assertRaisesRegex(ValueError, "invalid value"): MODULE.create_plugin( Path(directory), "weather-command", '/"\\nentrypoint = "attacker:run', "Friend", "查询天气", "/weather", ) def test_generator_rejects_invalid_author(self): with tempfile.TemporaryDirectory() as directory: with self.assertRaisesRegex(ValueError, "author has an invalid format"): MODULE.create_plugin( Path(directory), "weather-command", "/weather", "../Friend", "查询天气", ) def test_generator_rejects_invalid_help_description(self): with tempfile.TemporaryDirectory() as directory: with self.assertRaisesRegex(ValueError, "invalid display"): MODULE.create_plugin( Path(directory), "weather-command", "/weather", "Friend", "查询天气", "plain text", ) if __name__ == "__main__": unittest.main()