251 lines
7.9 KiB
C++
251 lines
7.9 KiB
C++
#include <gtest/gtest.h>
|
|
#include <filesystem>
|
|
#include <thread>
|
|
#include <chrono>
|
|
#include "pipeline/output/output_manager.hpp"
|
|
#include "pipeline/common/logger.hpp"
|
|
|
|
namespace fs = std::filesystem;
|
|
|
|
namespace pipeline {
|
|
|
|
class OutputManagerTest : public ::testing::Test {
|
|
protected:
|
|
void SetUp() override {
|
|
// 创建测试目录
|
|
test_dir_ = "/tmp/test_output_manager";
|
|
if (fs::exists(test_dir_)) {
|
|
fs::remove_all(test_dir_);
|
|
}
|
|
fs::create_directories(test_dir_);
|
|
|
|
// 创建测试帧
|
|
test_frame_ = cv::Mat(480, 640, CV_8UC3, cv::Scalar(0, 0, 0));
|
|
}
|
|
|
|
void TearDown() override {
|
|
if (fs::exists(test_dir_)) {
|
|
fs::remove_all(test_dir_);
|
|
}
|
|
}
|
|
|
|
// 创建视频输出配置
|
|
OutputTargetConfig createVideoConfig(const std::string& name) {
|
|
OutputTargetConfig config;
|
|
config.type = "video";
|
|
config.name = name;
|
|
config.path = test_dir_ + "/" + name + ".mp4";
|
|
config.fps = 30;
|
|
config.codec = "h264";
|
|
config.bitrate = 4000000;
|
|
return config;
|
|
}
|
|
|
|
// 创建RTSP输出配置
|
|
OutputTargetConfig createRtspConfig(const std::string& name) {
|
|
OutputTargetConfig config;
|
|
config.type = "rtsp";
|
|
config.name = name;
|
|
config.path = "rtsp://localhost:8554/" + name;
|
|
config.fps = 30;
|
|
config.codec = "h264";
|
|
config.bitrate = 4000000;
|
|
return config;
|
|
}
|
|
|
|
std::string test_dir_;
|
|
cv::Mat test_frame_;
|
|
};
|
|
|
|
// 测试基本功能
|
|
TEST_F(OutputManagerTest, BasicFunctionality) {
|
|
OutputManager manager;
|
|
|
|
// 添加输出目标
|
|
auto video_config = createVideoConfig("test_video");
|
|
EXPECT_TRUE(manager.addTarget(video_config));
|
|
|
|
auto rtsp_config = createRtspConfig("test_rtsp");
|
|
EXPECT_TRUE(manager.addTarget(rtsp_config));
|
|
|
|
// 验证目标数量
|
|
EXPECT_EQ(manager.getTargetCount(), 2);
|
|
|
|
// 验证目标名称
|
|
auto names = manager.getTargetNames();
|
|
EXPECT_EQ(names.size(), 2);
|
|
EXPECT_TRUE(std::find(names.begin(), names.end(), "test_video") != names.end());
|
|
EXPECT_TRUE(std::find(names.begin(), names.end(), "test_rtsp") != names.end());
|
|
}
|
|
|
|
// 测试输入源到输出目标的映射
|
|
TEST_F(OutputManagerTest, SourceTargetMapping) {
|
|
OutputManager manager;
|
|
|
|
// 添加视频输出目标
|
|
OutputTargetConfig video_config;
|
|
video_config.type = "video";
|
|
video_config.name = "test_video_map";
|
|
video_config.path = "/tmp/test_output_manager/test_video_map.mp4";
|
|
ASSERT_TRUE(manager.addTarget(video_config));
|
|
|
|
// 添加源到目标的映射
|
|
ASSERT_TRUE(manager.addSourceTargetMapping("source1", {"test_video_map"}));
|
|
|
|
// 写入帧
|
|
ASSERT_TRUE(manager.writeFrames("source1", test_frame_));
|
|
|
|
// 验证输出文件存在
|
|
ASSERT_TRUE(fs::exists(video_config.path));
|
|
}
|
|
|
|
// 测试错误处理
|
|
TEST_F(OutputManagerTest, ErrorHandling) {
|
|
OutputManager manager;
|
|
|
|
// 测试添加重复目标
|
|
auto video_config = createVideoConfig("test_video_error");
|
|
EXPECT_TRUE(manager.addTarget(video_config));
|
|
EXPECT_FALSE(manager.addTarget(video_config));
|
|
|
|
// 测试无效的映射
|
|
std::vector<std::string> targets = {"non_existent_target"};
|
|
EXPECT_FALSE(manager.addSourceTargetMapping("source", targets));
|
|
|
|
// 测试写入不存在的源
|
|
EXPECT_FALSE(manager.writeFrames("non_existent_source", test_frame_));
|
|
|
|
// 测试空帧
|
|
cv::Mat empty_frame;
|
|
EXPECT_FALSE(manager.writeFrames("source", empty_frame));
|
|
}
|
|
|
|
// 测试资源管理
|
|
TEST_F(OutputManagerTest, ResourceManagement) {
|
|
OutputManager manager;
|
|
|
|
// 添加多个目标
|
|
auto video_config = createVideoConfig("test_video_resource");
|
|
EXPECT_TRUE(manager.addTarget(video_config));
|
|
|
|
auto rtsp_config = createRtspConfig("test_rtsp_resource");
|
|
EXPECT_TRUE(manager.addTarget(rtsp_config));
|
|
|
|
// 添加映射
|
|
std::vector<std::string> targets = {"test_video_resource", "test_rtsp_resource"};
|
|
EXPECT_TRUE(manager.addSourceTargetMapping("source", targets));
|
|
|
|
// 移除映射
|
|
EXPECT_TRUE(manager.removeSourceMapping("source"));
|
|
EXPECT_FALSE(manager.writeFrames("source", test_frame_));
|
|
|
|
// 移除目标
|
|
EXPECT_TRUE(manager.removeTarget("test_video_resource"));
|
|
EXPECT_EQ(manager.getTargetCount(), 1);
|
|
|
|
// 清理所有资源
|
|
manager.cleanup();
|
|
EXPECT_EQ(manager.getTargetCount(), 0);
|
|
}
|
|
|
|
// 测试并发写入
|
|
TEST_F(OutputManagerTest, ConcurrentWrite) {
|
|
OutputManager manager;
|
|
|
|
// 添加两个视频输出目标
|
|
auto video_config1 = createVideoConfig("test_video_concurrent1");
|
|
ASSERT_TRUE(manager.addTarget(video_config1));
|
|
|
|
auto video_config2 = createVideoConfig("test_video_concurrent2");
|
|
ASSERT_TRUE(manager.addTarget(video_config2));
|
|
|
|
// 添加源到目标的映射
|
|
ASSERT_TRUE(manager.addSourceTargetMapping("source1", {"test_video_concurrent1"}));
|
|
ASSERT_TRUE(manager.addSourceTargetMapping("source2", {"test_video_concurrent2"}));
|
|
|
|
// 创建两个线程同时写入不同的输出目标
|
|
std::thread t1([&]() {
|
|
for (int i = 0; i < 10; ++i) {
|
|
EXPECT_TRUE(manager.writeFrames("source1", test_frame_));
|
|
std::this_thread::sleep_for(std::chrono::milliseconds(10));
|
|
}
|
|
});
|
|
|
|
std::thread t2([&]() {
|
|
for (int i = 0; i < 10; ++i) {
|
|
EXPECT_TRUE(manager.writeFrames("source2", test_frame_));
|
|
std::this_thread::sleep_for(std::chrono::milliseconds(10));
|
|
}
|
|
});
|
|
|
|
// 等待线程完成
|
|
t1.join();
|
|
t2.join();
|
|
|
|
// 验证输出文件存在
|
|
ASSERT_TRUE(fs::exists(video_config1.path));
|
|
ASSERT_TRUE(fs::exists(video_config2.path));
|
|
}
|
|
|
|
// 测试一个输入源映射到多个输出目标
|
|
TEST_F(OutputManagerTest, MultipleTargetsMapping) {
|
|
OutputManager manager;
|
|
|
|
// 添加多个输出目标
|
|
auto video_config1 = createVideoConfig("test_video_multi1");
|
|
ASSERT_TRUE(manager.addTarget(video_config1));
|
|
|
|
auto video_config2 = createVideoConfig("test_video_multi2");
|
|
ASSERT_TRUE(manager.addTarget(video_config2));
|
|
|
|
auto video_config3 = createVideoConfig("test_video_multi3");
|
|
ASSERT_TRUE(manager.addTarget(video_config3));
|
|
|
|
// 将一个输入源映射到多个输出目标
|
|
std::vector<std::string> targets = {
|
|
"test_video_multi1",
|
|
"test_video_multi2",
|
|
"test_video_multi3"
|
|
};
|
|
ASSERT_TRUE(manager.addSourceTargetMapping("source_multi", targets));
|
|
|
|
// 写入帧到所有映射的目标
|
|
ASSERT_TRUE(manager.writeFrames("source_multi", test_frame_));
|
|
|
|
// 验证所有输出文件都存在
|
|
ASSERT_TRUE(fs::exists(video_config1.path));
|
|
ASSERT_TRUE(fs::exists(video_config2.path));
|
|
ASSERT_TRUE(fs::exists(video_config3.path));
|
|
}
|
|
|
|
// 测试FPS参数边界值
|
|
TEST_F(OutputManagerTest, FpsBoundaryTest) {
|
|
OutputManager manager;
|
|
|
|
// 测试FPS为0
|
|
auto config_fps_zero = createVideoConfig("test_video_fps_zero");
|
|
config_fps_zero.fps = 0;
|
|
EXPECT_FALSE(manager.addTarget(config_fps_zero));
|
|
|
|
// 测试FPS为负数
|
|
auto config_fps_negative = createVideoConfig("test_video_fps_negative");
|
|
config_fps_negative.fps = -30;
|
|
EXPECT_FALSE(manager.addTarget(config_fps_negative));
|
|
|
|
// 测试FPS为最小有效值
|
|
auto config_fps_min = createVideoConfig("test_video_fps_min");
|
|
config_fps_min.fps = 1;
|
|
EXPECT_TRUE(manager.addTarget(config_fps_min));
|
|
|
|
// 测试FPS为正常值
|
|
auto config_fps_normal = createVideoConfig("test_video_fps_normal");
|
|
config_fps_normal.fps = 60;
|
|
EXPECT_TRUE(manager.addTarget(config_fps_normal));
|
|
|
|
// 验证正常FPS的输出是否工作
|
|
ASSERT_TRUE(manager.addSourceTargetMapping("source_fps", {"test_video_fps_normal"}));
|
|
ASSERT_TRUE(manager.writeFrames("source_fps", test_frame_));
|
|
ASSERT_TRUE(fs::exists(config_fps_normal.path));
|
|
}
|
|
|
|
} // namespace pipeline
|