rtsp_tensorrt/tests/test_yaml_config.cpp
sladro e13cb3659c feat: 初始化项目结构
- 创建基本项目结构和目录
- 添加CMake构建系统
- 实现基础的配置解析功能
- 添加YOLO推理框架支持
- 集成RTSP和视频流处理功能
- 添加性能监控和日志系统
2024-12-24 16:25:03 +08:00

367 lines
9.8 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include <gtest/gtest.h>
#include "pipeline/common/yaml_config_parser.hpp"
#include <fstream>
#include <filesystem>
using namespace pipeline;
class YamlConfigTest : public ::testing::Test {
protected:
void SetUp() override {
// 创建测试配置文件
std::ofstream test_config("test_config.yaml");
test_config << R"(
input:
sources:
- type: rtsp
name: camera1
url: rtsp://example.com/stream1
buffer_size: 30
max_batch_size: 4
inference:
model:
onnx_path: /path/to/model.onnx
engine_path: /path/to/model.engine
input_shape: [3, 640, 640]
precision: FP16
threshold:
conf: 0.5
nms: 0.45
gpu_id: 0
render:
window:
name: "Detection Results"
width: 1280
height: 720
fullscreen: false
default_style:
box_color: [0, 255, 0]
text_color: [255, 255, 255]
transparency: 0.0
box_thickness: 2
font_scale: 0.5
font_thickness: 1
class_styles:
person:
box_color: [255, 0, 0]
text_color: [255, 255, 255]
transparency: 0.2
box_thickness: 2
font_scale: 0.5
font_thickness: 1
car:
box_color: [0, 255, 0]
text_color: [255, 255, 255]
transparency: 0.2
box_thickness: 2
font_scale: 0.5
font_thickness: 1
metrics:
show_fps: true
show_inference_time: true
show_gpu_usage: true
update_interval_ms: 1000
output:
targets:
- type: video
name: output1
path: /path/to/output.mp4
fps: 30
codec: h264
bitrate: 4000000
log:
level: info
save_path: logs/
)";
test_config.close();
}
void TearDown() override {
// 清理测试文件
std::filesystem::remove("test_config.yaml");
std::filesystem::remove("invalid_config.yaml");
}
};
TEST_F(YamlConfigTest, LoadConfig) {
auto parser = createConfigParser();
ASSERT_TRUE(parser->parse("test_config.yaml"));
const auto& config = parser->getConfig();
// 验证输入配置
ASSERT_EQ(config.input.sources.size(), 1);
EXPECT_EQ(config.input.sources[0].type, "rtsp");
EXPECT_EQ(config.input.sources[0].name, "camera1");
EXPECT_EQ(config.input.sources[0].url, "rtsp://example.com/stream1");
EXPECT_EQ(config.input.sources[0].buffer_size, 30);
EXPECT_EQ(config.input.max_batch_size, 4);
// 验证推理配置
EXPECT_EQ(config.inference.engine_path, "/path/to/model.engine");
ASSERT_EQ(config.inference.input_shape.size(), 3);
EXPECT_EQ(config.inference.input_shape[0], 3);
EXPECT_EQ(config.inference.input_shape[1], 640);
EXPECT_EQ(config.inference.input_shape[2], 640);
EXPECT_EQ(config.inference.precision, "FP16");
EXPECT_FLOAT_EQ(config.inference.threshold.conf, 0.5f);
EXPECT_FLOAT_EQ(config.inference.threshold.nms, 0.45f);
EXPECT_EQ(config.inference.gpu_id, 0);
// 验证渲染配置
// 窗口配置
EXPECT_EQ(config.render.window.name, "Detection Results");
EXPECT_EQ(config.render.window.width, 1280);
EXPECT_EQ(config.render.window.height, 720);
EXPECT_FALSE(config.render.window.fullscreen);
// 默认样式
EXPECT_EQ(config.render.default_style.box_color, cv::Scalar(0, 255, 0));
EXPECT_EQ(config.render.default_style.text_color, cv::Scalar(255, 255, 255));
EXPECT_FLOAT_EQ(config.render.default_style.transparency, 0.0f);
EXPECT_EQ(config.render.default_style.box_thickness, 2);
EXPECT_DOUBLE_EQ(config.render.default_style.font_scale, 0.5);
EXPECT_EQ(config.render.default_style.font_thickness, 1);
// 类别样式
ASSERT_EQ(config.render.class_styles.size(), 2);
const auto& person_style = config.render.class_styles.at("person");
EXPECT_EQ(person_style.box_color, cv::Scalar(255, 0, 0));
EXPECT_EQ(person_style.text_color, cv::Scalar(255, 255, 255));
EXPECT_FLOAT_EQ(person_style.transparency, 0.2f);
const auto& car_style = config.render.class_styles.at("car");
EXPECT_EQ(car_style.box_color, cv::Scalar(0, 255, 0));
EXPECT_EQ(car_style.text_color, cv::Scalar(255, 255, 255));
EXPECT_FLOAT_EQ(car_style.transparency, 0.2f);
// 性能指标配置
EXPECT_TRUE(config.render.metrics.show_fps);
EXPECT_TRUE(config.render.metrics.show_inference_time);
EXPECT_TRUE(config.render.metrics.show_gpu_usage);
EXPECT_EQ(config.render.metrics.update_interval_ms, 1000);
// 验证输出配置
ASSERT_EQ(config.output.targets.size(), 1);
EXPECT_EQ(config.output.targets[0].type, "video");
EXPECT_EQ(config.output.targets[0].name, "output1");
EXPECT_EQ(config.output.targets[0].path, "/path/to/output.mp4");
EXPECT_EQ(config.output.targets[0].fps, 30);
EXPECT_EQ(config.output.targets[0].codec, "h264");
EXPECT_EQ(config.output.targets[0].bitrate, 4000000);
// 验证日志配置
EXPECT_EQ(config.log.level, "info");
EXPECT_EQ(config.log.save_path, "logs/");
}
TEST_F(YamlConfigTest, InvalidConfig) {
auto parser = createConfigParser();
// 测试不存在的文件
EXPECT_FALSE(parser->parse("non_existent.yaml"));
// 创建无效的配置文件
std::ofstream invalid_config("invalid_config.yaml");
invalid_config << R"(
input:
sources: [] #
)";
invalid_config.close();
// 测试无效的配置
EXPECT_FALSE(parser->parse("invalid_config.yaml"));
}
TEST_F(YamlConfigTest, InvalidConfigs) {
auto parser = createConfigParser();
// 测试各种无效配置场景
std::vector<std::pair<std::string, std::string>> invalid_configs = {
// 空输入源
{R"(
input:
sources: []
inference:
model:
engine_path: /path/to/model.engine
input_shape: [3, 640, 640]
)", ""},
// 无效的输入源配置
{R"(
input:
sources:
- type: rtsp
name: "" #
url: rtsp://example.com/stream1
inference:
model:
engine_path: /path/to/model.engine
input_shape: [3, 640, 640]
)", ""},
// 无效的推理配置
{R"(
input:
sources:
- type: rtsp
name: camera1
url: rtsp://example.com/stream1
inference:
model:
engine_path: "" #
input_shape: [3, 640, 640]
)", ""},
// 无效的渲染配置
{R"(
input:
sources:
- type: rtsp
name: camera1
url: rtsp://example.com/stream1
inference:
model:
engine_path: /path/to/model.engine
input_shape: [3, 640, 640]
render:
window:
name: "Detection Results"
width: -1 #
height: 720
)", ""},
// 无效的样式配置
{R"(
input:
sources:
- type: rtsp
name: camera1
url: rtsp://example.com/stream1
inference:
model:
engine_path: /path/to/model.engine
input_shape: [3, 640, 640]
render:
window:
name: "Detection Results"
width: 1280
height: 720
default_style:
transparency: 2.0 #
)", ""},
// 无效的输出配置
{R"(
input:
sources:
- type: rtsp
name: camera1
url: rtsp://example.com/stream1
inference:
model:
engine_path: /path/to/model.engine
input_shape: [3, 640, 640]
output:
targets:
- type: video
name: output1
path: "" #
fps: 30
)", ""},
// 无效的日志配置
{R"(
input:
sources:
- type: rtsp
name: camera1
url: rtsp://example.com/stream1
inference:
model:
engine_path: /path/to/model.engine
input_shape: [3, 640, 640]
log:
level: "" #
save_path: logs/
)", ""}
};
for (const auto& [config_str, desc] : invalid_configs) {
std::ofstream config_file("invalid_config.yaml");
config_file << config_str;
config_file.close();
EXPECT_FALSE(parser->parse("invalid_config.yaml")) << "应该检测到无效配置: " << desc;
std::filesystem::remove("invalid_config.yaml");
}
}
TEST_F(YamlConfigTest, ValidateThresholds) {
auto parser = createConfigParser();
// 测试阈值验证
std::string config_str = R"(
input:
sources:
- type: rtsp
name: camera1
url: rtsp://example.com/stream1
inference:
model:
engine_path: /path/to/model.engine
input_shape: [3, 640, 640]
threshold:
conf: 1.5 #
nms: 0.45
)";
std::ofstream config_file("invalid_threshold.yaml");
config_file << config_str;
config_file.close();
EXPECT_FALSE(parser->parse("invalid_threshold.yaml"));
std::filesystem::remove("invalid_threshold.yaml");
}
TEST_F(YamlConfigTest, ValidateClassStyles) {
auto parser = createConfigParser();
// 测试类别样式验证
std::string config_str = R"(
input:
sources:
- type: rtsp
name: camera1
url: rtsp://example.com/stream1
inference:
model:
engine_path: /path/to/model.engine
input_shape: [3, 640, 640]
render:
window:
name: "Detection Results"
width: 1280
height: 720
class_styles:
"": #
box_color: [255, 0, 0]
text_color: [255, 255, 255]
transparency: 0.2
)";
std::ofstream config_file("invalid_class_style.yaml");
config_file << config_str;
config_file.close();
EXPECT_FALSE(parser->parse("invalid_class_style.yaml"));
std::filesystem::remove("invalid_class_style.yaml");
}