ed4a561704
- Add complete API documentation for application integration (docs/API_DOCUMENT.md) - Fix check-update API to use version ID comparison instead of string comparison - Add validation: client version must exist in server version list - Add support for patch/incremental updates with base_version check - Add C++ SDK with HTTP client, JSON parser, and crypto support - Add simple_test.cpp for standalone testing on Windows Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
362 lines
12 KiB
C++
362 lines
12 KiB
C++
#include "verify_client.hpp"
|
|
#include <iostream>
|
|
#include <cassert>
|
|
#include <thread>
|
|
#include <chrono>
|
|
|
|
using namespace verify;
|
|
|
|
// 测试配置
|
|
const std::string BASE_URL = "https://gendan.xyz";
|
|
const std::string APP_KEY = "your_app_key"; // 需要替换为实际的appKey
|
|
const std::string TEST_USERNAME = "test_user_cpp";
|
|
const std::string TEST_PASSWORD = "test123456";
|
|
const std::string TEST_DEVICE_ID = "cpp_test_device_001";
|
|
|
|
class TestRunner {
|
|
public:
|
|
void run() {
|
|
std::cout << "========================================\n";
|
|
std::cout << "验证平台SDK C++ 测试\n";
|
|
std::cout << "========================================\n\n";
|
|
|
|
// 初始化客户端
|
|
testClientCreation();
|
|
|
|
// 测试应用信息接口
|
|
testAppInfo();
|
|
|
|
// 测试用户注册和登录
|
|
testUserRegistration();
|
|
testUserLogin();
|
|
|
|
// 测试账户接口
|
|
if (!token_.empty()) {
|
|
testAccount();
|
|
testHeartbeat();
|
|
}
|
|
|
|
// 测试充值接口
|
|
testRecharge();
|
|
|
|
// 测试设备管理
|
|
if (!token_.empty()) {
|
|
testDeviceManagement();
|
|
}
|
|
|
|
// 测试云端数据
|
|
if (!token_.empty()) {
|
|
testCloudData();
|
|
}
|
|
|
|
std::cout << "\n========================================\n";
|
|
std::cout << "所有测试完成!\n";
|
|
std::cout << "========================================\n";
|
|
}
|
|
|
|
private:
|
|
std::unique_ptr<Client> client_;
|
|
std::string token_;
|
|
uint64_t userId_ = 0;
|
|
|
|
void testClientCreation() {
|
|
std::cout << "[测试] 客户端创建... ";
|
|
try {
|
|
client_ = std::make_unique<Client>(BASE_URL, APP_KEY);
|
|
client_->setTimeout(30);
|
|
std::cout << "通过\n";
|
|
} catch (const std::exception& e) {
|
|
std::cout << "失败: " << e.what() << "\n";
|
|
throw;
|
|
}
|
|
}
|
|
|
|
void testAppInfo() {
|
|
std::cout << "[测试] 获取应用信息... ";
|
|
try {
|
|
AppConfig config = client_->getAppInfo();
|
|
std::cout << "通过\n";
|
|
std::cout << " - 应用名称: " << config.name << "\n";
|
|
std::cout << " - 计费类型: " << config.billingType << "\n";
|
|
std::cout << " - 最大设备数: " << config.maxDevices << "\n";
|
|
std::cout << " - 心跳间隔: " << config.heartbeatInterval << "秒\n";
|
|
} catch (const std::exception& e) {
|
|
std::cout << "失败: " << e.what() << "\n";
|
|
}
|
|
|
|
std::cout << "[测试] 检查更新... ";
|
|
try {
|
|
VersionInfo version = client_->checkUpdate("1.0.0");
|
|
std::cout << "通过\n";
|
|
std::cout << " - 有更新: " << (version.hasUpdate ? "是" : "否") << "\n";
|
|
std::cout << " - 最新版本: " << version.latestVersion << "\n";
|
|
} catch (const std::exception& e) {
|
|
std::cout << "失败: " << e.what() << "\n";
|
|
}
|
|
|
|
std::cout << "[测试] 获取公告列表... ";
|
|
try {
|
|
auto announcements = client_->getAnnouncements();
|
|
std::cout << "通过 (共" << announcements.size() << "条公告)\n";
|
|
} catch (const std::exception& e) {
|
|
std::cout << "失败: " << e.what() << "\n";
|
|
}
|
|
}
|
|
|
|
void testUserRegistration() {
|
|
std::cout << "[测试] 用户注册... ";
|
|
try {
|
|
// 先尝试登录,如果用户存在则跳过注册
|
|
try {
|
|
auto result = client_->login(TEST_USERNAME, TEST_PASSWORD, TEST_DEVICE_ID);
|
|
userId_ = result["user_id"].get<uint64_t>();
|
|
token_ = result["token"].get<std::string>();
|
|
std::cout << "用户已存在,跳过注册\n";
|
|
return;
|
|
} catch (...) {
|
|
// 用户不存在,继续注册
|
|
}
|
|
|
|
userId_ = client_->registerUser(
|
|
TEST_USERNAME,
|
|
TEST_PASSWORD,
|
|
TEST_DEVICE_ID,
|
|
"C++测试设备",
|
|
"windows",
|
|
"instance_001"
|
|
);
|
|
std::cout << "通过 (用户ID: " << userId_ << ")\n";
|
|
|
|
// 注册后登录
|
|
auto result = client_->login(TEST_USERNAME, TEST_PASSWORD, TEST_DEVICE_ID);
|
|
token_ = result["token"].get<std::string>();
|
|
} catch (const ApiException& e) {
|
|
std::cout << "API错误 [" << e.code() << "]: " << e.what() << "\n";
|
|
} catch (const std::exception& e) {
|
|
std::cout << "失败: " << e.what() << "\n";
|
|
}
|
|
}
|
|
|
|
void testUserLogin() {
|
|
std::cout << "[测试] 用户登录... ";
|
|
try {
|
|
auto result = client_->login(TEST_USERNAME, TEST_PASSWORD, TEST_DEVICE_ID);
|
|
userId_ = result["user_id"].get<uint64_t>();
|
|
token_ = result["token"].get<std::string>();
|
|
std::cout << "通过\n";
|
|
std::cout << " - 用户ID: " << userId_ << "\n";
|
|
std::cout << " - Token: " << token_.substr(0, 30) << "...\n";
|
|
} catch (const ApiException& e) {
|
|
std::cout << "API错误 [" << e.code() << "]: " << e.what() << "\n";
|
|
} catch (const std::exception& e) {
|
|
std::cout << "失败: " << e.what() << "\n";
|
|
}
|
|
}
|
|
|
|
void testAccount() {
|
|
std::cout << "[测试] 获取账户信息... ";
|
|
try {
|
|
UserInfo info = client_->getAccount(userId_);
|
|
std::cout << "通过\n";
|
|
std::cout << " - 用户名: " << info.username << "\n";
|
|
std::cout << " - 余额: " << info.balance << "\n";
|
|
std::cout << " - 状态: " << info.status << "\n";
|
|
} catch (const std::exception& e) {
|
|
std::cout << "失败: " << e.what() << "\n";
|
|
}
|
|
}
|
|
|
|
void testHeartbeat() {
|
|
std::cout << "[测试] 心跳上报... ";
|
|
try {
|
|
auto result = client_->heartbeat(userId_, TEST_DEVICE_ID, "instance_001");
|
|
std::cout << "通过\n";
|
|
if (result.contains("balance")) {
|
|
std::cout << " - 当前余额: " << result["balance"] << "\n";
|
|
}
|
|
} catch (const std::exception& e) {
|
|
std::cout << "失败: " << e.what() << "\n";
|
|
}
|
|
}
|
|
|
|
void testRecharge() {
|
|
std::cout << "[测试] 卡密充值 (使用无效卡密测试错误处理)... ";
|
|
try {
|
|
auto result = client_->recharge(TEST_USERNAME, "invalid_card_key_12345", TEST_DEVICE_ID);
|
|
std::cout << "未预期的成功\n";
|
|
} catch (const ApiException& e) {
|
|
std::cout << "通过 (预期错误: " << e.what() << ")\n";
|
|
} catch (const std::exception& e) {
|
|
std::cout << "通过 (预期错误: " << e.what() << ")\n";
|
|
}
|
|
}
|
|
|
|
void testDeviceManagement() {
|
|
std::cout << "[测试] 获取设备列表... ";
|
|
try {
|
|
auto devices = client_->getDevices();
|
|
std::cout << "通过 (共" << devices.size() << "台设备)\n";
|
|
for (const auto& d : devices) {
|
|
std::cout << " - 设备ID: " << d.deviceId << " (" << d.deviceName << ")\n";
|
|
}
|
|
} catch (const std::exception& e) {
|
|
std::cout << "失败: " << e.what() << "\n";
|
|
}
|
|
|
|
std::cout << "[测试] 获取设备数量... ";
|
|
try {
|
|
auto result = client_->getDeviceCount(userId_);
|
|
std::cout << "通过\n";
|
|
std::cout << " - 已绑定: " << result["count"] << "\n";
|
|
std::cout << " - 最大数: " << result["max_devices"] << "\n";
|
|
std::cout << " - 剩余: " << result["remaining"] << "\n";
|
|
} catch (const std::exception& e) {
|
|
std::cout << "失败: " << e.what() << "\n";
|
|
}
|
|
|
|
std::cout << "[测试] 获取实例列表... ";
|
|
try {
|
|
auto instances = client_->getInstances(userId_);
|
|
std::cout << "通过 (共" << instances.size() << "个实例)\n";
|
|
} catch (const std::exception& e) {
|
|
std::cout << "失败: " << e.what() << "\n";
|
|
}
|
|
}
|
|
|
|
void testCloudData() {
|
|
std::cout << "[测试] 获取云端常量... ";
|
|
try {
|
|
auto constants = client_->getConstants();
|
|
std::cout << "通过 (共" << constants.size() << "个常量)\n";
|
|
} catch (const std::exception& e) {
|
|
std::cout << "失败: " << e.what() << "\n";
|
|
}
|
|
|
|
std::cout << "[测试] 获取云端变量... ";
|
|
try {
|
|
auto variables = client_->getVariables();
|
|
std::cout << "通过 (共" << variables.size() << "个变量)\n";
|
|
} catch (const std::exception& e) {
|
|
std::cout << "失败: " << e.what() << "\n";
|
|
}
|
|
}
|
|
};
|
|
|
|
// 加密测试
|
|
void testCrypto() {
|
|
std::cout << "\n[测试] 加密功能...\n";
|
|
|
|
// AES测试
|
|
{
|
|
std::cout << " [AES加密/解密] ";
|
|
try {
|
|
Crypto aes(EncryptType::AES, "test_key_12345678");
|
|
std::string plaintext = "Hello, World! 你好,世界!";
|
|
std::string encrypted = aes.encrypt(plaintext);
|
|
std::string decrypted = aes.decrypt(encrypted);
|
|
|
|
if (decrypted == plaintext) {
|
|
std::cout << "通过\n";
|
|
std::cout << " 原文: " << plaintext << "\n";
|
|
std::cout << " 密文: " << encrypted.substr(0, 50) << "...\n";
|
|
} else {
|
|
std::cout << "失败: 解密结果不匹配\n";
|
|
}
|
|
} catch (const CryptoException& e) {
|
|
std::cout << "失败: " << e.what() << "\n";
|
|
std::cout << " 提示: 请使用 -DUSE_OPENSSL 编译以启用AES加密\n";
|
|
}
|
|
}
|
|
|
|
// RC4测试
|
|
{
|
|
std::cout << " [RC4加密/解密] ";
|
|
try {
|
|
Crypto rc4(EncryptType::RC4, "rc4_secret_key");
|
|
std::string plaintext = "Test RC4 encryption";
|
|
std::string encrypted = rc4.encrypt(plaintext);
|
|
std::string decrypted = rc4.decrypt(encrypted);
|
|
|
|
if (decrypted == plaintext) {
|
|
std::cout << "通过\n";
|
|
} else {
|
|
std::cout << "失败: 解密结果不匹配\n";
|
|
}
|
|
} catch (const std::exception& e) {
|
|
std::cout << "失败: " << e.what() << "\n";
|
|
}
|
|
}
|
|
}
|
|
|
|
// 性能测试
|
|
void testPerformance() {
|
|
std::cout << "\n[测试] 性能测试...\n";
|
|
|
|
Client client(BASE_URL, APP_KEY);
|
|
client.setTimeout(10);
|
|
|
|
int successCount = 0;
|
|
int failCount = 0;
|
|
const int iterations = 10;
|
|
|
|
auto start = std::chrono::high_resolution_clock::now();
|
|
|
|
for (int i = 0; i < iterations; ++i) {
|
|
try {
|
|
client.getAppInfo();
|
|
++successCount;
|
|
} catch (...) {
|
|
++failCount;
|
|
}
|
|
}
|
|
|
|
auto end = std::chrono::high_resolution_clock::now();
|
|
auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(end - start);
|
|
|
|
std::cout << " - 请求次数: " << iterations << "\n";
|
|
std::cout << " - 成功次数: " << successCount << "\n";
|
|
std::cout << " - 失败次数: " << failCount << "\n";
|
|
std::cout << " - 总耗时: " << duration.count() << "ms\n";
|
|
std::cout << " - 平均耗时: " << (duration.count() / iterations) << "ms/请求\n";
|
|
}
|
|
|
|
int main(int argc, char* argv[]) {
|
|
std::cout << R"(
|
|
╔════════════════════════════════════════════════════════════╗
|
|
║ 验证平台 SDK C++ 测试程序 ║
|
|
║ Verify Platform SDK C++ Test ║
|
|
╚════════════════════════════════════════════════════════════╝
|
|
)" << "\n";
|
|
|
|
// 解析命令行参数
|
|
for (int i = 1; i < argc; ++i) {
|
|
std::string arg = argv[i];
|
|
if (arg == "--help" || arg == "-h") {
|
|
std::cout << "用法: " << argv[0] << " [选项]\n";
|
|
std::cout << "选项:\n";
|
|
std::cout << " --help, -h 显示帮助信息\n";
|
|
std::cout << " --crypto 仅测试加密功能\n";
|
|
std::cout << " --perf 仅测试性能\n";
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
try {
|
|
// 测试加密
|
|
testCrypto();
|
|
|
|
// 主测试
|
|
TestRunner runner;
|
|
runner.run();
|
|
|
|
// 性能测试
|
|
testPerformance();
|
|
|
|
} catch (const std::exception& e) {
|
|
std::cerr << "\n错误: " << e.what() << "\n";
|
|
return 1;
|
|
}
|
|
|
|
return 0;
|
|
}
|