Files
SimpleRemoter/test/unit/screen/QualityAdaptiveTest.cpp
2026-04-19 22:55:21 +02:00

692 lines
23 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.
// 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;
}
}
}