#include #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({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"); }