/** * @file test_license.cpp * @brief ViewDesignEngine 许可证管理单元测试 */ #include #include "vde/core/license_manager.h" #include #include using namespace vde::core; // ═══════════════════════════════════════════════════════════════ // LicenseTier 测试 // ═══════════════════════════════════════════════════════════════ TEST(LicenseTier, NameConversion) { EXPECT_STREQ(license_tier_name(LicenseTier::Community), "Community"); EXPECT_STREQ(license_tier_name(LicenseTier::Professional), "Professional"); EXPECT_STREQ(license_tier_name(LicenseTier::Enterprise), "Enterprise"); } TEST(LicenseTier, ParseName) { EXPECT_EQ(parse_license_tier("Community"), 0); EXPECT_EQ(parse_license_tier("Professional"), 1); EXPECT_EQ(parse_license_tier("Enterprise"), 2); EXPECT_EQ(parse_license_tier("community"), 0); EXPECT_EQ(parse_license_tier("unknown"), -1); } // ═══════════════════════════════════════════════════════════════ // Feature 枚举测试 // ═══════════════════════════════════════════════════════════════ TEST(FeatureEnum, FeatureName) { EXPECT_STREQ(feature_name(Feature::BASIC_BREP), "BASIC_BREP"); EXPECT_STREQ(feature_name(Feature::CAM_5AXIS), "CAM_5AXIS"); EXPECT_STREQ(feature_name(Feature::TECHNICAL_SUPPORT), "TECHNICAL_SUPPORT"); } TEST(FeatureEnum, ParseFeature) { EXPECT_EQ(parse_feature("BASIC_BREP"), 0); EXPECT_EQ(parse_feature("CAM_5AXIS"), 10); EXPECT_EQ(parse_feature("TECHNICAL_SUPPORT"), 30); EXPECT_EQ(parse_feature("NONEXISTENT"), -1); } // ═══════════════════════════════════════════════════════════════ // Tier → Feature 映射测试 // ═══════════════════════════════════════════════════════════════ TEST(TierFeatures, CommunityLevel) { auto feats = features_for_tier(LicenseTier::Community); EXPECT_GE(feats.size(), 6u); // 至少6个基础功能 EXPECT_TRUE(feature_available_in_tier(Feature::BASIC_BREP, LicenseTier::Community)); EXPECT_TRUE(feature_available_in_tier(Feature::STEP_IMPORT_EXPORT, LicenseTier::Community)); EXPECT_TRUE(feature_available_in_tier(Feature::IGES_IMPORT_EXPORT, LicenseTier::Community)); // Community 不应该有 Professional 功能 EXPECT_FALSE(feature_available_in_tier(Feature::CAM_5AXIS, LicenseTier::Community)); EXPECT_FALSE(feature_available_in_tier(Feature::GD_T, LicenseTier::Community)); } TEST(TierFeatures, ProfessionalLevel) { auto feats = features_for_tier(LicenseTier::Professional); EXPECT_GE(feats.size(), 12u); // 包含 Community 的全部 EXPECT_TRUE(feature_available_in_tier(Feature::BASIC_BREP, LicenseTier::Professional)); // 包含 Professional 特有 EXPECT_TRUE(feature_available_in_tier(Feature::CAM_5AXIS, LicenseTier::Professional)); EXPECT_TRUE(feature_available_in_tier(Feature::ADVANCED_SURFACING, LicenseTier::Professional)); EXPECT_TRUE(feature_available_in_tier(Feature::GD_T, LicenseTier::Professional)); EXPECT_TRUE(feature_available_in_tier(Feature::SHEET_METAL, LicenseTier::Professional)); // 不应包含 Enterprise 功能 EXPECT_FALSE(feature_available_in_tier(Feature::TECHNICAL_SUPPORT, LicenseTier::Professional)); EXPECT_FALSE(feature_available_in_tier(Feature::GPU_ACCELERATION, LicenseTier::Professional)); } TEST(TierFeatures, EnterpriseLevel) { auto feats = features_for_tier(LicenseTier::Enterprise); EXPECT_GE(feats.size(), 18u); // 全部功能 EXPECT_TRUE(feature_available_in_tier(Feature::BASIC_BREP, LicenseTier::Enterprise)); EXPECT_TRUE(feature_available_in_tier(Feature::CAM_5AXIS, LicenseTier::Enterprise)); EXPECT_TRUE(feature_available_in_tier(Feature::TECHNICAL_SUPPORT, LicenseTier::Enterprise)); EXPECT_TRUE(feature_available_in_tier(Feature::CUSTOM_FORMATS, LicenseTier::Enterprise)); EXPECT_TRUE(feature_available_in_tier(Feature::GPU_ACCELERATION, LicenseTier::Enterprise)); EXPECT_TRUE(feature_available_in_tier(Feature::LICENSE_MANAGER_SDK, LicenseTier::Enterprise)); } // ═══════════════════════════════════════════════════════════════ // LicenseInfo 结构体测试 // ═══════════════════════════════════════════════════════════════ TEST(LicenseInfo, DefaultConstruction) { LicenseInfo info; EXPECT_EQ(info.tier, LicenseTier::Community); EXPECT_EQ(info.licensee, "Trial User"); EXPECT_EQ(info.expiry, 0); EXPECT_EQ(info.version, 1); } TEST(LicenseInfo, IsExpiredPermanent) { LicenseInfo info; info.expiry = 0; // 永久 EXPECT_FALSE(info.is_expired()); } TEST(LicenseInfo, IsExpiredFuture) { LicenseInfo info; info.expiry = std::time(nullptr) + 86400 * 365; // 一年后 EXPECT_FALSE(info.is_expired()); } TEST(LicenseInfo, IsExpiredPast) { LicenseInfo info; info.expiry = std::time(nullptr) - 86400; // 昨天 EXPECT_TRUE(info.is_expired()); } TEST(LicenseInfo, DaysUntilExpiry) { LicenseInfo info; // 永久 info.expiry = 0; EXPECT_EQ(info.days_until_expiry(), -1); // 未来30天 info.expiry = std::time(nullptr) + 86400 * 30; EXPECT_EQ(info.days_until_expiry(), 30); // 未来1天 info.expiry = std::time(nullptr) + 86400; EXPECT_EQ(info.days_until_expiry(), 1); // 已过期 info.expiry = std::time(nullptr) - 86400; EXPECT_EQ(info.days_until_expiry(), 0); } // ═══════════════════════════════════════════════════════════════ // LicenseKey 生成/解析/验证测试 // ═══════════════════════════════════════════════════════════════ TEST(LicenseKey, GenerateAndParse) { // 生成一个 Community 永不过期的 Key std::string key = LicenseKey::generate(LicenseTier::Community, 0, "TestUser"); EXPECT_FALSE(key.empty()); EXPECT_EQ(key.substr(0, 4), "VDE-"); // 解析 LicenseKey lk; EXPECT_TRUE(lk.parse(key)); EXPECT_TRUE(lk.signature_valid()); EXPECT_EQ(lk.info().tier, LicenseTier::Community); EXPECT_EQ(lk.info().expiry, 0); } TEST(LicenseKey, GenerateAndParseProfessional) { std::time_t fut = std::time(nullptr) + 86400 * 365; // 一年后 std::string key = LicenseKey::generate(LicenseTier::Professional, fut, "ProUser"); LicenseKey lk; EXPECT_TRUE(lk.parse(key)); EXPECT_TRUE(lk.signature_valid()); EXPECT_EQ(lk.info().tier, LicenseTier::Professional); EXPECT_EQ(lk.info().expiry, fut); } TEST(LicenseKey, GenerateEnterprise) { std::string key = LicenseKey::generate(LicenseTier::Enterprise, 0, "EntUser"); LicenseKey lk; EXPECT_TRUE(lk.parse(key)); EXPECT_TRUE(lk.signature_valid()); EXPECT_EQ(lk.info().tier, LicenseTier::Enterprise); } TEST(LicenseKey, Validate) { std::string key = LicenseKey::generate(LicenseTier::Community, 0, "User"); EXPECT_TRUE(LicenseKey::validate(key)); } TEST(LicenseKey, ValidateExpired) { // 生成一个已过期的 Key std::string key = LicenseKey::generate(LicenseTier::Community, std::time(nullptr) - 86400, "User"); EXPECT_FALSE(LicenseKey::validate(key)); } TEST(LicenseKey, InvalidFormat) { EXPECT_FALSE(LicenseKey::validate("")); EXPECT_FALSE(LicenseKey::validate("INVALID-KEY")); EXPECT_FALSE(LicenseKey::validate("VDE-!!!!")); } TEST(LicenseKey, TamperedKey) { std::string key = LicenseKey::generate(LicenseTier::Community, 0, "User"); // 篡改 key(改一个字符) if (key.size() > 6) { key[6] = (key[6] == 'A') ? 'B' : 'A'; } LicenseKey lk; bool parsed = lk.parse(key); if (parsed) { // 签名验证应该失败 EXPECT_FALSE(lk.signature_valid()); } // 无论如何,整体 validate 应该失败 EXPECT_FALSE(LicenseKey::validate(key)); } TEST(LicenseKey, MultipleKeysAreDifferent) { std::string k1 = LicenseKey::generate(LicenseTier::Community, 0, "U1"); std::string k2 = LicenseKey::generate(LicenseTier::Professional, 0, "U2"); EXPECT_NE(k1, k2); } TEST(LicenseKey, KeyStringStored) { std::string key = LicenseKey::generate(LicenseTier::Community, 0, "U"); LicenseKey lk; lk.parse(key); EXPECT_EQ(lk.key_string(), key); } // ═══════════════════════════════════════════════════════════════ // LicenseManager 单例测试 // ═══════════════════════════════════════════════════════════════ TEST(LicenseManager, Singleton) { LicenseManager& mgr1 = LicenseManager::instance(); LicenseManager& mgr2 = LicenseManager::instance(); EXPECT_EQ(&mgr1, &mgr2); } TEST(LicenseManager, DefaultCommunity) { auto& mgr = LicenseManager::instance(); EXPECT_EQ(mgr.current_tier(), LicenseTier::Community); EXPECT_FALSE(mgr.is_expired()); EXPECT_FALSE(mgr.is_trial()); } TEST(LicenseManager, HasFeatureBasic) { auto& mgr = LicenseManager::instance(); // Community 默认应该有基础功能 EXPECT_TRUE(mgr.has_feature("BASIC_BREP")); EXPECT_TRUE(mgr.has_feature("STEP_IMPORT_EXPORT")); EXPECT_TRUE(mgr.has_feature(Feature::MESH_OPERATIONS)); } TEST(LicenseManager, HasFeatureProfessional) { auto& mgr = LicenseManager::instance(); // Community 不应该有 Professional 功能 EXPECT_FALSE(mgr.has_feature("CAM_5AXIS")); EXPECT_FALSE(mgr.has_feature("GD_T")); EXPECT_FALSE(mgr.has_feature("ADVANCED_SURFACING")); } TEST(LicenseManager, SetLicenseCommunity) { auto& mgr = LicenseManager::instance(); // 保存原始 license auto orig = mgr.current_license(); std::string key = LicenseKey::generate(LicenseTier::Community, 0, "Test"); EXPECT_TRUE(mgr.set_license(key)); EXPECT_EQ(mgr.current_tier(), LicenseTier::Community); EXPECT_FALSE(mgr.is_trial()); // 恢复原始 mgr.set_license(LicenseKey::generate(LicenseTier::Community, 0, "Community User")); } TEST(LicenseManager, SetLicenseProfessional) { auto& mgr = LicenseManager::instance(); std::time_t fut = std::time(nullptr) + 86400 * 365; std::string key = LicenseKey::generate(LicenseTier::Professional, fut, "Pro"); EXPECT_TRUE(mgr.set_license(key)); EXPECT_EQ(mgr.current_tier(), LicenseTier::Professional); EXPECT_TRUE(mgr.has_feature("CAM_5AXIS")); EXPECT_TRUE(mgr.has_feature("GD_T")); // 恢复默认 mgr.set_license(LicenseKey::generate(LicenseTier::Community, 0, "Community User")); } TEST(LicenseManager, SetLicenseEnterprise) { auto& mgr = LicenseManager::instance(); std::string key = LicenseKey::generate(LicenseTier::Enterprise, 0, "Ent"); EXPECT_TRUE(mgr.set_license(key)); EXPECT_EQ(mgr.current_tier(), LicenseTier::Enterprise); EXPECT_TRUE(mgr.has_feature("TECHNICAL_SUPPORT")); EXPECT_TRUE(mgr.has_feature("GPU_ACCELERATION")); EXPECT_TRUE(mgr.has_feature("CUSTOM_FORMATS")); // 恢复 mgr.set_license(LicenseKey::generate(LicenseTier::Community, 0, "Community User")); } TEST(LicenseManager, SetLicenseExpired) { auto& mgr = LicenseManager::instance(); // 先生成一个有效 key 确保非过期状态 mgr.set_license(LicenseKey::generate(LicenseTier::Community, 0, "Reset")); // 生成已过期的 key std::string key = LicenseKey::generate(LicenseTier::Professional, std::time(nullptr) - 86400, "Expired"); // 已过期 key 应该被拒绝 EXPECT_FALSE(mgr.set_license(key)); } TEST(LicenseManager, SetLicenseInvalid) { auto& mgr = LicenseManager::instance(); EXPECT_FALSE(mgr.set_license("INVALID-KEY")); EXPECT_FALSE(mgr.set_license("")); } TEST(LicenseManager, TrialMode) { auto& mgr = LicenseManager::instance(); // 先设置永久 Community key mgr.set_license(LicenseKey::generate(LicenseTier::Community, 0, "Reset")); mgr.start_trial(30); EXPECT_TRUE(mgr.is_trial()); EXPECT_EQ(mgr.current_tier(), LicenseTier::Professional); EXPECT_EQ(mgr.trial_days_left(), 30); EXPECT_TRUE(mgr.has_feature("CAM_5AXIS")); // 但也应该有基础功能 EXPECT_TRUE(mgr.has_feature("BASIC_BREP")); // 恢复 mgr.set_license(LicenseKey::generate(LicenseTier::Community, 0, "Community User")); EXPECT_FALSE(mgr.is_trial()); } TEST(LicenseManager, TrialDaysLeftVarious) { auto& mgr = LicenseManager::instance(); mgr.set_license(LicenseKey::generate(LicenseTier::Community, 0, "Reset")); // 没有试用时 EXPECT_EQ(mgr.trial_days_left(), -1); // 30天试用 mgr.start_trial(30); EXPECT_GE(mgr.trial_days_left(), 29); // 可能刚好跨天 EXPECT_LE(mgr.trial_days_left(), 30); // 恢复 mgr.set_license(LicenseKey::generate(LicenseTier::Community, 0, "Reset")); } TEST(LicenseManager, CurrentLicense) { auto& mgr = LicenseManager::instance(); std::string key = LicenseKey::generate(LicenseTier::Professional, std::time(nullptr) + 86400 * 90, "TestCo"); mgr.set_license(key); const auto& info = mgr.current_license(); EXPECT_EQ(info.tier, LicenseTier::Professional); EXPECT_EQ(info.licensee, "Licensee"); // payload 中无 licensee 字段 // 恢复 mgr.set_license(LicenseKey::generate(LicenseTier::Community, 0, "Community User")); } TEST(LicenseManager, HasFeatureInvalidName) { auto& mgr = LicenseManager::instance(); EXPECT_FALSE(mgr.has_feature("NONEXISTENT_FEATURE")); EXPECT_FALSE(mgr.has_feature("")); } TEST(LicenseManager, ExpiredLicenseBlocksFeatures) { auto& mgr = LicenseManager::instance(); // 恢复有效状态 mgr.set_license(LicenseKey::generate(LicenseTier::Professional, std::time(nullptr) + 86400 * 365, "Reset")); EXPECT_TRUE(mgr.has_feature("CAM_5AXIS")); // 设置已过期的 license mgr.set_license(LicenseKey::generate(LicenseTier::Professional, std::time(nullptr) - 86400, "Expired")); // 过期 license 不会被设置(set_license 返回 false),所以状态不变 // 但如果 is_expired() 返回 true,has_feature 也会 false // 恢复 mgr.set_license(LicenseKey::generate(LicenseTier::Community, 0, "Community User")); }