Files
cos-cpp-sdk-v5/demo/stable_test.cpp
a158 3cf88acc07 BG
2026-04-05 20:22:11 +08:00

395 lines
16 KiB
C++

// Copyright (c) 2022, Tencent Inc.
// All rights reserved.
#include <stdlib.h>
#include <sys/stat.h>
#include <iostream>
#include <map>
#include <string>
#include <thread>
#include <vector>
#include "cos_api.h"
#include "cos_sys_config.h"
#include "util/auth_tool.h"
#include "util/test_utils.h"
using namespace qcloud_cos;
static void PrintResult(const qcloud_cos::CosResult& result) {
std::stringstream oss;
oss << "ErrorMsg=" << result.GetErrorMsg() << std::endl;
oss << "HttpStatus=" << result.GetHttpStatus() << std::endl;
oss << "ErrorCode=" << result.GetErrorCode() << std::endl;
oss << "ErrorMsg=" << result.GetErrorMsg() << std::endl;
oss << "ResourceAddr=" << result.GetResourceAddr() << std::endl;
oss << "XCosRequestId=" << result.GetXCosRequestId() << std::endl;
oss << "XCosTraceId=" << result.GetXCosTraceId() << std::endl;
SDK_LOG_INFO("%s", oss.str().c_str());
}
enum PutOpType { SIMPLE_PUT = 1, MULTI_PUT, ASYNC_PUT, ASYNC_MULTI_PUT };
enum GetOpType { SIMPLE_GET = 6, MULTI_GET, ASYNC_GET, ASYNC_MULTI_GET };
#define GENERATE_LOCAL_FILE(size) \
std::string object_name = "stable_test_size_" + std::to_string(size); \
std::string local_file = "./" + object_name; \
SDK_LOG_INFO("generate local file: %s", local_file.c_str()); \
TestUtils::WriteRandomDatatoFile(local_file, file_size); \
uint64_t file_crc64_origin = FileUtil::GetFileCrc64(local_file); \
std::string file_md5_origin = FileUtil::GetFileMd5(local_file); \
SDK_LOG_INFO("file_crc64_origin: %lu", file_crc64_origin); \
SDK_LOG_INFO("file_md5_origin: %s", file_md5_origin.c_str());
#define CHECK_COMMON_RESULT(result) \
assert(result.IsSucc()); \
assert(!result.GetXCosRequestId().empty()); \
assert(result.GetHttpStatus() >= 200 && result.GetHttpStatus() < 300);
#define CHECK_COMMON_RESP(resp) \
assert(resp.GetServer() == "tencent-cos"); \
assert(!resp.GetDate().empty()); \
assert(!resp.GetConnection().empty()); \
assert(!resp.GetXCosRequestId().empty());
#define CHECK_PUT_RESP(resp, op_type) \
assert(resp.GetXCosHashCrc64Ecma() == std::to_string(file_crc64_origin)); \
if (op_type == MULTI_PUT || op_type == ASYNC_MULTI_PUT) { \
assert(!resp.GetContentType().empty()); \
assert(resp.GetEtag() != file_md5_origin); \
} else { \
assert(resp.GetEtag() == file_md5_origin); \
}
#define CHECK_HEAD_RESP(resp) \
assert(resp.GetXCosHashCrc64Ecma() == std::to_string(file_crc64_origin)); \
assert(resp.GetContentLength() == file_size); \
assert(!resp.GetLastModified().empty());
#define CHECK_GET_RESP(resp, op_type) \
assert(resp.GetXCosHashCrc64Ecma() == std::to_string(file_crc64_origin)); \
assert(!resp.GetLastModified().empty()); \
std::string file_md5_download = TestUtils::CalcFileMd5(local_file_download); \
assert(file_md5_download == file_md5_origin); \
if (op_type == SIMPLE_GET || op_type == ASYNC_GET) { \
assert(resp.GetContentLength() == file_size); \
}
class TestStatistics {
public:
TestStatistics()
: put_object_succ(0),
put_object_fail(0),
multi_put_object_succ(0),
multi_put_object_fail(0),
async_put_object_succ(0),
async_put_object_fail(0),
async_multi_put_object_succ(0),
async_multi_put_object_fail(0),
get_object_succ(0),
get_object_fail(0),
multi_get_object_succ(0),
multi_get_object_fail(0),
async_get_object_succ(0),
async_get_object_fail(0),
async_multi_get_object_succ(0),
async_multi_get_object_fail(0),
head_object_succ(0),
head_object_fail(0),
delete_object_succ(0),
delete_object_fail(0) {}
int put_object_succ;
int put_object_fail;
int multi_put_object_succ;
int multi_put_object_fail;
int async_put_object_succ;
int async_put_object_fail;
int async_multi_put_object_succ;
int async_multi_put_object_fail;
int get_object_succ;
int get_object_fail;
int multi_get_object_succ;
int multi_get_object_fail;
int async_get_object_succ;
int async_get_object_fail;
int async_multi_get_object_succ;
int async_multi_get_object_fail;
int head_object_succ;
int head_object_fail;
int delete_object_succ;
int delete_object_fail;
void UpdataStat(bool succ, int op_type) {
switch (op_type) {
case SIMPLE_PUT:
succ ? put_object_succ++ : put_object_fail++;
case MULTI_PUT:
succ ? multi_put_object_succ++ : multi_put_object_fail++;
case ASYNC_PUT:
succ ? async_put_object_succ++ : async_put_object_fail++;
case ASYNC_MULTI_PUT:
succ ? async_multi_put_object_succ++ : async_multi_put_object_fail++;
case SIMPLE_GET:
succ ? get_object_succ++ : get_object_fail++;
case MULTI_GET:
succ ? multi_get_object_succ++ : multi_get_object_fail++;
case ASYNC_GET:
succ ? async_get_object_succ++ : async_get_object_fail++;
case ASYNC_MULTI_GET:
succ ? async_multi_get_object_succ++ : async_multi_get_object_fail++;
}
}
void PrintStat() {
std::stringstream oss;
oss << std::endl;
oss << "put_object_succ:" << put_object_succ << std::endl;
oss << "put_object_fail:" << put_object_fail << std::endl;
oss << "multi_put_object_succ:" << put_object_succ << std::endl;
oss << "multi_put_object_fail:" << put_object_fail << std::endl;
oss << "async_put_object_succ:" << put_object_succ << std::endl;
oss << "async_put_object_fail:" << put_object_fail << std::endl;
oss << "async_multi_put_object_succ:" << put_object_succ << std::endl;
oss << "async_multi_put_object_fail:" << put_object_fail << std::endl;
oss << "get_object_succ:" << put_object_succ << std::endl;
oss << "get_object_fail:" << put_object_fail << std::endl;
oss << "multi_get_object_succ:" << put_object_succ << std::endl;
oss << "multi_get_object_fail:" << put_object_fail << std::endl;
oss << "async_get_object_succ:" << put_object_succ << std::endl;
oss << "async_get_object_fail:" << put_object_fail << std::endl;
oss << "async_multi_get_object_succ:" << put_object_succ << std::endl;
oss << "async_multi_get_object_fail:" << put_object_fail << std::endl;
oss << "head_object_succ:" << put_object_succ << std::endl;
oss << "head_object_fail:" << put_object_fail << std::endl;
oss << "delete_object_succ:" << put_object_succ << std::endl;
oss << "delete_object_fail:" << put_object_fail << std::endl;
SDK_LOG_INFO("%s", oss.str().c_str());
}
};
void TestLogCallback(const std::string& log) {
std::ofstream ofs;
ofs.open("./stable_test.log", std::ios_base::app);
ofs << log;
ofs.close();
}
int main(int argc, char** argv) {
UNUSED_PARAM(argc)
UNUSED_PARAM(argv)
qcloud_cos::CosConfig config("./config.json");
config.SetLogCallback(&TestLogCallback);
qcloud_cos::CosAPI cos(config);
TestStatistics stat;
std::string bucket_name = "test-12345678";
size_t max_file_size = 100 * 1024 * 1024;
while (true) {
std::vector<int> put_op_type_v = {SIMPLE_PUT, MULTI_PUT, ASYNC_PUT,
ASYNC_MULTI_PUT};
for (auto& op_type : put_op_type_v) {
size_t file_size = rand() % max_file_size;
GENERATE_LOCAL_FILE(file_size)
bool done = false;
std::mutex mutex;
std::condition_variable cond;
auto put_done_cb = [file_crc64_origin, file_md5_origin, &done, &mutex,
&cond, &stat](const SharedAsyncContext& context,
void* user_data) {
int op_type = (*reinterpret_cast<int*>(user_data));
CHECK_COMMON_RESULT(context->GetResult())
if (context->GetResult().IsSucc()) {
stat.UpdataStat(true, op_type);
} else {
stat.UpdataStat(false, op_type);
}
AsyncResp resp = context->GetAsyncResp();
CHECK_COMMON_RESP(resp)
CHECK_PUT_RESP(resp, op_type)
done = true;
std::unique_lock<std::mutex> lock(mutex);
cond.notify_one();
};
// put object
CosResult result;
PutObjectByFileResp resp1;
MultiPutObjectResp resp2;
if (op_type == SIMPLE_PUT) {
SDK_LOG_INFO("put object, object_name: %s", object_name.c_str());
PutObjectByFileReq req(bucket_name, object_name, local_file);
result = cos.PutObject(req, &resp1);
} else if (op_type == MULTI_PUT) {
SDK_LOG_INFO("multi put object, object_name: %s", object_name.c_str());
MultiPutObjectReq req(bucket_name, object_name, local_file);
result = cos.MultiPutObject(req, &resp2);
} else if (op_type == ASYNC_PUT) {
SDK_LOG_INFO("async put object, object_name: %s", object_name.c_str());
AsyncPutObjectReq req(bucket_name, object_name, local_file);
req.SetDoneCallback(put_done_cb);
req.SetUserData(reinterpret_cast<void*>(&op_type));
MultiPutObjectResp resp;
cos.AsyncPutObject(req);
} else if (op_type == ASYNC_MULTI_PUT) {
SDK_LOG_INFO("async multi put object, object_name: %s",
object_name.c_str());
AsyncMultiPutObjectReq req(bucket_name, object_name, local_file);
req.SetUserData(reinterpret_cast<void*>(&op_type));
req.SetDoneCallback(put_done_cb);
cos.AsyncMultiPutObject(req);
}
if (op_type == SIMPLE_PUT || op_type == MULTI_PUT) {
if (!result.IsSucc()) {
SDK_LOG_ERR("failed to put object, object_name: %s",
object_name.c_str());
PrintResult(result);
stat.UpdataStat(false, op_type);
} else {
stat.UpdataStat(true, op_type);
CHECK_COMMON_RESULT(result)
if (op_type == SIMPLE_PUT) {
CHECK_COMMON_RESP(resp1)
CHECK_PUT_RESP(resp1, op_type)
} else {
CHECK_COMMON_RESP(resp2)
CHECK_PUT_RESP(resp2, op_type)
}
}
} else {
while (!done) {
SDK_LOG_INFO("wait for put completing, object_name: %s",
object_name.c_str());
std::unique_lock<std::mutex> lock(mutex);
cond.wait_until(
lock, std::chrono::system_clock::now() + std::chrono::seconds(1));
}
}
// head object
HeadObjectReq head_req(bucket_name, object_name);
HeadObjectResp headresp;
SDK_LOG_INFO("head object, object_name: %s", object_name.c_str());
result = cos.HeadObject(head_req, &headresp);
if (!result.IsSucc()) {
SDK_LOG_ERR("failed to head object, object_name: %s",
object_name.c_str());
PrintResult(result);
stat.head_object_fail++;
} else {
stat.head_object_succ++;
CHECK_COMMON_RESULT(result)
CHECK_COMMON_RESP(headresp)
CHECK_HEAD_RESP(headresp)
}
// get object
// 使用多个接口下载同一个对象
done = false;
std::string local_file_download = local_file + "_download";
auto get_done_cb = [file_size, local_file_download, file_crc64_origin,
file_md5_origin, &done, &mutex, &cond,
&stat](const SharedAsyncContext& context,
void* user_data) {
int op_type = (*reinterpret_cast<int*>(user_data));
CHECK_COMMON_RESULT(context->GetResult())
if (context->GetResult().IsSucc()) {
stat.UpdataStat(true, op_type);
} else {
stat.UpdataStat(false, op_type);
}
AsyncResp resp = context->GetAsyncResp();
CHECK_COMMON_RESP(resp)
CHECK_GET_RESP(resp, op_type)
done = true;
std::unique_lock<std::mutex> lock(mutex);
cond.notify_one();
};
std::vector<int> get_op_type_v = {SIMPLE_GET, MULTI_GET, ASYNC_GET,
ASYNC_MULTI_GET};
for (auto& op_type : get_op_type_v) {
GetObjectByFileResp resp1;
MultiGetObjectResp resp2;
if (op_type == SIMPLE_GET) {
SDK_LOG_INFO("get object, object_name: %s", object_name.c_str());
GetObjectByFileReq req(bucket_name, object_name, local_file_download);
result = cos.GetObject(req, &resp1);
} else if (op_type == MULTI_GET) {
SDK_LOG_INFO("multi get object, object_name: %s",
object_name.c_str());
MultiGetObjectReq req(bucket_name, object_name, local_file_download);
result = cos.MultiGetObject(req, &resp2);
} else if (op_type == ASYNC_GET) {
SDK_LOG_INFO("async get object, object_name: %s",
object_name.c_str());
AsyncGetObjectReq req(bucket_name, object_name, local_file_download);
req.SetDoneCallback(get_done_cb);
req.SetUserData(reinterpret_cast<void*>(&op_type));
cos.AsyncGetObject(req);
} else if (op_type == ASYNC_MULTI_GET) {
SDK_LOG_INFO("async multi get object, object_name: %s",
object_name.c_str());
AsyncMultiGetObjectReq req(bucket_name, object_name,
local_file_download);
req.SetUserData(reinterpret_cast<void*>(&op_type));
req.SetDoneCallback(get_done_cb);
cos.AsyncMultiGetObject(req);
}
if (op_type == SIMPLE_GET || op_type == MULTI_GET) {
if (!result.IsSucc()) {
SDK_LOG_ERR("failed to get object, object_name: %s",
object_name.c_str());
PrintResult(result);
stat.UpdataStat(false, op_type);
} else {
stat.UpdataStat(true, op_type);
CHECK_COMMON_RESULT(result)
if (op_type == SIMPLE_GET) {
CHECK_COMMON_RESP(resp1)
CHECK_GET_RESP(resp1, op_type)
} else {
CHECK_COMMON_RESP(resp2)
CHECK_GET_RESP(resp2, op_type)
}
}
} else {
while (!done) {
SDK_LOG_INFO("wait for get completing, object_name: %s",
object_name.c_str());
std::unique_lock<std::mutex> lock(mutex);
cond.wait_until(lock, std::chrono::system_clock::now() +
std::chrono::seconds(1));
}
done = false;
}
}
// delete object
SDK_LOG_INFO("delete object, object_name: %s", object_name.c_str());
qcloud_cos::DeleteObjectReq del_req(bucket_name, object_name);
qcloud_cos::DeleteObjectResp del_resp;
result = cos.DeleteObject(del_req, &del_resp);
if (!result.IsSucc()) {
SDK_LOG_ERR("failed to delete object, object_name: %s",
object_name.c_str());
PrintResult(result);
stat.delete_object_fail++;
} else {
stat.delete_object_succ++;
CHECK_COMMON_RESULT(result)
CHECK_COMMON_RESP(del_resp)
}
// delete local file
TestUtils::RemoveFile(local_file);
TestUtils::RemoveFile(local_file_download);
}
stat.PrintStat();
}
#if defined(_WIN32)
system("pause");
#endif
return 0;
}