test: 添加插件依赖机制自动化回归测试

- 新增 7 个测试用例固化插件依赖关系
- 验证 http 插件依赖 video
- 验证 ble/wifi/video/screen 插件无依赖
- 验证所有插件 ID 唯一性
- 验证拓扑排序正确性(依赖项先初始化)
- 所有 31 个测试通过

防止依赖关系漂移,确保架构稳定性。
This commit is contained in:
showen
2026-03-12 13:11:47 +08:00
parent 7091008f09
commit c48340dece
2 changed files with 153 additions and 0 deletions

View File

@@ -319,3 +319,101 @@ fn wifi_result_sent_to_manager_is_broadcast_to_plugins() {
assert!(has_event(&events, "msg:alpha:wifi_result:connected"));
assert!(has_event(&events, "msg:beta:wifi_result:connected"));
}
#[test]
fn http_plugin_must_depend_on_video() {
use crate::plugins::http::HttpPlugin;
let plugin = HttpPlugin::new();
let deps = plugin.dependencies();
assert_eq!(deps, vec!["video"], "http plugin must depend on video");
}
#[test]
fn ble_plugin_must_have_no_dependencies() {
use crate::plugins::ble::BlePlugin;
let plugin = BlePlugin::new();
let deps = plugin.dependencies();
assert!(deps.is_empty(), "ble plugin must have no dependencies");
}
#[test]
fn wifi_plugin_must_have_no_dependencies() {
use crate::plugins::wifi::WifiPlugin;
let plugin = WifiPlugin::new();
let deps = plugin.dependencies();
assert!(deps.is_empty(), "wifi plugin must have no dependencies");
}
#[test]
fn video_plugin_must_have_no_dependencies() {
use crate::plugins::video::VideoPlugin;
let plugin = VideoPlugin::new();
let deps = plugin.dependencies();
assert!(deps.is_empty(), "video plugin must have no dependencies");
}
#[test]
fn screen_plugin_must_have_no_dependencies() {
use crate::plugins::screen::ScreenPlugin;
let plugin = ScreenPlugin::new();
let deps = plugin.dependencies();
assert!(deps.is_empty(), "screen plugin must have no dependencies");
}
#[test]
fn all_plugin_ids_must_be_unique() {
use crate::plugins::ble::BlePlugin;
use crate::plugins::http::HttpPlugin;
use crate::plugins::screen::ScreenPlugin;
use crate::plugins::video::VideoPlugin;
use crate::plugins::wifi::WifiPlugin;
use std::collections::HashSet;
let plugins: Vec<Box<dyn Plugin>> = vec![
Box::new(BlePlugin::new()),
Box::new(HttpPlugin::new()),
Box::new(ScreenPlugin::new()),
Box::new(VideoPlugin::new()),
Box::new(WifiPlugin::new()),
];
let mut ids = HashSet::new();
for plugin in plugins {
let id = plugin.id();
assert!(ids.insert(id), "duplicate plugin id detected: '{}'", id);
}
}
#[test]
fn topological_sort_places_http_after_video() {
let events = Arc::new(Mutex::new(Vec::new()));
let mut manager = ServiceManager::new(test_config());
manager.register(Box::new(TestPlugin::new(
"http",
vec!["video"],
events.clone(),
)));
manager.register(Box::new(TestPlugin::new("video", vec![], events.clone())));
manager
.start_all()
.expect("start_all should succeed with http depending on video");
let event_log = lock_events(&events).clone();
let http_init_pos = event_log
.iter()
.position(|e| e == "init:http")
.expect("http should be initialized");
let video_init_pos = event_log
.iter()
.position(|e| e == "init:video")
.expect("video should be initialized");
assert!(
video_init_pos < http_init_pos,
"video must be initialized before http (video at {}, http at {})",
video_init_pos,
http_init_pos
);
}