stable_test.cpp 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394
  1. // Copyright (c) 2022, Tencent Inc.
  2. // All rights reserved.
  3. #include <stdlib.h>
  4. #include <sys/stat.h>
  5. #include <iostream>
  6. #include <map>
  7. #include <string>
  8. #include <thread>
  9. #include <vector>
  10. #include "cos_api.h"
  11. #include "cos_sys_config.h"
  12. #include "util/auth_tool.h"
  13. #include "util/test_utils.h"
  14. using namespace qcloud_cos;
  15. static void PrintResult(const qcloud_cos::CosResult& result) {
  16. std::stringstream oss;
  17. oss << "ErrorMsg=" << result.GetErrorMsg() << std::endl;
  18. oss << "HttpStatus=" << result.GetHttpStatus() << std::endl;
  19. oss << "ErrorCode=" << result.GetErrorCode() << std::endl;
  20. oss << "ErrorMsg=" << result.GetErrorMsg() << std::endl;
  21. oss << "ResourceAddr=" << result.GetResourceAddr() << std::endl;
  22. oss << "XCosRequestId=" << result.GetXCosRequestId() << std::endl;
  23. oss << "XCosTraceId=" << result.GetXCosTraceId() << std::endl;
  24. SDK_LOG_INFO("%s", oss.str().c_str());
  25. }
  26. enum PutOpType { SIMPLE_PUT = 1, MULTI_PUT, ASYNC_PUT, ASYNC_MULTI_PUT };
  27. enum GetOpType { SIMPLE_GET = 6, MULTI_GET, ASYNC_GET, ASYNC_MULTI_GET };
  28. #define GENERATE_LOCAL_FILE(size) \
  29. std::string object_name = "stable_test_size_" + std::to_string(size); \
  30. std::string local_file = "./" + object_name; \
  31. SDK_LOG_INFO("generate local file: %s", local_file.c_str()); \
  32. TestUtils::WriteRandomDatatoFile(local_file, file_size); \
  33. uint64_t file_crc64_origin = FileUtil::GetFileCrc64(local_file); \
  34. std::string file_md5_origin = FileUtil::GetFileMd5(local_file); \
  35. SDK_LOG_INFO("file_crc64_origin: %lu", file_crc64_origin); \
  36. SDK_LOG_INFO("file_md5_origin: %s", file_md5_origin.c_str());
  37. #define CHECK_COMMON_RESULT(result) \
  38. assert(result.IsSucc()); \
  39. assert(!result.GetXCosRequestId().empty()); \
  40. assert(result.GetHttpStatus() >= 200 && result.GetHttpStatus() < 300);
  41. #define CHECK_COMMON_RESP(resp) \
  42. assert(resp.GetServer() == "tencent-cos"); \
  43. assert(!resp.GetDate().empty()); \
  44. assert(!resp.GetConnection().empty()); \
  45. assert(!resp.GetXCosRequestId().empty());
  46. #define CHECK_PUT_RESP(resp, op_type) \
  47. assert(resp.GetXCosHashCrc64Ecma() == std::to_string(file_crc64_origin)); \
  48. if (op_type == MULTI_PUT || op_type == ASYNC_MULTI_PUT) { \
  49. assert(!resp.GetContentType().empty()); \
  50. assert(resp.GetEtag() != file_md5_origin); \
  51. } else { \
  52. assert(resp.GetEtag() == file_md5_origin); \
  53. }
  54. #define CHECK_HEAD_RESP(resp) \
  55. assert(resp.GetXCosHashCrc64Ecma() == std::to_string(file_crc64_origin)); \
  56. assert(resp.GetContentLength() == file_size); \
  57. assert(!resp.GetLastModified().empty());
  58. #define CHECK_GET_RESP(resp, op_type) \
  59. assert(resp.GetXCosHashCrc64Ecma() == std::to_string(file_crc64_origin)); \
  60. assert(!resp.GetLastModified().empty()); \
  61. std::string file_md5_download = TestUtils::CalcFileMd5(local_file_download); \
  62. assert(file_md5_download == file_md5_origin); \
  63. if (op_type == SIMPLE_GET || op_type == ASYNC_GET) { \
  64. assert(resp.GetContentLength() == file_size); \
  65. }
  66. class TestStatistics {
  67. public:
  68. TestStatistics()
  69. : put_object_succ(0),
  70. put_object_fail(0),
  71. multi_put_object_succ(0),
  72. multi_put_object_fail(0),
  73. async_put_object_succ(0),
  74. async_put_object_fail(0),
  75. async_multi_put_object_succ(0),
  76. async_multi_put_object_fail(0),
  77. get_object_succ(0),
  78. get_object_fail(0),
  79. multi_get_object_succ(0),
  80. multi_get_object_fail(0),
  81. async_get_object_succ(0),
  82. async_get_object_fail(0),
  83. async_multi_get_object_succ(0),
  84. async_multi_get_object_fail(0),
  85. head_object_succ(0),
  86. head_object_fail(0),
  87. delete_object_succ(0),
  88. delete_object_fail(0) {}
  89. int put_object_succ;
  90. int put_object_fail;
  91. int multi_put_object_succ;
  92. int multi_put_object_fail;
  93. int async_put_object_succ;
  94. int async_put_object_fail;
  95. int async_multi_put_object_succ;
  96. int async_multi_put_object_fail;
  97. int get_object_succ;
  98. int get_object_fail;
  99. int multi_get_object_succ;
  100. int multi_get_object_fail;
  101. int async_get_object_succ;
  102. int async_get_object_fail;
  103. int async_multi_get_object_succ;
  104. int async_multi_get_object_fail;
  105. int head_object_succ;
  106. int head_object_fail;
  107. int delete_object_succ;
  108. int delete_object_fail;
  109. void UpdataStat(bool succ, int op_type) {
  110. switch (op_type) {
  111. case SIMPLE_PUT:
  112. succ ? put_object_succ++ : put_object_fail++;
  113. case MULTI_PUT:
  114. succ ? multi_put_object_succ++ : multi_put_object_fail++;
  115. case ASYNC_PUT:
  116. succ ? async_put_object_succ++ : async_put_object_fail++;
  117. case ASYNC_MULTI_PUT:
  118. succ ? async_multi_put_object_succ++ : async_multi_put_object_fail++;
  119. case SIMPLE_GET:
  120. succ ? get_object_succ++ : get_object_fail++;
  121. case MULTI_GET:
  122. succ ? multi_get_object_succ++ : multi_get_object_fail++;
  123. case ASYNC_GET:
  124. succ ? async_get_object_succ++ : async_get_object_fail++;
  125. case ASYNC_MULTI_GET:
  126. succ ? async_multi_get_object_succ++ : async_multi_get_object_fail++;
  127. }
  128. }
  129. void PrintStat() {
  130. std::stringstream oss;
  131. oss << std::endl;
  132. oss << "put_object_succ:" << put_object_succ << std::endl;
  133. oss << "put_object_fail:" << put_object_fail << std::endl;
  134. oss << "multi_put_object_succ:" << put_object_succ << std::endl;
  135. oss << "multi_put_object_fail:" << put_object_fail << std::endl;
  136. oss << "async_put_object_succ:" << put_object_succ << std::endl;
  137. oss << "async_put_object_fail:" << put_object_fail << std::endl;
  138. oss << "async_multi_put_object_succ:" << put_object_succ << std::endl;
  139. oss << "async_multi_put_object_fail:" << put_object_fail << std::endl;
  140. oss << "get_object_succ:" << put_object_succ << std::endl;
  141. oss << "get_object_fail:" << put_object_fail << std::endl;
  142. oss << "multi_get_object_succ:" << put_object_succ << std::endl;
  143. oss << "multi_get_object_fail:" << put_object_fail << std::endl;
  144. oss << "async_get_object_succ:" << put_object_succ << std::endl;
  145. oss << "async_get_object_fail:" << put_object_fail << std::endl;
  146. oss << "async_multi_get_object_succ:" << put_object_succ << std::endl;
  147. oss << "async_multi_get_object_fail:" << put_object_fail << std::endl;
  148. oss << "head_object_succ:" << put_object_succ << std::endl;
  149. oss << "head_object_fail:" << put_object_fail << std::endl;
  150. oss << "delete_object_succ:" << put_object_succ << std::endl;
  151. oss << "delete_object_fail:" << put_object_fail << std::endl;
  152. SDK_LOG_INFO("%s", oss.str().c_str());
  153. }
  154. };
  155. void TestLogCallback(const std::string& log) {
  156. std::ofstream ofs;
  157. ofs.open("./stable_test.log", std::ios_base::app);
  158. ofs << log;
  159. ofs.close();
  160. }
  161. int main(int argc, char** argv) {
  162. UNUSED_PARAM(argc)
  163. UNUSED_PARAM(argv)
  164. qcloud_cos::CosConfig config("./config.json");
  165. config.SetLogCallback(&TestLogCallback);
  166. qcloud_cos::CosAPI cos(config);
  167. TestStatistics stat;
  168. std::string bucket_name = "test-12345678";
  169. size_t max_file_size = 100 * 1024 * 1024;
  170. while (true) {
  171. std::vector<int> put_op_type_v = {SIMPLE_PUT, MULTI_PUT, ASYNC_PUT,
  172. ASYNC_MULTI_PUT};
  173. for (auto& op_type : put_op_type_v) {
  174. size_t file_size = rand() % max_file_size;
  175. GENERATE_LOCAL_FILE(file_size)
  176. bool done = false;
  177. std::mutex mutex;
  178. std::condition_variable cond;
  179. auto put_done_cb = [file_crc64_origin, file_md5_origin, &done, &mutex,
  180. &cond, &stat](const SharedAsyncContext& context,
  181. void* user_data) {
  182. int op_type = (*reinterpret_cast<int*>(user_data));
  183. CHECK_COMMON_RESULT(context->GetResult())
  184. if (context->GetResult().IsSucc()) {
  185. stat.UpdataStat(true, op_type);
  186. } else {
  187. stat.UpdataStat(false, op_type);
  188. }
  189. AsyncResp resp = context->GetAsyncResp();
  190. CHECK_COMMON_RESP(resp)
  191. CHECK_PUT_RESP(resp, op_type)
  192. done = true;
  193. std::unique_lock<std::mutex> lock(mutex);
  194. cond.notify_one();
  195. };
  196. // put object
  197. CosResult result;
  198. PutObjectByFileResp resp1;
  199. MultiPutObjectResp resp2;
  200. if (op_type == SIMPLE_PUT) {
  201. SDK_LOG_INFO("put object, object_name: %s", object_name.c_str());
  202. PutObjectByFileReq req(bucket_name, object_name, local_file);
  203. result = cos.PutObject(req, &resp1);
  204. } else if (op_type == MULTI_PUT) {
  205. SDK_LOG_INFO("multi put object, object_name: %s", object_name.c_str());
  206. MultiPutObjectReq req(bucket_name, object_name, local_file);
  207. result = cos.MultiPutObject(req, &resp2);
  208. } else if (op_type == ASYNC_PUT) {
  209. SDK_LOG_INFO("async put object, object_name: %s", object_name.c_str());
  210. AsyncPutObjectReq req(bucket_name, object_name, local_file);
  211. req.SetDoneCallback(put_done_cb);
  212. req.SetUserData(reinterpret_cast<void*>(&op_type));
  213. MultiPutObjectResp resp;
  214. cos.AsyncPutObject(req);
  215. } else if (op_type == ASYNC_MULTI_PUT) {
  216. SDK_LOG_INFO("async multi put object, object_name: %s",
  217. object_name.c_str());
  218. AsyncMultiPutObjectReq req(bucket_name, object_name, local_file);
  219. req.SetUserData(reinterpret_cast<void*>(&op_type));
  220. req.SetDoneCallback(put_done_cb);
  221. cos.AsyncMultiPutObject(req);
  222. }
  223. if (op_type == SIMPLE_PUT || op_type == MULTI_PUT) {
  224. if (!result.IsSucc()) {
  225. SDK_LOG_ERR("failed to put object, object_name: %s",
  226. object_name.c_str());
  227. PrintResult(result);
  228. stat.UpdataStat(false, op_type);
  229. } else {
  230. stat.UpdataStat(true, op_type);
  231. CHECK_COMMON_RESULT(result)
  232. if (op_type == SIMPLE_PUT) {
  233. CHECK_COMMON_RESP(resp1)
  234. CHECK_PUT_RESP(resp1, op_type)
  235. } else {
  236. CHECK_COMMON_RESP(resp2)
  237. CHECK_PUT_RESP(resp2, op_type)
  238. }
  239. }
  240. } else {
  241. while (!done) {
  242. SDK_LOG_INFO("wait for put completing, object_name: %s",
  243. object_name.c_str());
  244. std::unique_lock<std::mutex> lock(mutex);
  245. cond.wait_until(
  246. lock, std::chrono::system_clock::now() + std::chrono::seconds(1));
  247. }
  248. }
  249. // head object
  250. HeadObjectReq head_req(bucket_name, object_name);
  251. HeadObjectResp headresp;
  252. SDK_LOG_INFO("head object, object_name: %s", object_name.c_str());
  253. result = cos.HeadObject(head_req, &headresp);
  254. if (!result.IsSucc()) {
  255. SDK_LOG_ERR("failed to head object, object_name: %s",
  256. object_name.c_str());
  257. PrintResult(result);
  258. stat.head_object_fail++;
  259. } else {
  260. stat.head_object_succ++;
  261. CHECK_COMMON_RESULT(result)
  262. CHECK_COMMON_RESP(headresp)
  263. CHECK_HEAD_RESP(headresp)
  264. }
  265. // get object
  266. // 使用多个接口下载同一个对象
  267. done = false;
  268. std::string local_file_download = local_file + "_download";
  269. auto get_done_cb = [file_size, local_file_download, file_crc64_origin,
  270. file_md5_origin, &done, &mutex, &cond,
  271. &stat](const SharedAsyncContext& context,
  272. void* user_data) {
  273. int op_type = (*reinterpret_cast<int*>(user_data));
  274. CHECK_COMMON_RESULT(context->GetResult())
  275. if (context->GetResult().IsSucc()) {
  276. stat.UpdataStat(true, op_type);
  277. } else {
  278. stat.UpdataStat(false, op_type);
  279. }
  280. AsyncResp resp = context->GetAsyncResp();
  281. CHECK_COMMON_RESP(resp)
  282. CHECK_GET_RESP(resp, op_type)
  283. done = true;
  284. std::unique_lock<std::mutex> lock(mutex);
  285. cond.notify_one();
  286. };
  287. std::vector<int> get_op_type_v = {SIMPLE_GET, MULTI_GET, ASYNC_GET,
  288. ASYNC_MULTI_GET};
  289. for (auto& op_type : get_op_type_v) {
  290. GetObjectByFileResp resp1;
  291. MultiGetObjectResp resp2;
  292. if (op_type == SIMPLE_GET) {
  293. SDK_LOG_INFO("get object, object_name: %s", object_name.c_str());
  294. GetObjectByFileReq req(bucket_name, object_name, local_file_download);
  295. result = cos.GetObject(req, &resp1);
  296. } else if (op_type == MULTI_GET) {
  297. SDK_LOG_INFO("multi get object, object_name: %s",
  298. object_name.c_str());
  299. MultiGetObjectReq req(bucket_name, object_name, local_file_download);
  300. result = cos.MultiGetObject(req, &resp2);
  301. } else if (op_type == ASYNC_GET) {
  302. SDK_LOG_INFO("async get object, object_name: %s",
  303. object_name.c_str());
  304. AsyncGetObjectReq req(bucket_name, object_name, local_file_download);
  305. req.SetDoneCallback(get_done_cb);
  306. req.SetUserData(reinterpret_cast<void*>(&op_type));
  307. cos.AsyncGetObject(req);
  308. } else if (op_type == ASYNC_MULTI_GET) {
  309. SDK_LOG_INFO("async multi get object, object_name: %s",
  310. object_name.c_str());
  311. AsyncMultiGetObjectReq req(bucket_name, object_name,
  312. local_file_download);
  313. req.SetUserData(reinterpret_cast<void*>(&op_type));
  314. req.SetDoneCallback(get_done_cb);
  315. cos.AsyncMultiGetObject(req);
  316. }
  317. if (op_type == SIMPLE_GET || op_type == MULTI_GET) {
  318. if (!result.IsSucc()) {
  319. SDK_LOG_ERR("failed to get object, object_name: %s",
  320. object_name.c_str());
  321. PrintResult(result);
  322. stat.UpdataStat(false, op_type);
  323. } else {
  324. stat.UpdataStat(true, op_type);
  325. CHECK_COMMON_RESULT(result)
  326. if (op_type == SIMPLE_GET) {
  327. CHECK_COMMON_RESP(resp1)
  328. CHECK_GET_RESP(resp1, op_type)
  329. } else {
  330. CHECK_COMMON_RESP(resp2)
  331. CHECK_GET_RESP(resp2, op_type)
  332. }
  333. }
  334. } else {
  335. while (!done) {
  336. SDK_LOG_INFO("wait for get completing, object_name: %s",
  337. object_name.c_str());
  338. std::unique_lock<std::mutex> lock(mutex);
  339. cond.wait_until(lock, std::chrono::system_clock::now() +
  340. std::chrono::seconds(1));
  341. }
  342. done = false;
  343. }
  344. }
  345. // delete object
  346. SDK_LOG_INFO("delete object, object_name: %s", object_name.c_str());
  347. qcloud_cos::DeleteObjectReq del_req(bucket_name, object_name);
  348. qcloud_cos::DeleteObjectResp del_resp;
  349. result = cos.DeleteObject(del_req, &del_resp);
  350. if (!result.IsSucc()) {
  351. SDK_LOG_ERR("failed to delete object, object_name: %s",
  352. object_name.c_str());
  353. PrintResult(result);
  354. stat.delete_object_fail++;
  355. } else {
  356. stat.delete_object_succ++;
  357. CHECK_COMMON_RESULT(result)
  358. CHECK_COMMON_RESP(del_resp)
  359. }
  360. // delete local file
  361. TestUtils::RemoveFile(local_file);
  362. TestUtils::RemoveFile(local_file_download);
  363. }
  364. stat.PrintStat();
  365. }
  366. #if defined(_WIN32)
  367. system("pause");
  368. #endif
  369. return 0;
  370. }