Init: Migrate SimpleRemoter (Since v1.3.1) to Gitea

This commit is contained in:
yuanyuanxiang
2026-04-19 19:55:01 +02:00
commit 5a325a202b
744 changed files with 235562 additions and 0 deletions

View File

@@ -0,0 +1,691 @@
// QualityAdaptiveTest.cpp - Phase 4: 质量自适应单元测试
// 测试 RTT 到质量等级的映射和防抖策略
#include <gtest/gtest.h>
#include <vector>
#include <cstdint>
#include <climits>
// ============================================
// 质量等级枚举 (来自 commands.h)
// ============================================
enum QualityLevel {
QUALITY_DISABLED = -2, // 关闭质量控制
QUALITY_ADAPTIVE = -1, // 自适应模式
QUALITY_ULTRA = 0, // 极佳(局域网)
QUALITY_HIGH = 1, // 优秀
QUALITY_GOOD = 2, // 良好
QUALITY_MEDIUM = 3, // 一般
QUALITY_LOW = 4, // 较差
QUALITY_MINIMAL = 5, // 最低
QUALITY_COUNT = 6,
};
// ============================================
// 算法枚举
// ============================================
#define ALGORITHM_GRAY 0
#define ALGORITHM_DIFF 1
#define ALGORITHM_H264 2
#define ALGORITHM_RGB565 3
// ============================================
// 质量配置结构体 (来自 commands.h)
// ============================================
struct QualityProfile {
int maxFPS; // 最大帧率
int maxWidth; // 最大宽度 (0=不限)
int algorithm; // 压缩算法
int bitRate; // kbps (仅H264使用)
};
// 默认质量配置表
static const QualityProfile g_QualityProfiles[QUALITY_COUNT] = {
{25, 0, ALGORITHM_DIFF, 0 }, // Ultra: 25FPS, 原始, DIFF
{20, 0, ALGORITHM_RGB565, 0 }, // High: 20FPS, 原始, RGB565
{20, 1920, ALGORITHM_H264, 3000}, // Good: 20FPS, 1080P, H264
{15, 1600, ALGORITHM_H264, 2000}, // Medium: 15FPS, 900P, H264
{12, 1280, ALGORITHM_H264, 1200}, // Low: 12FPS, 720P, H264
{8, 1024, ALGORITHM_H264, 800 }, // Minimal: 8FPS, 540P, H264
};
// ============================================
// RTT 阈值表 (来自 commands.h)
// ============================================
// 行0: 直连模式, 行1: FRP代理模式
static const int g_RttThresholds[2][QUALITY_COUNT] = {
/* DIRECT */ { 30, 80, 150, 250, 400, INT_MAX },
/* PROXY */ { 60, 160, 300, 500, 800, INT_MAX },
};
// ============================================
// RTT到质量等级映射函数 (来自 commands.h)
// ============================================
inline int GetTargetQualityLevel(int rtt, int usingFRP)
{
int row = usingFRP ? 1 : 0;
for (int level = 0; level < QUALITY_COUNT; level++) {
if (rtt < g_RttThresholds[row][level]) {
return level;
}
}
return QUALITY_MINIMAL;
}
// ============================================
// 防抖策略模拟器
// ============================================
class QualityDebouncer {
public:
// 防抖参数
static const int DOWNGRADE_STABLE_COUNT = 2; // 降级所需稳定次数
static const int UPGRADE_STABLE_COUNT = 5; // 升级所需稳定次数
static const int DEFAULT_COOLDOWN_MS = 3000; // 默认冷却时间
static const int RES_CHANGE_DOWNGRADE_COOLDOWN_MS = 15000; // 分辨率降级冷却
static const int RES_CHANGE_UPGRADE_COOLDOWN_MS = 30000; // 分辨率升级冷却
static const int STARTUP_DELAY_MS = 60000; // 启动延迟
QualityDebouncer()
: m_currentLevel(QUALITY_HIGH)
, m_stableCount(0)
, m_lastChangeTime(0)
, m_startTime(0)
, m_enabled(true)
{}
void Reset() {
m_currentLevel = QUALITY_HIGH;
m_stableCount = 0;
m_lastChangeTime = 0;
m_startTime = 0;
}
void SetStartTime(uint64_t time) {
m_startTime = time;
}
void SetEnabled(bool enabled) {
m_enabled = enabled;
}
// 评估并返回新的质量等级
// 返回 -1 表示不改变
int Evaluate(int targetLevel, uint64_t currentTime, bool resolutionChange = false) {
if (!m_enabled) return -1;
// 启动延迟
if (currentTime - m_startTime < STARTUP_DELAY_MS) {
return -1;
}
// 冷却时间检查
uint64_t cooldown = DEFAULT_COOLDOWN_MS;
if (resolutionChange) {
cooldown = (targetLevel > m_currentLevel)
? RES_CHANGE_DOWNGRADE_COOLDOWN_MS
: RES_CHANGE_UPGRADE_COOLDOWN_MS;
}
if (currentTime - m_lastChangeTime < cooldown) {
return -1;
}
// 降级: 快速响应
if (targetLevel > m_currentLevel) {
m_stableCount++;
if (m_stableCount >= DOWNGRADE_STABLE_COUNT) {
int newLevel = targetLevel;
m_currentLevel = newLevel;
m_stableCount = 0;
m_lastChangeTime = currentTime;
return newLevel;
}
}
// 升级: 谨慎处理,每次只升一级
else if (targetLevel < m_currentLevel) {
m_stableCount++;
if (m_stableCount >= UPGRADE_STABLE_COUNT) {
int newLevel = m_currentLevel - 1; // 只升一级
m_currentLevel = newLevel;
m_stableCount = 0;
m_lastChangeTime = currentTime;
return newLevel;
}
}
// 目标等级等于当前等级
else {
m_stableCount = 0;
}
return -1;
}
int GetCurrentLevel() const { return m_currentLevel; }
int GetStableCount() const { return m_stableCount; }
private:
int m_currentLevel;
int m_stableCount;
uint64_t m_lastChangeTime;
uint64_t m_startTime;
bool m_enabled;
};
// ============================================
// 测试夹具
// ============================================
class QualityAdaptiveTest : public ::testing::Test {
protected:
void SetUp() override {
debouncer.Reset();
}
QualityDebouncer debouncer;
};
// ============================================
// RTT 映射测试 - 直连模式
// ============================================
TEST_F(QualityAdaptiveTest, RTT_Direct_Ultra) {
// RTT < 30ms -> Ultra
EXPECT_EQ(GetTargetQualityLevel(0, 0), QUALITY_ULTRA);
EXPECT_EQ(GetTargetQualityLevel(10, 0), QUALITY_ULTRA);
EXPECT_EQ(GetTargetQualityLevel(29, 0), QUALITY_ULTRA);
}
TEST_F(QualityAdaptiveTest, RTT_Direct_High) {
// 30ms <= RTT < 80ms -> High
EXPECT_EQ(GetTargetQualityLevel(30, 0), QUALITY_HIGH);
EXPECT_EQ(GetTargetQualityLevel(50, 0), QUALITY_HIGH);
EXPECT_EQ(GetTargetQualityLevel(79, 0), QUALITY_HIGH);
}
TEST_F(QualityAdaptiveTest, RTT_Direct_Good) {
// 80ms <= RTT < 150ms -> Good
EXPECT_EQ(GetTargetQualityLevel(80, 0), QUALITY_GOOD);
EXPECT_EQ(GetTargetQualityLevel(100, 0), QUALITY_GOOD);
EXPECT_EQ(GetTargetQualityLevel(149, 0), QUALITY_GOOD);
}
TEST_F(QualityAdaptiveTest, RTT_Direct_Medium) {
// 150ms <= RTT < 250ms -> Medium
EXPECT_EQ(GetTargetQualityLevel(150, 0), QUALITY_MEDIUM);
EXPECT_EQ(GetTargetQualityLevel(200, 0), QUALITY_MEDIUM);
EXPECT_EQ(GetTargetQualityLevel(249, 0), QUALITY_MEDIUM);
}
TEST_F(QualityAdaptiveTest, RTT_Direct_Low) {
// 250ms <= RTT < 400ms -> Low
EXPECT_EQ(GetTargetQualityLevel(250, 0), QUALITY_LOW);
EXPECT_EQ(GetTargetQualityLevel(300, 0), QUALITY_LOW);
EXPECT_EQ(GetTargetQualityLevel(399, 0), QUALITY_LOW);
}
TEST_F(QualityAdaptiveTest, RTT_Direct_Minimal) {
// RTT >= 400ms -> Minimal
EXPECT_EQ(GetTargetQualityLevel(400, 0), QUALITY_MINIMAL);
EXPECT_EQ(GetTargetQualityLevel(500, 0), QUALITY_MINIMAL);
EXPECT_EQ(GetTargetQualityLevel(1000, 0), QUALITY_MINIMAL);
}
// ============================================
// RTT 映射测试 - FRP代理模式
// ============================================
TEST_F(QualityAdaptiveTest, RTT_FRP_Ultra) {
// RTT < 60ms -> Ultra (FRP模式阈值更宽松)
EXPECT_EQ(GetTargetQualityLevel(0, 1), QUALITY_ULTRA);
EXPECT_EQ(GetTargetQualityLevel(30, 1), QUALITY_ULTRA);
EXPECT_EQ(GetTargetQualityLevel(59, 1), QUALITY_ULTRA);
}
TEST_F(QualityAdaptiveTest, RTT_FRP_High) {
// 60ms <= RTT < 160ms -> High
EXPECT_EQ(GetTargetQualityLevel(60, 1), QUALITY_HIGH);
EXPECT_EQ(GetTargetQualityLevel(100, 1), QUALITY_HIGH);
EXPECT_EQ(GetTargetQualityLevel(159, 1), QUALITY_HIGH);
}
TEST_F(QualityAdaptiveTest, RTT_FRP_Good) {
// 160ms <= RTT < 300ms -> Good
EXPECT_EQ(GetTargetQualityLevel(160, 1), QUALITY_GOOD);
EXPECT_EQ(GetTargetQualityLevel(200, 1), QUALITY_GOOD);
EXPECT_EQ(GetTargetQualityLevel(299, 1), QUALITY_GOOD);
}
TEST_F(QualityAdaptiveTest, RTT_FRP_Medium) {
// 300ms <= RTT < 500ms -> Medium
EXPECT_EQ(GetTargetQualityLevel(300, 1), QUALITY_MEDIUM);
EXPECT_EQ(GetTargetQualityLevel(400, 1), QUALITY_MEDIUM);
EXPECT_EQ(GetTargetQualityLevel(499, 1), QUALITY_MEDIUM);
}
TEST_F(QualityAdaptiveTest, RTT_FRP_Low) {
// 500ms <= RTT < 800ms -> Low
EXPECT_EQ(GetTargetQualityLevel(500, 1), QUALITY_LOW);
EXPECT_EQ(GetTargetQualityLevel(600, 1), QUALITY_LOW);
EXPECT_EQ(GetTargetQualityLevel(799, 1), QUALITY_LOW);
}
TEST_F(QualityAdaptiveTest, RTT_FRP_Minimal) {
// RTT >= 800ms -> Minimal
EXPECT_EQ(GetTargetQualityLevel(800, 1), QUALITY_MINIMAL);
EXPECT_EQ(GetTargetQualityLevel(1000, 1), QUALITY_MINIMAL);
EXPECT_EQ(GetTargetQualityLevel(2000, 1), QUALITY_MINIMAL);
}
// ============================================
// 质量配置表测试
// ============================================
TEST_F(QualityAdaptiveTest, Profile_Ultra) {
const auto& p = g_QualityProfiles[QUALITY_ULTRA];
EXPECT_EQ(p.maxFPS, 25);
EXPECT_EQ(p.maxWidth, 0); // 无限制
EXPECT_EQ(p.algorithm, ALGORITHM_DIFF);
EXPECT_EQ(p.bitRate, 0);
}
TEST_F(QualityAdaptiveTest, Profile_High) {
const auto& p = g_QualityProfiles[QUALITY_HIGH];
EXPECT_EQ(p.maxFPS, 20);
EXPECT_EQ(p.maxWidth, 0); // 无限制
EXPECT_EQ(p.algorithm, ALGORITHM_RGB565);
EXPECT_EQ(p.bitRate, 0);
}
TEST_F(QualityAdaptiveTest, Profile_Good) {
const auto& p = g_QualityProfiles[QUALITY_GOOD];
EXPECT_EQ(p.maxFPS, 20);
EXPECT_EQ(p.maxWidth, 1920); // 1080p
EXPECT_EQ(p.algorithm, ALGORITHM_H264);
EXPECT_EQ(p.bitRate, 3000);
}
TEST_F(QualityAdaptiveTest, Profile_Medium) {
const auto& p = g_QualityProfiles[QUALITY_MEDIUM];
EXPECT_EQ(p.maxFPS, 15);
EXPECT_EQ(p.maxWidth, 1600); // 900p
EXPECT_EQ(p.algorithm, ALGORITHM_H264);
EXPECT_EQ(p.bitRate, 2000);
}
TEST_F(QualityAdaptiveTest, Profile_Low) {
const auto& p = g_QualityProfiles[QUALITY_LOW];
EXPECT_EQ(p.maxFPS, 12);
EXPECT_EQ(p.maxWidth, 1280); // 720p
EXPECT_EQ(p.algorithm, ALGORITHM_H264);
EXPECT_EQ(p.bitRate, 1200);
}
TEST_F(QualityAdaptiveTest, Profile_Minimal) {
const auto& p = g_QualityProfiles[QUALITY_MINIMAL];
EXPECT_EQ(p.maxFPS, 8);
EXPECT_EQ(p.maxWidth, 1024); // 540p
EXPECT_EQ(p.algorithm, ALGORITHM_H264);
EXPECT_EQ(p.bitRate, 800);
}
// ============================================
// 防抖策略测试 - 启动延迟
// ============================================
TEST_F(QualityAdaptiveTest, Debounce_StartupDelay) {
debouncer.SetStartTime(0);
// 启动后60秒内不应改变
EXPECT_EQ(debouncer.Evaluate(QUALITY_MINIMAL, 1000), -1);
EXPECT_EQ(debouncer.Evaluate(QUALITY_MINIMAL, 30000), -1);
EXPECT_EQ(debouncer.Evaluate(QUALITY_MINIMAL, 59999), -1);
}
TEST_F(QualityAdaptiveTest, Debounce_AfterStartupDelay) {
debouncer.SetStartTime(0);
// 启动60秒后应该可以改变
// 需要连续2次降级请求
debouncer.Evaluate(QUALITY_MINIMAL, 60000); // 第1次
int result = debouncer.Evaluate(QUALITY_MINIMAL, 60001); // 第2次
EXPECT_EQ(result, QUALITY_MINIMAL);
}
// ============================================
// 防抖策略测试 - 降级
// ============================================
TEST_F(QualityAdaptiveTest, Debounce_Downgrade_RequiresTwice) {
debouncer.SetStartTime(0);
uint64_t time = 60000;
// 第1次降级请求 - 不应立即执行
int result = debouncer.Evaluate(QUALITY_MINIMAL, time);
EXPECT_EQ(result, -1);
EXPECT_EQ(debouncer.GetStableCount(), 1);
// 第2次降级请求 - 应该执行
result = debouncer.Evaluate(QUALITY_MINIMAL, time + 100);
EXPECT_EQ(result, QUALITY_MINIMAL);
EXPECT_EQ(debouncer.GetCurrentLevel(), QUALITY_MINIMAL);
}
TEST_F(QualityAdaptiveTest, Debounce_Downgrade_ResetOnStable) {
debouncer.SetStartTime(0);
uint64_t time = 60000;
// 第1次降级请求
debouncer.Evaluate(QUALITY_LOW, time);
EXPECT_EQ(debouncer.GetStableCount(), 1);
// 目标等级恢复 - 计数应重置
debouncer.Evaluate(QUALITY_HIGH, time + 100); // 当前等级
EXPECT_EQ(debouncer.GetStableCount(), 0);
}
// ============================================
// 防抖策略测试 - 升级
// ============================================
TEST_F(QualityAdaptiveTest, Debounce_Upgrade_RequiresFiveTimes) {
debouncer.SetStartTime(0);
uint64_t time = 60000;
// 先降级到 MINIMAL
debouncer.Evaluate(QUALITY_MINIMAL, time);
debouncer.Evaluate(QUALITY_MINIMAL, time + 100);
EXPECT_EQ(debouncer.GetCurrentLevel(), QUALITY_MINIMAL);
// 尝试升级到 ULTRA (需要5次)
time += 5000; // 冷却后
for (int i = 0; i < 4; i++) {
int result = debouncer.Evaluate(QUALITY_ULTRA, time + i * 100);
EXPECT_EQ(result, -1); // 前4次不应执行
EXPECT_EQ(debouncer.GetStableCount(), i + 1);
}
// 第5次应该执行但只升一级
int result = debouncer.Evaluate(QUALITY_ULTRA, time + 500);
EXPECT_EQ(result, QUALITY_LOW); // MINIMAL -> LOW (只升一级)
}
TEST_F(QualityAdaptiveTest, Debounce_Upgrade_OneStepAtATime) {
debouncer.SetStartTime(0);
uint64_t time = 60000;
// 降级到 MINIMAL
debouncer.Evaluate(QUALITY_MINIMAL, time);
debouncer.Evaluate(QUALITY_MINIMAL, time + 100);
EXPECT_EQ(debouncer.GetCurrentLevel(), QUALITY_MINIMAL);
// 多次升级请求,验证每次只升一级
// 从 MINIMAL(5) 升到 HIGH(1) 需要4次升级每次需要5个稳定请求
time += 5000;
int upgradeCount = 0;
while (debouncer.GetCurrentLevel() > QUALITY_HIGH && upgradeCount < 10) {
for (int i = 0; i < 5; i++) {
debouncer.Evaluate(QUALITY_ULTRA, time); // 请求最高等级
time += 100;
}
time += 5000; // 冷却
upgradeCount++;
}
// 最终应该回到 HIGH (或更高)
EXPECT_LE(debouncer.GetCurrentLevel(), QUALITY_HIGH);
}
// ============================================
// 防抖策略测试 - 冷却时间
// ============================================
TEST_F(QualityAdaptiveTest, Debounce_DefaultCooldown) {
debouncer.SetStartTime(0);
uint64_t time = 60000;
// 执行一次降级
debouncer.Evaluate(QUALITY_LOW, time);
debouncer.Evaluate(QUALITY_LOW, time + 100);
EXPECT_EQ(debouncer.GetCurrentLevel(), QUALITY_LOW);
// 冷却期内不应再次改变
int result = debouncer.Evaluate(QUALITY_MINIMAL, time + 200);
EXPECT_EQ(result, -1);
result = debouncer.Evaluate(QUALITY_MINIMAL, time + 2999);
EXPECT_EQ(result, -1);
}
TEST_F(QualityAdaptiveTest, Debounce_AfterCooldown) {
debouncer.SetStartTime(0);
uint64_t time = 60000;
// 执行一次降级
debouncer.Evaluate(QUALITY_LOW, time);
debouncer.Evaluate(QUALITY_LOW, time + 100);
// 冷却后应该可以再次改变
time += 3100;
debouncer.Evaluate(QUALITY_MINIMAL, time);
int result = debouncer.Evaluate(QUALITY_MINIMAL, time + 100);
EXPECT_EQ(result, QUALITY_MINIMAL);
}
// ============================================
// 防抖策略测试 - 分辨率变化冷却
// ============================================
TEST_F(QualityAdaptiveTest, Debounce_ResolutionChange_DowngradeCooldown) {
debouncer.SetStartTime(0);
uint64_t time = 60000;
// 执行一次带分辨率变化的降级
debouncer.Evaluate(QUALITY_LOW, time, true); // resolutionChange=true
debouncer.Evaluate(QUALITY_LOW, time + 100, true);
// 分辨率降级冷却15秒
int result = debouncer.Evaluate(QUALITY_MINIMAL, time + 14000, true);
EXPECT_EQ(result, -1);
// 15秒后可以
time += 16000;
debouncer.Evaluate(QUALITY_MINIMAL, time, true);
result = debouncer.Evaluate(QUALITY_MINIMAL, time + 100, true);
EXPECT_EQ(result, QUALITY_MINIMAL);
}
TEST_F(QualityAdaptiveTest, Debounce_ResolutionChange_UpgradeCooldown) {
debouncer.SetStartTime(0);
uint64_t time = 60000;
// 先降级到 MINIMAL (不带分辨率变化,使用默认冷却)
debouncer.Evaluate(QUALITY_MINIMAL, time);
debouncer.Evaluate(QUALITY_MINIMAL, time + 100);
EXPECT_EQ(debouncer.GetCurrentLevel(), QUALITY_MINIMAL);
// 等待足够长时间(>30秒进行带分辨率变化的升级
time += 35000; // 超过30秒冷却
for (int i = 0; i < 5; i++) {
debouncer.Evaluate(QUALITY_ULTRA, time + i * 100, true); // resolutionChange=true
}
// 应该成功升级一级 (MINIMAL -> LOW)
EXPECT_EQ(debouncer.GetCurrentLevel(), QUALITY_LOW);
// 30秒内不应再次升级带分辨率变化的升级需要30秒冷却
time += 1000;
for (int i = 0; i < 5; i++) {
debouncer.Evaluate(QUALITY_ULTRA, time + i * 100, true);
}
EXPECT_EQ(debouncer.GetCurrentLevel(), QUALITY_LOW); // 未改变还在30秒冷却期内
}
// ============================================
// 禁用自适应测试
// ============================================
TEST_F(QualityAdaptiveTest, Debounce_Disabled) {
debouncer.SetStartTime(0);
debouncer.SetEnabled(false);
uint64_t time = 60000;
int result = debouncer.Evaluate(QUALITY_MINIMAL, time);
EXPECT_EQ(result, -1);
result = debouncer.Evaluate(QUALITY_MINIMAL, time + 100);
EXPECT_EQ(result, -1);
// 质量等级应保持不变
EXPECT_EQ(debouncer.GetCurrentLevel(), QUALITY_HIGH);
}
// ============================================
// 边界值测试
// ============================================
TEST_F(QualityAdaptiveTest, RTT_Boundary_Zero) {
EXPECT_EQ(GetTargetQualityLevel(0, 0), QUALITY_ULTRA);
EXPECT_EQ(GetTargetQualityLevel(0, 1), QUALITY_ULTRA);
}
TEST_F(QualityAdaptiveTest, RTT_Boundary_Negative) {
// 负值RTT应该仍返回最高质量
EXPECT_EQ(GetTargetQualityLevel(-1, 0), QUALITY_ULTRA);
EXPECT_EQ(GetTargetQualityLevel(-100, 0), QUALITY_ULTRA);
}
TEST_F(QualityAdaptiveTest, RTT_Boundary_VeryHigh) {
// 非常高的RTT
EXPECT_EQ(GetTargetQualityLevel(10000, 0), QUALITY_MINIMAL);
EXPECT_EQ(GetTargetQualityLevel(100000, 0), QUALITY_MINIMAL);
EXPECT_EQ(GetTargetQualityLevel(INT_MAX - 1, 0), QUALITY_MINIMAL);
}
// ============================================
// 常量验证测试
// ============================================
TEST(QualityConstantsTest, QualityLevelEnum) {
EXPECT_EQ(QUALITY_DISABLED, -2);
EXPECT_EQ(QUALITY_ADAPTIVE, -1);
EXPECT_EQ(QUALITY_ULTRA, 0);
EXPECT_EQ(QUALITY_HIGH, 1);
EXPECT_EQ(QUALITY_GOOD, 2);
EXPECT_EQ(QUALITY_MEDIUM, 3);
EXPECT_EQ(QUALITY_LOW, 4);
EXPECT_EQ(QUALITY_MINIMAL, 5);
EXPECT_EQ(QUALITY_COUNT, 6);
}
TEST(QualityConstantsTest, ProfileCount) {
// 应该有 QUALITY_COUNT 个配置
EXPECT_EQ(sizeof(g_QualityProfiles) / sizeof(g_QualityProfiles[0]),
static_cast<size_t>(QUALITY_COUNT));
}
TEST(QualityConstantsTest, ThresholdCount) {
// 每行应该有 QUALITY_COUNT 个阈值
EXPECT_EQ(sizeof(g_RttThresholds[0]) / sizeof(g_RttThresholds[0][0]),
static_cast<size_t>(QUALITY_COUNT));
}
TEST(QualityConstantsTest, ThresholdIncreasing) {
// 阈值应该递增
for (int row = 0; row < 2; row++) {
for (int i = 0; i < QUALITY_COUNT - 1; i++) {
EXPECT_LT(g_RttThresholds[row][i], g_RttThresholds[row][i + 1])
<< "Row " << row << ", index " << i;
}
}
}
TEST(QualityConstantsTest, FRPThresholdsHigher) {
// FRP模式阈值应该比直连模式高
for (int i = 0; i < QUALITY_COUNT - 1; i++) {
EXPECT_GT(g_RttThresholds[1][i], g_RttThresholds[0][i])
<< "Index " << i;
}
}
// ============================================
// 参数化测试RTT值遍历
// ============================================
class RTTMappingTest : public ::testing::TestWithParam<std::tuple<int, int, int>> {};
TEST_P(RTTMappingTest, RTT_Mapping) {
auto [rtt, usingFRP, expectedLevel] = GetParam();
EXPECT_EQ(GetTargetQualityLevel(rtt, usingFRP), expectedLevel);
}
INSTANTIATE_TEST_SUITE_P(
DirectMode,
RTTMappingTest,
::testing::Values(
std::make_tuple(0, 0, QUALITY_ULTRA),
std::make_tuple(29, 0, QUALITY_ULTRA),
std::make_tuple(30, 0, QUALITY_HIGH),
std::make_tuple(79, 0, QUALITY_HIGH),
std::make_tuple(80, 0, QUALITY_GOOD),
std::make_tuple(149, 0, QUALITY_GOOD),
std::make_tuple(150, 0, QUALITY_MEDIUM),
std::make_tuple(249, 0, QUALITY_MEDIUM),
std::make_tuple(250, 0, QUALITY_LOW),
std::make_tuple(399, 0, QUALITY_LOW),
std::make_tuple(400, 0, QUALITY_MINIMAL),
std::make_tuple(1000, 0, QUALITY_MINIMAL)
)
);
INSTANTIATE_TEST_SUITE_P(
FRPMode,
RTTMappingTest,
::testing::Values(
std::make_tuple(0, 1, QUALITY_ULTRA),
std::make_tuple(59, 1, QUALITY_ULTRA),
std::make_tuple(60, 1, QUALITY_HIGH),
std::make_tuple(159, 1, QUALITY_HIGH),
std::make_tuple(160, 1, QUALITY_GOOD),
std::make_tuple(299, 1, QUALITY_GOOD),
std::make_tuple(300, 1, QUALITY_MEDIUM),
std::make_tuple(499, 1, QUALITY_MEDIUM),
std::make_tuple(500, 1, QUALITY_LOW),
std::make_tuple(799, 1, QUALITY_LOW),
std::make_tuple(800, 1, QUALITY_MINIMAL),
std::make_tuple(2000, 1, QUALITY_MINIMAL)
)
);
// ============================================
// 质量配置合理性测试
// ============================================
TEST(QualityProfileTest, FPSDecreasing) {
// FPS 应该随质量降低而减少
for (int i = 0; i < QUALITY_COUNT - 1; i++) {
EXPECT_GE(g_QualityProfiles[i].maxFPS, g_QualityProfiles[i + 1].maxFPS)
<< "Level " << i;
}
}
TEST(QualityProfileTest, MaxWidthDecreasing) {
// maxWidth 应该随质量降低而减少除了0表示不限
int prevWidth = INT_MAX;
for (int i = 0; i < QUALITY_COUNT; i++) {
int width = g_QualityProfiles[i].maxWidth;
if (width > 0) {
EXPECT_LE(width, prevWidth) << "Level " << i;
prevWidth = width;
}
}
}
TEST(QualityProfileTest, BitRateDecreasing) {
// H264 bitRate 应该随质量降低而减少
int prevBitRate = INT_MAX;
for (int i = 0; i < QUALITY_COUNT; i++) {
if (g_QualityProfiles[i].algorithm == ALGORITHM_H264) {
int bitRate = g_QualityProfiles[i].bitRate;
EXPECT_LE(bitRate, prevBitRate) << "Level " << i;
prevBitRate = bitRate;
}
}
}