Title: Implement minimal core framework with PL injection and update build config
Key features implemented: - Updated package metadata and dependencies in PKG-INFO, setup files - Added main.py entry point for backward compatibility with README launch method - Enhanced CLI with config options, system info command, and proper signal handling - Implemented minimal PluginManager loading only plugin-loader core plugin - Refactored PluginLoader to follow minimal core design, removed sandbox/isolation complexity - Updated auto-dependency plugin with safer PL injection mechanism and disabled pl_injection - Removed legacy plugin files (firewall, frp_proxy, ftp_server, multi_lang_deploy, ops_toolbox, security_gateway) as functionality moved to core plugin system - Improved gitignore with comprehensive ignore patterns The changes implement a minimal core framework design where only the plugin-loader is directly loaded by the core, with all other plugins managed through the PL injection mechanism, significantly simplifying the architecture.
This commit is contained in:
39
tests/test_cli.py
Normal file
39
tests/test_cli.py
Normal file
@@ -0,0 +1,39 @@
|
||||
"""CLI 命令单元测试"""
|
||||
import pytest
|
||||
from click.testing import CliRunner
|
||||
from oss.cli import cli, version, serve
|
||||
|
||||
|
||||
class TestCLI:
|
||||
"""测试 CLI 命令"""
|
||||
|
||||
def test_version_command(self):
|
||||
"""测试版本命令"""
|
||||
runner = CliRunner()
|
||||
result = runner.invoke(version)
|
||||
|
||||
assert result.exit_code == 0
|
||||
assert "Future OSS" in result.output
|
||||
assert "1.2.0" in result.output
|
||||
|
||||
def test_cli_help(self):
|
||||
"""测试 CLI 帮助信息"""
|
||||
runner = CliRunner()
|
||||
result = runner.invoke(cli, ['--help'])
|
||||
|
||||
assert result.exit_code == 0
|
||||
assert "Future OSS" in result.output
|
||||
assert "serve" in result.output
|
||||
assert "version" in result.output
|
||||
|
||||
def test_serve_command_exists(self):
|
||||
"""测试 serve 命令存在"""
|
||||
runner = CliRunner()
|
||||
result = runner.invoke(serve, ['--help'])
|
||||
|
||||
assert result.exit_code == 0
|
||||
assert "启动 Future OSS" in result.output
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
pytest.main([__file__, "-v"])
|
||||
105
tests/test_config.py
Normal file
105
tests/test_config.py
Normal file
@@ -0,0 +1,105 @@
|
||||
"""配置管理测试"""
|
||||
import os
|
||||
import pytest
|
||||
from pathlib import Path
|
||||
import tempfile
|
||||
import json
|
||||
|
||||
from oss.config.config import Config
|
||||
|
||||
|
||||
class TestConfig:
|
||||
"""配置管理测试类"""
|
||||
|
||||
def test_default_values(self):
|
||||
"""测试默认配置值"""
|
||||
config = Config()
|
||||
assert config.http_api_port == 8080
|
||||
assert config.http_tcp_port == 8082
|
||||
assert config.host == "0.0.0.0"
|
||||
assert config.log_level == "INFO"
|
||||
assert config.permission_check is True
|
||||
|
||||
def test_env_override(self, monkeypatch):
|
||||
"""测试环境变量覆盖"""
|
||||
monkeypatch.setenv("HTTP_API_PORT", "9999")
|
||||
monkeypatch.setenv("LOG_LEVEL", "DEBUG")
|
||||
|
||||
config = Config()
|
||||
assert config.http_api_port == 9999
|
||||
assert config.log_level == "DEBUG"
|
||||
|
||||
def test_file_config(self):
|
||||
"""测试配置文件加载"""
|
||||
with tempfile.NamedTemporaryFile(mode='w', suffix='.json', delete=False) as f:
|
||||
json.dump({"HTTP_API_PORT": 7777, "LOG_LEVEL": "WARNING"}, f)
|
||||
temp_path = f.name
|
||||
|
||||
try:
|
||||
config = Config(temp_path)
|
||||
assert config.http_api_port == 7777
|
||||
assert config.log_level == "WARNING"
|
||||
finally:
|
||||
os.unlink(temp_path)
|
||||
|
||||
def test_env_priority_over_file(self, monkeypatch):
|
||||
"""测试环境变量优先级高于配置文件"""
|
||||
with tempfile.NamedTemporaryFile(mode='w', suffix='.json', delete=False) as f:
|
||||
json.dump({"HTTP_API_PORT": 7777}, f)
|
||||
temp_path = f.name
|
||||
|
||||
try:
|
||||
monkeypatch.setenv("HTTP_API_PORT", "8888")
|
||||
config = Config(temp_path)
|
||||
assert config.http_api_port == 8888 # 环境变量优先
|
||||
finally:
|
||||
os.unlink(temp_path)
|
||||
monkeypatch.delenv("HTTP_API_PORT", raising=False)
|
||||
|
||||
def test_get_set(self):
|
||||
"""测试 get/set 方法"""
|
||||
config = Config()
|
||||
assert config.get("HTTP_API_PORT") == 8080
|
||||
config.set("HTTP_API_PORT", 6666)
|
||||
assert config.get("HTTP_API_PORT") == 6666
|
||||
|
||||
def test_properties(self):
|
||||
"""测试属性访问"""
|
||||
config = Config()
|
||||
assert isinstance(config.data_dir, Path)
|
||||
assert isinstance(config.store_dir, Path)
|
||||
assert config.data_dir.name == "data"
|
||||
assert config.store_dir.name == "store"
|
||||
|
||||
def test_all_method(self):
|
||||
"""测试 all() 方法返回所有配置"""
|
||||
config = Config()
|
||||
all_config = config.all()
|
||||
assert "HTTP_API_PORT" in all_config
|
||||
assert "HOST" in all_config
|
||||
assert len(all_config) > 5
|
||||
|
||||
def test_bool_conversion(self, monkeypatch):
|
||||
"""测试布尔值转换"""
|
||||
monkeypatch.setenv("PERMISSION_CHECK", "false")
|
||||
config = Config()
|
||||
assert config.permission_check is False
|
||||
|
||||
monkeypatch.setenv("PERMISSION_CHECK", "true")
|
||||
config = Config()
|
||||
assert config.permission_check is True
|
||||
|
||||
def test_int_conversion(self, monkeypatch):
|
||||
"""测试整数转换"""
|
||||
monkeypatch.setenv("MAX_WORKERS", "8")
|
||||
config = Config()
|
||||
assert config.get("MAX_WORKERS") == 8
|
||||
|
||||
# 无效值应该保持默认
|
||||
monkeypatch.setenv("MAX_WORKERS", "invalid")
|
||||
config = Config()
|
||||
assert config.get("MAX_WORKERS") == 4 # 默认值
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
pytest.main([__file__, "-v"])
|
||||
48
tests/test_plugin_loader.py
Normal file
48
tests/test_plugin_loader.py
Normal file
@@ -0,0 +1,48 @@
|
||||
"""插件加载器单元测试"""
|
||||
import pytest
|
||||
from pathlib import Path
|
||||
from oss.plugin.loader import PluginLoader
|
||||
|
||||
|
||||
class TestPluginLoader:
|
||||
"""测试插件加载器核心功能"""
|
||||
|
||||
def test_loader_initialization(self):
|
||||
"""测试加载器初始化"""
|
||||
loader = PluginLoader()
|
||||
assert loader.loaded == {}
|
||||
|
||||
def test_load_nonexistent_plugin(self):
|
||||
"""测试加载不存在的插件"""
|
||||
loader = PluginLoader()
|
||||
result = loader.load_core_plugin("nonexistent-plugin")
|
||||
assert result is None
|
||||
|
||||
def test_load_plugin_loader(self):
|
||||
"""测试加载 plugin-loader 核心插件"""
|
||||
loader = PluginLoader()
|
||||
result = loader.load_core_plugin("plugin-loader")
|
||||
|
||||
assert result is not None
|
||||
assert "instance" in result
|
||||
assert "module" in result
|
||||
assert "path" in result
|
||||
assert "name" in result
|
||||
assert result["name"] == "plugin-loader"
|
||||
assert hasattr(result["instance"], "init")
|
||||
assert hasattr(result["instance"], "start")
|
||||
assert hasattr(result["instance"], "stop")
|
||||
|
||||
def test_loaded_plugins_tracking(self):
|
||||
"""测试已加载插件跟踪"""
|
||||
loader = PluginLoader()
|
||||
initial_count = len(loader.loaded)
|
||||
|
||||
loader.load_core_plugin("plugin-loader")
|
||||
|
||||
assert len(loader.loaded) == initial_count + 1
|
||||
assert "plugin-loader" in loader.loaded
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
pytest.main([__file__, "-v"])
|
||||
53
tests/test_plugin_manager.py
Normal file
53
tests/test_plugin_manager.py
Normal file
@@ -0,0 +1,53 @@
|
||||
"""插件管理器单元测试"""
|
||||
import pytest
|
||||
from oss.plugin.manager import PluginManager
|
||||
|
||||
|
||||
class TestPluginManager:
|
||||
"""测试插件管理器核心功能"""
|
||||
|
||||
def test_manager_initialization(self):
|
||||
"""测试管理器初始化"""
|
||||
manager = PluginManager()
|
||||
assert manager.plugin_loader is None
|
||||
assert manager.loader is not None
|
||||
|
||||
def test_manager_load(self):
|
||||
"""测试管理器加载 plugin-loader"""
|
||||
manager = PluginManager()
|
||||
manager.load()
|
||||
|
||||
assert manager.plugin_loader is not None
|
||||
assert hasattr(manager.plugin_loader, "init")
|
||||
assert hasattr(manager.plugin_loader, "start")
|
||||
assert hasattr(manager.plugin_loader, "stop")
|
||||
|
||||
def test_manager_start_without_load(self):
|
||||
"""测试未加载时启动(应安全处理)"""
|
||||
manager = PluginManager()
|
||||
# 不应抛出异常
|
||||
manager.start()
|
||||
|
||||
def test_manager_stop_without_load(self):
|
||||
"""测试未加载时停止(应安全处理)"""
|
||||
manager = PluginManager()
|
||||
# 不应抛出异常
|
||||
manager.stop()
|
||||
|
||||
def test_manager_lifecycle(self):
|
||||
"""测试完整生命周期"""
|
||||
manager = PluginManager()
|
||||
|
||||
# 加载
|
||||
manager.load()
|
||||
assert manager.plugin_loader is not None
|
||||
|
||||
# 启动(会初始化所有插件)
|
||||
# 注意:实际启动需要完整环境,这里只测试方法存在
|
||||
assert callable(manager.plugin_loader.init)
|
||||
assert callable(manager.plugin_loader.start)
|
||||
assert callable(manager.plugin_loader.stop)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
pytest.main([__file__, "-v"])
|
||||
Reference in New Issue
Block a user