326 lines
10 KiB
C++
326 lines
10 KiB
C++
#include <gtest/gtest.h>
|
|
#include "pipeline/common/config_parser.hpp"
|
|
|
|
using namespace pipeline;
|
|
|
|
// 测试配置数据结构的默认值
|
|
TEST(ConfigParserTest, DefaultValues) {
|
|
// 测试InputSourceConfig默认值
|
|
InputSourceConfig input_source;
|
|
EXPECT_EQ(input_source.buffer_size, 30);
|
|
EXPECT_TRUE(input_source.type.empty());
|
|
EXPECT_TRUE(input_source.name.empty());
|
|
EXPECT_TRUE(input_source.url.empty());
|
|
EXPECT_TRUE(input_source.outputs.empty());
|
|
|
|
// 测试InputConfig默认值
|
|
InputConfig input;
|
|
EXPECT_EQ(input.max_batch_size, 4);
|
|
EXPECT_TRUE(input.sources.empty());
|
|
|
|
// 测试ModelConfig默认值
|
|
ModelConfig model;
|
|
EXPECT_TRUE(model.engine_path.empty());
|
|
EXPECT_EQ(model.input_shape, std::vector<int>({3, 640, 640}));
|
|
EXPECT_EQ(model.precision, "FP16");
|
|
EXPECT_FLOAT_EQ(model.threshold.conf, 0.5f);
|
|
EXPECT_FLOAT_EQ(model.threshold.nms, 0.45f);
|
|
EXPECT_EQ(model.gpu_id, 0);
|
|
EXPECT_TRUE(model.labels.empty());
|
|
EXPECT_TRUE(model.version.empty());
|
|
|
|
// 测试RenderConfig默认值
|
|
RenderConfig render;
|
|
EXPECT_EQ(render.window.name, "Detection Results");
|
|
EXPECT_EQ(render.window.width, 1280);
|
|
EXPECT_EQ(render.window.height, 720);
|
|
EXPECT_FALSE(render.window.fullscreen);
|
|
|
|
// 测试默认渲染样式
|
|
EXPECT_EQ(render.default_style.box_color, cv::Scalar(0, 255, 0));
|
|
EXPECT_EQ(render.default_style.text_color, cv::Scalar(255, 255, 255));
|
|
EXPECT_FLOAT_EQ(render.default_style.transparency, 0.0f);
|
|
EXPECT_EQ(render.default_style.box_thickness, 2);
|
|
EXPECT_DOUBLE_EQ(render.default_style.font_scale, 0.5);
|
|
EXPECT_EQ(render.default_style.font_thickness, 1);
|
|
|
|
// 测试性能指标显示设置
|
|
EXPECT_TRUE(render.metrics.show_fps);
|
|
EXPECT_TRUE(render.metrics.show_inference_time);
|
|
EXPECT_TRUE(render.metrics.show_gpu_usage);
|
|
EXPECT_EQ(render.metrics.update_interval_ms, 1000);
|
|
|
|
// 测试OutputTargetConfig默认值
|
|
OutputTargetConfig output_target;
|
|
EXPECT_TRUE(output_target.type.empty());
|
|
EXPECT_TRUE(output_target.name.empty());
|
|
EXPECT_TRUE(output_target.path.empty());
|
|
EXPECT_EQ(output_target.fps, 30);
|
|
EXPECT_EQ(output_target.codec, "h264");
|
|
EXPECT_EQ(output_target.bitrate, 4000000);
|
|
|
|
// 测试LogConfig默认值
|
|
LogConfig log;
|
|
EXPECT_EQ(log.level, "info");
|
|
EXPECT_EQ(log.save_path, "logs/");
|
|
}
|
|
|
|
// 测试配置数据结构的赋值
|
|
TEST(ConfigParserTest, Assignment) {
|
|
// 测试InputSourceConfig赋值
|
|
InputSourceConfig input_source;
|
|
input_source.type = "rtsp";
|
|
input_source.name = "camera1";
|
|
input_source.url = "rtsp://example.com";
|
|
input_source.buffer_size = 50;
|
|
input_source.outputs = {"output1", "output2"};
|
|
|
|
EXPECT_EQ(input_source.type, "rtsp");
|
|
EXPECT_EQ(input_source.name, "camera1");
|
|
EXPECT_EQ(input_source.url, "rtsp://example.com");
|
|
EXPECT_EQ(input_source.buffer_size, 50);
|
|
EXPECT_EQ(input_source.outputs.size(), 2);
|
|
|
|
// 测试完整Pipeline配置
|
|
PipelineConfig config;
|
|
|
|
// 设置输入配置
|
|
config.input.max_batch_size = 8;
|
|
config.input.sources.push_back(input_source);
|
|
|
|
// 设置推理配置
|
|
config.inference.engine_path = "/path/to/model.engine";
|
|
config.inference.precision = "FP32";
|
|
config.inference.threshold.conf = 0.6f;
|
|
config.inference.labels = {"person", "car"};
|
|
config.inference.version = "yolov8";
|
|
|
|
// 设置渲染配置
|
|
RenderConfig::ClassStyle style;
|
|
style.box_color = cv::Scalar(255, 0, 0);
|
|
config.render.class_styles["person"] = style;
|
|
|
|
// 验证设置的值
|
|
EXPECT_EQ(config.input.max_batch_size, 8);
|
|
EXPECT_EQ(config.input.sources.size(), 1);
|
|
EXPECT_EQ(config.inference.engine_path, "/path/to/model.engine");
|
|
EXPECT_EQ(config.inference.precision, "FP32");
|
|
EXPECT_FLOAT_EQ(config.inference.threshold.conf, 0.6f);
|
|
EXPECT_EQ(config.inference.labels.size(), 2);
|
|
EXPECT_EQ(config.inference.version, "yolov8");
|
|
EXPECT_EQ(config.render.class_styles.size(), 1);
|
|
}
|
|
|
|
// 测试渲染样式配置
|
|
TEST(ConfigParserTest, RenderStyleConfig) {
|
|
RenderConfig render;
|
|
|
|
// 设置自定义样式
|
|
RenderConfig::ClassStyle person_style;
|
|
person_style.box_color = cv::Scalar(255, 0, 0); // BGR
|
|
person_style.text_color = cv::Scalar(255, 255, 255);
|
|
person_style.transparency = 0.2f;
|
|
render.class_styles["person"] = person_style;
|
|
|
|
// 验证样式设置
|
|
EXPECT_EQ(render.class_styles.size(), 1);
|
|
EXPECT_EQ(render.class_styles["person"].box_color, cv::Scalar(255, 0, 0));
|
|
EXPECT_EQ(render.class_styles["person"].text_color, cv::Scalar(255, 255, 255));
|
|
EXPECT_FLOAT_EQ(render.class_styles["person"].transparency, 0.2f);
|
|
}
|
|
|
|
// 测试模型标签和版本配置
|
|
TEST(ConfigParserTest, ModelLabelsAndVersion) {
|
|
// 测试ModelConfig的新增字段默认值
|
|
ModelConfig model;
|
|
EXPECT_TRUE(model.labels.empty());
|
|
EXPECT_TRUE(model.version.empty());
|
|
|
|
// 测试标签配置
|
|
model.labels = {"person", "car", "truck"};
|
|
EXPECT_EQ(model.labels.size(), 3);
|
|
EXPECT_EQ(model.labels[0], "person");
|
|
EXPECT_EQ(model.labels[1], "car");
|
|
EXPECT_EQ(model.labels[2], "truck");
|
|
|
|
// 测试版本配置
|
|
model.version = "yolov8";
|
|
EXPECT_EQ(model.version, "yolov8");
|
|
|
|
// 测试完整Pipeline配置中的标签和版本
|
|
PipelineConfig config;
|
|
config.inference.labels = {"person", "car", "truck"};
|
|
config.inference.version = "yolov8";
|
|
|
|
EXPECT_EQ(config.inference.labels.size(), 3);
|
|
EXPECT_EQ(config.inference.version, "yolov8");
|
|
}
|
|
|
|
// 测试渲染样式与标签的匹配
|
|
TEST(ConfigParserTest, RenderStyleLabelMapping) {
|
|
PipelineConfig config;
|
|
|
|
// 设置模型标签
|
|
config.inference.labels = {"person", "car", "truck"};
|
|
|
|
// 设置渲染样式
|
|
RenderConfig::ClassStyle person_style;
|
|
person_style.box_color = cv::Scalar(255, 0, 0); // BGR
|
|
config.render.class_styles["person"] = person_style;
|
|
|
|
RenderConfig::ClassStyle car_style;
|
|
car_style.box_color = cv::Scalar(0, 255, 0);
|
|
config.render.class_styles["car"] = car_style;
|
|
|
|
// 验证标签和样式的匹配
|
|
EXPECT_EQ(config.render.class_styles.count("person"), 1);
|
|
EXPECT_EQ(config.render.class_styles.count("car"), 1);
|
|
EXPECT_EQ(config.render.class_styles["person"].box_color, cv::Scalar(255, 0, 0));
|
|
EXPECT_EQ(config.render.class_styles["car"].box_color, cv::Scalar(0, 255, 0));
|
|
|
|
// 验证未配置样式的标签使用默认样式
|
|
EXPECT_EQ(config.render.class_styles.count("truck"), 0);
|
|
}
|
|
|
|
// 测试输入输出映射配置
|
|
TEST(ConfigParserTest, InputOutputMapping) {
|
|
// 创建配置解析器
|
|
auto parser = createConfigParser();
|
|
|
|
// 创建测试配置文件
|
|
std::ofstream config_file("test_mapping.yaml");
|
|
config_file << R"(
|
|
input:
|
|
sources:
|
|
- type: video
|
|
name: "video1"
|
|
url: "/test/video1.mp4"
|
|
buffer_size: 30
|
|
output_targets: ["output1"]
|
|
- type: rtsp
|
|
name: "camera1"
|
|
url: "rtsp://test/stream1"
|
|
buffer_size: 30
|
|
output_targets: ["output2", "stream1"]
|
|
max_batch_size: 4
|
|
|
|
output:
|
|
targets:
|
|
- type: "video"
|
|
name: "output1"
|
|
path: "/output/video1.mp4"
|
|
fps: 30
|
|
codec: "h264"
|
|
- type: "video"
|
|
name: "output2"
|
|
path: "/output/video2.mp4"
|
|
fps: 30
|
|
codec: "h264"
|
|
- type: "rtsp"
|
|
name: "stream1"
|
|
path: "rtsp://localhost:8554/live"
|
|
fps: 30
|
|
codec: "h264"
|
|
)";
|
|
config_file.close();
|
|
|
|
// 解析配置文件
|
|
ASSERT_TRUE(parser->parse("test_mapping.yaml"));
|
|
ASSERT_TRUE(parser->validate());
|
|
|
|
const auto& config = parser->getConfig();
|
|
|
|
// 验证输入源配置
|
|
ASSERT_EQ(config.input.sources.size(), 2);
|
|
|
|
// 验证第一个输入源的输出映射
|
|
const auto& source1 = config.input.sources[0];
|
|
EXPECT_EQ(source1.name, "video1");
|
|
ASSERT_EQ(source1.outputs.size(), 1);
|
|
EXPECT_EQ(source1.outputs[0], "output1");
|
|
|
|
// 验证第二个输入源的输出映射
|
|
const auto& source2 = config.input.sources[1];
|
|
EXPECT_EQ(source2.name, "camera1");
|
|
ASSERT_EQ(source2.outputs.size(), 2);
|
|
EXPECT_EQ(source2.outputs[0], "output2");
|
|
EXPECT_EQ(source2.outputs[1], "stream1");
|
|
|
|
// 验证输出目标配置
|
|
ASSERT_EQ(config.output.targets.size(), 3);
|
|
|
|
// 清理测试文件
|
|
std::filesystem::remove("test_mapping.yaml");
|
|
}
|
|
|
|
// 测试无效的输出目标映射
|
|
TEST(ConfigParserTest, InvalidOutputMapping) {
|
|
auto parser = createConfigParser();
|
|
|
|
// 创建测试配置文件,包含无效的输出目标
|
|
std::ofstream config_file("invalid_mapping.yaml");
|
|
config_file << R"(
|
|
input:
|
|
sources:
|
|
- type: video
|
|
name: "video1"
|
|
url: "/test/video1.mp4"
|
|
output_targets: ["nonexistent_output"] # 不存在的输出目标
|
|
max_batch_size: 4
|
|
|
|
output:
|
|
targets:
|
|
- type: "video"
|
|
name: "output1"
|
|
path: "/output/video1.mp4"
|
|
fps: 30
|
|
codec: "h264"
|
|
)";
|
|
config_file.close();
|
|
|
|
// 解析配置文件应该成功,但验证应该失败
|
|
ASSERT_TRUE(parser->parse("invalid_mapping.yaml"));
|
|
ASSERT_FALSE(parser->validate()); // 验证应该失败,因为输出目标不存在
|
|
|
|
// 清理测试文件
|
|
std::filesystem::remove("invalid_mapping.yaml");
|
|
}
|
|
|
|
// 测试向后兼容性
|
|
TEST(ConfigParserTest, BackwardCompatibility) {
|
|
auto parser = createConfigParser();
|
|
|
|
// 创建使用旧格式的测试配置文件
|
|
std::ofstream config_file("old_format.yaml");
|
|
config_file << R"(
|
|
input:
|
|
sources:
|
|
- type: video
|
|
name: "video1"
|
|
url: "/test/video1.mp4"
|
|
outputs: ["output1"] # 旧格式使用outputs而不是output_targets
|
|
max_batch_size: 4
|
|
|
|
output:
|
|
targets:
|
|
- type: "video"
|
|
name: "output1"
|
|
path: "/output/video1.mp4"
|
|
fps: 30
|
|
codec: "h264"
|
|
)";
|
|
config_file.close();
|
|
|
|
// 解析和验证应该都成功
|
|
ASSERT_TRUE(parser->parse("old_format.yaml"));
|
|
ASSERT_TRUE(parser->validate());
|
|
|
|
const auto& config = parser->getConfig();
|
|
ASSERT_EQ(config.input.sources.size(), 1);
|
|
ASSERT_EQ(config.input.sources[0].outputs.size(), 1);
|
|
EXPECT_EQ(config.input.sources[0].outputs[0], "output1");
|
|
|
|
// 清理测试文件
|
|
std::filesystem::remove("old_format.yaml");
|
|
}
|