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

876 lines
25 KiB
C++
Raw Permalink 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.
/**
* @file DateVerifyTest.cpp
* @brief DateVerify 时间验证类测试
*
* 测试覆盖:
* - isTimeTampered() 时间篡改检测
* - getTimeOffset() 时间偏差获取
* - isTrial() 试用期检测
* - isTrail() 兼容性测试
* - 边界条件和缓存机制
*/
#include <gtest/gtest.h>
#include <cstring>
#include <ctime>
#include <map>
#include <chrono>
#include <cmath>
#include <string>
#include <functional>
// ============================================
// 可测试版本的 DateVerify 类
// 允许注入模拟的网络时间
// ============================================
class TestableDateVerify
{
private:
bool m_hasVerified = false;
bool m_lastTimeTampered = true;
time_t m_lastVerifyLocalTime = 0;
time_t m_lastNetworkTime = 0;
static const int VERIFY_INTERVAL = 6 * 3600; // 6小时
// 模拟的网络时间0表示网络不可用
time_t m_mockNetworkTime = 0;
bool m_useMockTime = false;
// 模拟的本地时间
time_t m_mockLocalTime = 0;
bool m_useMockLocalTime = false;
// 模拟的编译日期
std::string m_mockCompileDate;
time_t getNetworkTimeInChina()
{
if (m_useMockTime) {
return m_mockNetworkTime;
}
// 实际测试中不调用网络
return 0;
}
time_t getLocalTime()
{
if (m_useMockLocalTime) {
return m_mockLocalTime;
}
return time(nullptr);
}
int monthAbbrevToNumber(const std::string& month)
{
static const std::map<std::string, int> months = {
{"Jan", 1}, {"Feb", 2}, {"Mar", 3}, {"Apr", 4},
{"May", 5}, {"Jun", 6}, {"Jul", 7}, {"Aug", 8},
{"Sep", 9}, {"Oct", 10}, {"Nov", 11}, {"Dec", 12}
};
auto it = months.find(month);
return (it != months.end()) ? it->second : 0;
}
tm parseCompileDate(const char* compileDate)
{
tm tmCompile = { 0 };
std::string monthStr(compileDate, 3);
std::string dayStr(compileDate + 4, 2);
std::string yearStr(compileDate + 7, 4);
tmCompile.tm_year = std::stoi(yearStr) - 1900;
tmCompile.tm_mon = monthAbbrevToNumber(monthStr) - 1;
tmCompile.tm_mday = std::stoi(dayStr);
return tmCompile;
}
int daysBetweenDates(const tm& date1, const tm& date2)
{
auto timeToTimePoint = [](const tm& tmTime) {
std::time_t tt = mktime(const_cast<tm*>(&tmTime));
return std::chrono::system_clock::from_time_t(tt);
};
auto tp1 = timeToTimePoint(date1);
auto tp2 = timeToTimePoint(date2);
auto duration = tp1 > tp2 ? tp1 - tp2 : tp2 - tp1;
return static_cast<int>(std::chrono::duration_cast<std::chrono::hours>(duration).count() / 24);
}
tm getCurrentDate()
{
std::time_t now = getLocalTime();
tm tmNow = *std::localtime(&now);
tmNow.tm_hour = 0;
tmNow.tm_min = 0;
tmNow.tm_sec = 0;
return tmNow;
}
public:
// 测试辅助方法
void setMockNetworkTime(time_t t) { m_mockNetworkTime = t; m_useMockTime = true; }
void setNetworkUnavailable() { m_mockNetworkTime = 0; m_useMockTime = true; }
void setMockLocalTime(time_t t) { m_mockLocalTime = t; m_useMockLocalTime = true; }
void setMockCompileDate(const std::string& date) { m_mockCompileDate = date; }
void resetCache() { m_hasVerified = false; m_lastTimeTampered = true; }
bool hasVerified() const { return m_hasVerified; }
// 检测本地时间是否被篡改
bool isTimeTampered(int toleranceDays = 1)
{
time_t currentLocalTime = getLocalTime();
// 检查是否可以使用缓存
if (m_hasVerified) {
time_t localElapsed = currentLocalTime - m_lastVerifyLocalTime;
// 本地时间在合理范围内前进,使用缓存推算
if (localElapsed >= 0 && localElapsed < VERIFY_INTERVAL) {
time_t estimatedNetworkTime = m_lastNetworkTime + localElapsed;
double diffDays = difftime(estimatedNetworkTime, currentLocalTime) / 86400.0;
if (fabs(diffDays) <= toleranceDays) {
return false; // 未篡改
}
}
}
// 执行网络验证
time_t networkTime = getNetworkTimeInChina();
if (networkTime == 0) {
// 网络不可用:如果之前验证通过且本地时间没异常,暂时信任
if (m_hasVerified && !m_lastTimeTampered) {
time_t localElapsed = currentLocalTime - m_lastVerifyLocalTime;
// 允许5分钟回拨和24小时内的前进
if (localElapsed >= -300 && localElapsed < 24 * 3600) {
return false;
}
}
return true; // 无法验证,视为篡改
}
// 更新缓存
m_hasVerified = true;
m_lastVerifyLocalTime = currentLocalTime;
m_lastNetworkTime = networkTime;
double diffDays = difftime(networkTime, currentLocalTime) / 86400.0;
m_lastTimeTampered = fabs(diffDays) > toleranceDays;
return m_lastTimeTampered;
}
// 获取网络时间与本地时间的偏差(秒)
int getTimeOffset()
{
time_t networkTime = getNetworkTimeInChina();
if (networkTime == 0) return 0;
return static_cast<int>(difftime(networkTime, getLocalTime()));
}
bool isTrial(int trialDays = 7)
{
if (isTimeTampered())
return false;
const char* compileDate = m_mockCompileDate.empty() ? __DATE__ : m_mockCompileDate.c_str();
tm tmCompile = parseCompileDate(compileDate), tmCurrent = getCurrentDate();
int daysDiff = daysBetweenDates(tmCompile, tmCurrent);
return daysDiff <= trialDays;
}
// 兼容性函数
bool isTrail(int trailDays = 7) { return isTrial(trailDays); }
};
// ============================================
// 辅助函数
// ============================================
// 创建指定日期的 time_t
time_t makeTime(int year, int month, int day, int hour = 12, int minute = 0, int second = 0)
{
tm t = {};
t.tm_year = year - 1900;
t.tm_mon = month - 1;
t.tm_mday = day;
t.tm_hour = hour;
t.tm_min = minute;
t.tm_sec = second;
return mktime(&t);
}
// 格式化日期为 __DATE__ 格式 (例如 "Mar 13 2026")
std::string formatCompileDate(int year, int month, int day)
{
static const char* months[] = {
"Jan", "Feb", "Mar", "Apr", "May", "Jun",
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
};
char buf[16];
snprintf(buf, sizeof(buf), "%s %2d %d", months[month - 1], day, year);
return std::string(buf);
}
// ============================================
// isTimeTampered 测试
// ============================================
class IsTimeTamperedTest : public ::testing::Test {
protected:
TestableDateVerify verifier;
};
TEST_F(IsTimeTamperedTest, NetworkUnavailable_NoCache_ReturnsTampered)
{
// 网络不可用,无缓存时应返回 true视为篡改
verifier.setNetworkUnavailable();
EXPECT_TRUE(verifier.isTimeTampered());
}
TEST_F(IsTimeTamperedTest, NetworkAvailable_TimeMatch_ReturnsNotTampered)
{
// 网络时间与本地时间匹配
time_t now = time(nullptr);
verifier.setMockNetworkTime(now);
verifier.setMockLocalTime(now);
EXPECT_FALSE(verifier.isTimeTampered(1));
}
TEST_F(IsTimeTamperedTest, NetworkAvailable_TimeWithinTolerance_ReturnsNotTampered)
{
// 网络时间与本地时间差异在容忍范围内12小时差异1天容忍
time_t now = time(nullptr);
verifier.setMockNetworkTime(now);
verifier.setMockLocalTime(now - 12 * 3600); // 本地时间落后12小时
EXPECT_FALSE(verifier.isTimeTampered(1));
}
TEST_F(IsTimeTamperedTest, NetworkAvailable_TimeExceedsTolerance_ReturnsTampered)
{
// 网络时间与本地时间差异超过容忍范围2天差异1天容忍
time_t now = time(nullptr);
verifier.setMockNetworkTime(now);
verifier.setMockLocalTime(now - 2 * 86400); // 本地时间落后2天
EXPECT_TRUE(verifier.isTimeTampered(1));
}
TEST_F(IsTimeTamperedTest, ToleranceDays_Zero_StrictMode)
{
// 0天容忍度任何偏差都应报告为篡改
time_t now = time(nullptr);
verifier.setMockNetworkTime(now);
verifier.setMockLocalTime(now - 86400); // 1天偏差
EXPECT_TRUE(verifier.isTimeTampered(0));
}
TEST_F(IsTimeTamperedTest, ToleranceDays_Large_LenientMode)
{
// 大容忍度7天较大偏差仍应通过
time_t now = time(nullptr);
verifier.setMockNetworkTime(now);
verifier.setMockLocalTime(now - 5 * 86400); // 5天偏差
EXPECT_FALSE(verifier.isTimeTampered(7));
}
TEST_F(IsTimeTamperedTest, LocalTimeAhead_ExceedsTolerance_ReturnsTampered)
{
// 本地时间超前网络时间
time_t now = time(nullptr);
verifier.setMockNetworkTime(now);
verifier.setMockLocalTime(now + 3 * 86400); // 本地时间超前3天
EXPECT_TRUE(verifier.isTimeTampered(1));
}
TEST_F(IsTimeTamperedTest, CacheHit_WithinInterval_UsesCache)
{
// 首次验证成功
time_t now = time(nullptr);
verifier.setMockNetworkTime(now);
verifier.setMockLocalTime(now);
EXPECT_FALSE(verifier.isTimeTampered(1));
EXPECT_TRUE(verifier.hasVerified());
// 模拟时间前进1小时在6小时缓存间隔内
verifier.setMockLocalTime(now + 3600);
verifier.setNetworkUnavailable(); // 网络不可用
// 应该使用缓存,不报告篡改
EXPECT_FALSE(verifier.isTimeTampered(1));
}
TEST_F(IsTimeTamperedTest, CacheMiss_ExceedsInterval_RequiresNetwork)
{
// 首次验证成功
time_t now = time(nullptr);
verifier.setMockNetworkTime(now);
verifier.setMockLocalTime(now);
EXPECT_FALSE(verifier.isTimeTampered(1));
// 模拟时间前进25小时超过24小时宽容期
// 注实现中网络不可用时有24小时宽容期超过后才报告篡改
verifier.setMockLocalTime(now + 25 * 3600);
verifier.setNetworkUnavailable();
// 超过24小时宽容期网络不可用应报告篡改
EXPECT_TRUE(verifier.isTimeTampered(1));
}
TEST_F(IsTimeTamperedTest, NetworkUnavailable_WithGoodCache_AllowsSmallRewind)
{
// 首次验证成功
time_t now = time(nullptr);
verifier.setMockNetworkTime(now);
verifier.setMockLocalTime(now);
EXPECT_FALSE(verifier.isTimeTampered(1));
// 模拟时间回拨2分钟在允许的5分钟范围内
verifier.setMockLocalTime(now - 120);
verifier.setNetworkUnavailable();
// 应该暂时信任
EXPECT_FALSE(verifier.isTimeTampered(1));
}
TEST_F(IsTimeTamperedTest, NetworkUnavailable_WithGoodCache_RejectsLargeRewind)
{
// 首次验证成功
time_t now = time(nullptr);
verifier.setMockNetworkTime(now);
verifier.setMockLocalTime(now);
EXPECT_FALSE(verifier.isTimeTampered(1));
// 模拟时间回拨10分钟超过允许的5分钟
verifier.setMockLocalTime(now - 600);
verifier.setNetworkUnavailable();
// 应该报告篡改
EXPECT_TRUE(verifier.isTimeTampered(1));
}
// ============================================
// getTimeOffset 测试
// ============================================
class GetTimeOffsetTest : public ::testing::Test {
protected:
TestableDateVerify verifier;
};
TEST_F(GetTimeOffsetTest, NetworkUnavailable_ReturnsZero)
{
verifier.setNetworkUnavailable();
EXPECT_EQ(verifier.getTimeOffset(), 0);
}
TEST_F(GetTimeOffsetTest, LocalTimeBehind_ReturnsPositive)
{
time_t now = time(nullptr);
verifier.setMockNetworkTime(now);
verifier.setMockLocalTime(now - 3600); // 本地落后1小时
int offset = verifier.getTimeOffset();
EXPECT_GT(offset, 0);
EXPECT_NEAR(offset, 3600, 5); // 允许5秒误差
}
TEST_F(GetTimeOffsetTest, LocalTimeAhead_ReturnsNegative)
{
time_t now = time(nullptr);
verifier.setMockNetworkTime(now);
verifier.setMockLocalTime(now + 3600); // 本地超前1小时
int offset = verifier.getTimeOffset();
EXPECT_LT(offset, 0);
EXPECT_NEAR(offset, -3600, 5);
}
TEST_F(GetTimeOffsetTest, TimeMatch_ReturnsNearZero)
{
time_t now = time(nullptr);
verifier.setMockNetworkTime(now);
verifier.setMockLocalTime(now);
int offset = verifier.getTimeOffset();
EXPECT_NEAR(offset, 0, 2); // 允许2秒误差
}
// ============================================
// isTrial / isTrail 测试
// ============================================
class IsTrialTest : public ::testing::Test {
protected:
TestableDateVerify verifier;
void SetUp() override {
// 默认设置:网络正常,时间同步
time_t now = time(nullptr);
verifier.setMockNetworkTime(now);
verifier.setMockLocalTime(now);
}
};
TEST_F(IsTrialTest, WithinTrialPeriod_ReturnsTrue)
{
// 编译日期3天前
time_t now = time(nullptr);
tm* tmNow = localtime(&now);
// 创建3天前的日期
time_t threeDaysAgo = now - 3 * 86400;
tm* tmCompile = localtime(&threeDaysAgo);
std::string compileDate = formatCompileDate(
tmCompile->tm_year + 1900,
tmCompile->tm_mon + 1,
tmCompile->tm_mday
);
verifier.setMockCompileDate(compileDate);
EXPECT_TRUE(verifier.isTrial(7)); // 7天试用期内
}
TEST_F(IsTrialTest, ExactTrialPeriod_ReturnsTrue)
{
// 编译日期正好7天前
time_t now = time(nullptr);
time_t sevenDaysAgo = now - 7 * 86400;
tm* tmCompile = localtime(&sevenDaysAgo);
std::string compileDate = formatCompileDate(
tmCompile->tm_year + 1900,
tmCompile->tm_mon + 1,
tmCompile->tm_mday
);
verifier.setMockCompileDate(compileDate);
EXPECT_TRUE(verifier.isTrial(7)); // 边界正好7天
}
TEST_F(IsTrialTest, ExceedsTrialPeriod_ReturnsFalse)
{
// 编译日期8天前
time_t now = time(nullptr);
time_t eightDaysAgo = now - 8 * 86400;
tm* tmCompile = localtime(&eightDaysAgo);
std::string compileDate = formatCompileDate(
tmCompile->tm_year + 1900,
tmCompile->tm_mon + 1,
tmCompile->tm_mday
);
verifier.setMockCompileDate(compileDate);
EXPECT_FALSE(verifier.isTrial(7)); // 超过7天试用期
}
TEST_F(IsTrialTest, CompileToday_ReturnsTrue)
{
// 编译日期:今天
time_t now = time(nullptr);
tm* tmNow = localtime(&now);
std::string compileDate = formatCompileDate(
tmNow->tm_year + 1900,
tmNow->tm_mon + 1,
tmNow->tm_mday
);
verifier.setMockCompileDate(compileDate);
EXPECT_TRUE(verifier.isTrial(7));
EXPECT_TRUE(verifier.isTrial(1));
EXPECT_TRUE(verifier.isTrial(0));
}
TEST_F(IsTrialTest, TimeTampered_ReturnsFalse)
{
// 时间被篡改时,无论试用期如何都应返回 false
time_t now = time(nullptr);
verifier.setMockNetworkTime(now);
verifier.setMockLocalTime(now - 30 * 86400); // 本地时间落后30天
// 即使编译日期是今天,时间篡改也会导致返回 false
tm* tmNow = localtime(&now);
std::string compileDate = formatCompileDate(
tmNow->tm_year + 1900,
tmNow->tm_mon + 1,
tmNow->tm_mday
);
verifier.setMockCompileDate(compileDate);
EXPECT_FALSE(verifier.isTrial(7));
}
TEST_F(IsTrialTest, CustomTrialDays_Zero)
{
// 0天试用期只有编译当天有效
time_t now = time(nullptr);
time_t yesterday = now - 86400;
tm* tmYesterday = localtime(&yesterday);
std::string compileDate = formatCompileDate(
tmYesterday->tm_year + 1900,
tmYesterday->tm_mon + 1,
tmYesterday->tm_mday
);
verifier.setMockCompileDate(compileDate);
EXPECT_FALSE(verifier.isTrial(0)); // 昨天编译0天试用期已过
}
TEST_F(IsTrialTest, IsTrail_CompatibilityAlias)
{
// isTrail 应该与 isTrial 行为一致
time_t now = time(nullptr);
tm* tmNow = localtime(&now);
std::string compileDate = formatCompileDate(
tmNow->tm_year + 1900,
tmNow->tm_mon + 1,
tmNow->tm_mday
);
verifier.setMockCompileDate(compileDate);
EXPECT_EQ(verifier.isTrail(7), verifier.isTrial(7));
EXPECT_EQ(verifier.isTrail(0), verifier.isTrial(0));
}
// ============================================
// 边界条件测试
// ============================================
class BoundaryTest : public ::testing::Test {
protected:
TestableDateVerify verifier;
};
TEST_F(BoundaryTest, ToleranceDays_ExactBoundary)
{
// 测试容忍度边界:偏差正好等于容忍天数
time_t now = time(nullptr);
verifier.setMockNetworkTime(now);
verifier.setMockLocalTime(now - 86400); // 正好1天偏差
// 1天容忍度1天偏差应该通过<= 比较)
EXPECT_FALSE(verifier.isTimeTampered(1));
}
TEST_F(BoundaryTest, ToleranceDays_JustOverBoundary)
{
// 测试容忍度边界:偏差刚刚超过容忍天数
time_t now = time(nullptr);
verifier.setMockNetworkTime(now);
verifier.setMockLocalTime(now - 86400 - 3600); // 1天+1小时偏差
// 1天容忍度偏差超过1天应该失败
EXPECT_TRUE(verifier.isTimeTampered(1));
}
TEST_F(BoundaryTest, CacheInterval_ExactBoundary)
{
// 测试网络不可用时的24小时宽容期边界
time_t now = time(nullptr);
verifier.setMockNetworkTime(now);
verifier.setMockLocalTime(now);
EXPECT_FALSE(verifier.isTimeTampered(1));
// 正好24小时后刚好到达宽容期边界
verifier.setMockLocalTime(now + 24 * 3600);
verifier.setNetworkUnavailable();
// 刚好到达24小时边界网络不可用应报告篡改
EXPECT_TRUE(verifier.isTimeTampered(1));
}
TEST_F(BoundaryTest, CacheInterval_JustUnderBoundary)
{
// 测试缓存间隔边界略少于6小时
time_t now = time(nullptr);
verifier.setMockNetworkTime(now);
verifier.setMockLocalTime(now);
EXPECT_FALSE(verifier.isTimeTampered(1));
// 5小时59分钟后仍在缓存有效期内
verifier.setMockLocalTime(now + 6 * 3600 - 60);
verifier.setNetworkUnavailable();
// 仍在缓存有效期内
EXPECT_FALSE(verifier.isTimeTampered(1));
}
TEST_F(BoundaryTest, NetworkTimeRollback_AllowedMargin)
{
// 测试允许的时间回拨范围正好5分钟
time_t now = time(nullptr);
verifier.setMockNetworkTime(now);
verifier.setMockLocalTime(now);
EXPECT_FALSE(verifier.isTimeTampered(1));
// 回拨正好5分钟
verifier.setMockLocalTime(now - 300);
verifier.setNetworkUnavailable();
// 边界情况:-300 >= -300应该通过
EXPECT_FALSE(verifier.isTimeTampered(1));
}
TEST_F(BoundaryTest, NetworkTimeRollback_ExceedsMargin)
{
// 测试超过允许的时间回拨范围
time_t now = time(nullptr);
verifier.setMockNetworkTime(now);
verifier.setMockLocalTime(now);
EXPECT_FALSE(verifier.isTimeTampered(1));
// 回拨超过5分钟
verifier.setMockLocalTime(now - 301);
verifier.setNetworkUnavailable();
// 超过允许范围
EXPECT_TRUE(verifier.isTimeTampered(1));
}
TEST_F(BoundaryTest, TrialDays_LargeValue)
{
// 测试大试用期值
time_t now = time(nullptr);
verifier.setMockNetworkTime(now);
verifier.setMockLocalTime(now);
// 100天前编译
time_t hundredDaysAgo = now - 100 * 86400;
tm* tmCompile = localtime(&hundredDaysAgo);
std::string compileDate = formatCompileDate(
tmCompile->tm_year + 1900,
tmCompile->tm_mon + 1,
tmCompile->tm_mday
);
verifier.setMockCompileDate(compileDate);
EXPECT_FALSE(verifier.isTrial(99)); // 99天试用期已过
EXPECT_TRUE(verifier.isTrial(100)); // 正好100天
EXPECT_TRUE(verifier.isTrial(365)); // 365天试用期内
}
// ============================================
// 日期解析测试
// ============================================
class DateParsingTest : public ::testing::Test {
protected:
TestableDateVerify verifier;
void SetUp() override {
time_t now = time(nullptr);
verifier.setMockNetworkTime(now);
verifier.setMockLocalTime(now);
}
};
TEST_F(DateParsingTest, AllMonths)
{
// 测试所有月份的解析
const char* months[] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun",
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
time_t now = time(nullptr);
tm* tmNow = localtime(&now);
for (int i = 0; i < 12; ++i) {
char dateStr[16];
snprintf(dateStr, sizeof(dateStr), "%s %2d %d", months[i], 15, tmNow->tm_year + 1900);
verifier.setMockCompileDate(dateStr);
// 只要不是时间篡改,应该能正常解析
// 结果取决于当前日期与编译日期的差异
bool result = verifier.isTrial(365); // 使用较长试用期确保通过
EXPECT_TRUE(result) << "Failed for month: " << months[i];
}
}
TEST_F(DateParsingTest, SingleDigitDay)
{
// 测试单数字日期(如 "Mar 1 2026"
time_t now = time(nullptr);
tm* tmNow = localtime(&now);
char dateStr[16];
snprintf(dateStr, sizeof(dateStr), "Mar 1 %d", tmNow->tm_year + 1900);
verifier.setMockCompileDate(dateStr);
EXPECT_TRUE(verifier.isTrial(365));
}
TEST_F(DateParsingTest, DoubleDigitDay)
{
// 测试双数字日期(如 "Mar 15 2026"
time_t now = time(nullptr);
tm* tmNow = localtime(&now);
char dateStr[16];
snprintf(dateStr, sizeof(dateStr), "Mar 15 %d", tmNow->tm_year + 1900);
verifier.setMockCompileDate(dateStr);
EXPECT_TRUE(verifier.isTrial(365));
}
// ============================================
// 授权场景模拟测试
// ============================================
class AuthorizationScenarioTest : public ::testing::Test {
protected:
TestableDateVerify verifier;
};
TEST_F(AuthorizationScenarioTest, ValidLicense_TimeNotTampered)
{
// 场景:有效授权,时间未被篡改
time_t now = time(nullptr);
verifier.setMockNetworkTime(now);
verifier.setMockLocalTime(now);
// 授权检查应该通过
EXPECT_FALSE(verifier.isTimeTampered(1));
}
TEST_F(AuthorizationScenarioTest, ExpiredLicense_UserRollsBackTime)
{
// 场景:授权过期,用户将时间回拨企图绕过
time_t now = time(nullptr);
time_t thirtyDaysAgo = now - 30 * 86400;
verifier.setMockNetworkTime(now); // 网络时间是真实时间
verifier.setMockLocalTime(thirtyDaysAgo); // 用户将本地时间回拨30天
// 应该检测到时间篡改
EXPECT_TRUE(verifier.isTimeTampered(1));
}
TEST_F(AuthorizationScenarioTest, ExpiredLicense_UserAdvancesTime)
{
// 场景:用户将时间提前(不太常见,但也应检测)
time_t now = time(nullptr);
time_t thirtyDaysAhead = now + 30 * 86400;
verifier.setMockNetworkTime(now);
verifier.setMockLocalTime(thirtyDaysAhead);
// 应该检测到时间篡改
EXPECT_TRUE(verifier.isTimeTampered(1));
}
TEST_F(AuthorizationScenarioTest, OfflineUser_RecentValidation)
{
// 场景:用户刚刚验证通过后断网
time_t now = time(nullptr);
verifier.setMockNetworkTime(now);
verifier.setMockLocalTime(now);
EXPECT_FALSE(verifier.isTimeTampered(1)); // 首次验证通过
// 用户断网,但时间正常前进
verifier.setMockLocalTime(now + 3600); // 1小时后
verifier.setNetworkUnavailable();
// 应该允许(使用缓存)
EXPECT_FALSE(verifier.isTimeTampered(1));
}
TEST_F(AuthorizationScenarioTest, OfflineUser_LongOffline)
{
// 场景:用户长时间离线后恢复
time_t now = time(nullptr);
verifier.setMockNetworkTime(now);
verifier.setMockLocalTime(now);
EXPECT_FALSE(verifier.isTimeTampered(1));
// 用户离线超过24小时
verifier.setMockLocalTime(now + 25 * 3600);
verifier.setNetworkUnavailable();
// 缓存已过期,网络不可用,应该拒绝
EXPECT_TRUE(verifier.isTimeTampered(1));
}
TEST_F(AuthorizationScenarioTest, TrialUser_WithinPeriod)
{
// 场景:试用用户在试用期内
time_t now = time(nullptr);
verifier.setMockNetworkTime(now);
verifier.setMockLocalTime(now);
time_t threeDaysAgo = now - 3 * 86400;
tm* tmCompile = localtime(&threeDaysAgo);
verifier.setMockCompileDate(formatCompileDate(
tmCompile->tm_year + 1900,
tmCompile->tm_mon + 1,
tmCompile->tm_mday
));
EXPECT_TRUE(verifier.isTrial(7));
}
TEST_F(AuthorizationScenarioTest, TrialUser_Expired)
{
// 场景:试用用户试用期已过
time_t now = time(nullptr);
verifier.setMockNetworkTime(now);
verifier.setMockLocalTime(now);
time_t tenDaysAgo = now - 10 * 86400;
tm* tmCompile = localtime(&tenDaysAgo);
verifier.setMockCompileDate(formatCompileDate(
tmCompile->tm_year + 1900,
tmCompile->tm_mon + 1,
tmCompile->tm_mday
));
EXPECT_FALSE(verifier.isTrial(7));
}
TEST_F(AuthorizationScenarioTest, TrialUser_RollsBackTime)
{
// 场景:试用用户回拨时间企图延长试用期
time_t now = time(nullptr);
time_t tenDaysAgo = now - 10 * 86400;
verifier.setMockNetworkTime(now); // 真实网络时间
verifier.setMockLocalTime(tenDaysAgo); // 用户回拨到10天前
// 编译日期设为15天前
time_t fifteenDaysAgo = now - 15 * 86400;
tm* tmCompile = localtime(&fifteenDaysAgo);
verifier.setMockCompileDate(formatCompileDate(
tmCompile->tm_year + 1900,
tmCompile->tm_mon + 1,
tmCompile->tm_mday
));
// 时间篡改应被检测isTrial 应返回 false
EXPECT_FALSE(verifier.isTrial(7));
}