tests.cc 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732
  1. // MinIO C++ Library for Amazon S3 Compatible Cloud Storage
  2. // Copyright 2022 MinIO, Inc.
  3. //
  4. // Licensed under the Apache License, Version 2.0 (the "License");
  5. // you may not use this file except in compliance with the License.
  6. // You may obtain a copy of the License at
  7. //
  8. // http://www.apache.org/licenses/LICENSE-2.0
  9. //
  10. // Unless required by applicable law or agreed to in writing, software
  11. // distributed under the License is distributed on an "AS IS" BASIS,
  12. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. // See the License for the specific language governing permissions and
  14. // limitations under the License.
  15. #include <unistd.h>
  16. #include <random>
  17. #include <thread>
  18. #include "client.h"
  19. thread_local static std::mt19937 rg{std::random_device{}()};
  20. const static std::string charset =
  21. "0123456789"
  22. "abcdefghijklmnopqrstuvwxyz"
  23. "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
  24. thread_local static std::uniform_int_distribution<std::string::size_type> pick(
  25. 0, charset.length() - 2);
  26. class RandomBuf : public std::streambuf {
  27. private:
  28. size_t size_;
  29. std::array<char, 64> buf_;
  30. protected:
  31. int_type underflow() override {
  32. if (size_ == 0) return EOF;
  33. size_t size = std::min(size_, buf_.size());
  34. setg(&buf_[0], &buf_[0], &buf_[size]);
  35. for (size_t i = 0; i < size; ++i) buf_[i] = charset[pick(rg)];
  36. size_ -= size;
  37. return 0;
  38. }
  39. public:
  40. RandomBuf(size_t size) : size_(size) {}
  41. };
  42. class RandCharStream : private RandomBuf, public std::istream {
  43. public:
  44. explicit RandCharStream(size_t size);
  45. };
  46. RandCharStream::RandCharStream(size_t size)
  47. : RandomBuf(size), std::istream(this) {}
  48. std::string RandomString(std::string chrs, std::string::size_type length) {
  49. thread_local static std::uniform_int_distribution<std::string::size_type>
  50. pick(0, chrs.length() - 2);
  51. std::string s;
  52. s.reserve(length);
  53. while (length--) s += chrs[pick(rg)];
  54. return s;
  55. }
  56. std::string RandBucketName() {
  57. return RandomString("0123456789abcdefghijklmnopqrstuvwxyz", 8);
  58. }
  59. std::string RandObjectName() { return RandomString(charset, 8); }
  60. struct MakeBucketError : public std::runtime_error {
  61. MakeBucketError(std::string err) : runtime_error(err) {}
  62. };
  63. struct RemoveBucketError : public std::runtime_error {
  64. RemoveBucketError(std::string err) : runtime_error(err) {}
  65. };
  66. struct BucketExistsError : public std::runtime_error {
  67. BucketExistsError(std::string err) : runtime_error(err) {}
  68. };
  69. class Tests {
  70. private:
  71. minio::s3::Client& client_;
  72. std::string bucket_name_;
  73. public:
  74. Tests(minio::s3::Client& client) : client_(client) {
  75. bucket_name_ = RandBucketName();
  76. minio::s3::MakeBucketArgs args;
  77. args.bucket = bucket_name_;
  78. minio::s3::MakeBucketResponse resp = client_.MakeBucket(args);
  79. if (!resp) {
  80. throw std::runtime_error("MakeBucket(): " + resp.Error().String());
  81. }
  82. }
  83. ~Tests() noexcept(false) {
  84. minio::s3::RemoveBucketArgs args;
  85. args.bucket = bucket_name_;
  86. minio::s3::RemoveBucketResponse resp = client_.RemoveBucket(args);
  87. if (!resp) {
  88. throw std::runtime_error("RemoveBucket(): " + resp.Error().String());
  89. }
  90. }
  91. void MakeBucket(std::string bucket_name) noexcept(false) {
  92. minio::s3::MakeBucketArgs args;
  93. args.bucket = bucket_name;
  94. minio::s3::MakeBucketResponse resp = client_.MakeBucket(args);
  95. if (resp) return;
  96. throw MakeBucketError("MakeBucket(): " + resp.Error().String());
  97. }
  98. void RemoveBucket(std::string bucket_name) noexcept(false) {
  99. minio::s3::RemoveBucketArgs args;
  100. args.bucket = bucket_name;
  101. minio::s3::RemoveBucketResponse resp = client_.RemoveBucket(args);
  102. if (resp) return;
  103. throw RemoveBucketError("RemoveBucket(): " + resp.Error().String());
  104. }
  105. void RemoveObject(std::string bucket_name, std::string object_name) {
  106. minio::s3::RemoveObjectArgs args;
  107. args.bucket = bucket_name;
  108. args.object = object_name;
  109. minio::s3::RemoveObjectResponse resp = client_.RemoveObject(args);
  110. if (!resp) {
  111. throw std::runtime_error("RemoveObject(): " + resp.Error().String());
  112. }
  113. }
  114. void RemoveObjects(std::list<std::string> objects) {
  115. minio::s3::RemoveObjectsArgs args;
  116. args.bucket = bucket_name_;
  117. std::list<minio::s3::DeleteObject> delete_objects;
  118. for (auto& object : objects) {
  119. delete_objects.push_back(minio::s3::DeleteObject{object});
  120. }
  121. std::list<minio::s3::DeleteObject>::iterator i = delete_objects.begin();
  122. args.func = [&delete_objects = delete_objects,
  123. &i = i](minio::s3::DeleteObject& object) -> bool {
  124. if (i == delete_objects.end()) return false;
  125. object = *i;
  126. i++;
  127. return true;
  128. };
  129. minio::s3::RemoveObjectsResult result = client_.RemoveObjects(args);
  130. std::string msg;
  131. for (; result; result++) {
  132. minio::s3::DeleteError err = *result;
  133. if (!err) {
  134. throw std::runtime_error("RemoveObjects(): " + err.Error().String());
  135. }
  136. if (msg.empty()) msg = "unable to remove object(s)";
  137. msg += "; " + err.object_name;
  138. if (!err.version_id.empty()) msg += "?versionId=" + err.version_id;
  139. }
  140. if (!msg.empty()) throw std::runtime_error("RemoveObjects(): " + msg);
  141. }
  142. void MakeBucket() {
  143. std::cout << "MakeBucket()" << std::endl;
  144. std::string bucket_name = RandBucketName();
  145. MakeBucket(bucket_name);
  146. RemoveBucket(bucket_name);
  147. }
  148. void RemoveBucket() {
  149. std::cout << "RemoveBucket()" << std::endl;
  150. std::string bucket_name = RandBucketName();
  151. MakeBucket(bucket_name);
  152. RemoveBucket(bucket_name);
  153. }
  154. void BucketExists() {
  155. std::cout << "BucketExists()" << std::endl;
  156. std::string bucket_name = RandBucketName();
  157. try {
  158. MakeBucket(bucket_name);
  159. minio::s3::BucketExistsArgs args;
  160. args.bucket = bucket_name;
  161. minio::s3::BucketExistsResponse resp = client_.BucketExists(args);
  162. if (!resp) {
  163. throw BucketExistsError("BucketExists(): " + resp.Error().String());
  164. }
  165. if (!resp.exist) {
  166. throw std::runtime_error("BucketExists(): expected: true; got: false");
  167. }
  168. RemoveBucket(bucket_name);
  169. } catch (const MakeBucketError& err) {
  170. throw err;
  171. } catch (const std::runtime_error& err) {
  172. RemoveBucket(bucket_name);
  173. throw err;
  174. }
  175. }
  176. void ListBuckets() {
  177. std::cout << "ListBuckets()" << std::endl;
  178. std::list<std::string> bucket_names;
  179. try {
  180. for (int i = 0; i < 3; i++) {
  181. std::string bucket_name = RandBucketName();
  182. MakeBucket(bucket_name);
  183. bucket_names.push_back(bucket_name);
  184. }
  185. minio::s3::ListBucketsResponse resp = client_.ListBuckets();
  186. if (!resp) {
  187. throw std::runtime_error("ListBuckets(): " + resp.Error().String());
  188. }
  189. int c = 0;
  190. for (auto& bucket : resp.buckets) {
  191. if (std::find(bucket_names.begin(), bucket_names.end(), bucket.name) !=
  192. bucket_names.end()) {
  193. c++;
  194. }
  195. }
  196. if (c != bucket_names.size()) {
  197. throw std::runtime_error(
  198. "ListBuckets(): expected: " + std::to_string(bucket_names.size()) +
  199. "; got: " + std::to_string(c));
  200. }
  201. for (auto& bucket_name : bucket_names) RemoveBucket(bucket_name);
  202. } catch (const std::runtime_error& err) {
  203. for (auto& bucket_name : bucket_names) RemoveBucket(bucket_name);
  204. throw err;
  205. }
  206. }
  207. void StatObject() {
  208. std::cout << "StatObject()" << std::endl;
  209. std::string object_name = RandObjectName();
  210. std::string data = "StatObject()";
  211. std::stringstream ss(data);
  212. minio::s3::PutObjectArgs args(ss, data.length(), 0);
  213. args.bucket = bucket_name_;
  214. args.object = object_name;
  215. minio::s3::PutObjectResponse resp = client_.PutObject(args);
  216. if (!resp) {
  217. throw std::runtime_error("PutObject(): " + resp.Error().String());
  218. }
  219. try {
  220. minio::s3::StatObjectArgs args;
  221. args.bucket = bucket_name_;
  222. args.object = object_name;
  223. minio::s3::StatObjectResponse resp = client_.StatObject(args);
  224. if (!resp) {
  225. throw std::runtime_error("StatObject(): " + resp.Error().String());
  226. }
  227. if (resp.size != data.length()) {
  228. throw std::runtime_error(
  229. "StatObject(): expected: " + std::to_string(data.length()) +
  230. "; got: " + std::to_string(resp.size));
  231. }
  232. RemoveObject(bucket_name_, object_name);
  233. } catch (const std::runtime_error& err) {
  234. RemoveObject(bucket_name_, object_name);
  235. throw err;
  236. }
  237. }
  238. void RemoveObject() {
  239. std::cout << "RemoveObject()" << std::endl;
  240. std::string object_name = RandObjectName();
  241. std::string data = "RemoveObject()";
  242. std::stringstream ss(data);
  243. minio::s3::PutObjectArgs args(ss, data.length(), 0);
  244. args.bucket = bucket_name_;
  245. args.object = object_name;
  246. minio::s3::PutObjectResponse resp = client_.PutObject(args);
  247. if (!resp) {
  248. throw std::runtime_error("PutObject(): " + resp.Error().String());
  249. }
  250. RemoveObject(bucket_name_, object_name);
  251. }
  252. void DownloadObject() {
  253. std::cout << "DownloadObject()" << std::endl;
  254. std::string object_name = RandObjectName();
  255. std::string data = "DownloadObject()";
  256. std::stringstream ss(data);
  257. minio::s3::PutObjectArgs args(ss, data.length(), 0);
  258. args.bucket = bucket_name_;
  259. args.object = object_name;
  260. minio::s3::PutObjectResponse resp = client_.PutObject(args);
  261. if (!resp) {
  262. throw std::runtime_error("PutObject(): " + resp.Error().String());
  263. }
  264. try {
  265. std::string filename = RandObjectName();
  266. minio::s3::DownloadObjectArgs args;
  267. args.bucket = bucket_name_;
  268. args.object = object_name;
  269. args.filename = filename;
  270. minio::s3::DownloadObjectResponse resp = client_.DownloadObject(args);
  271. if (!resp) {
  272. throw std::runtime_error("DownloadObject(): " + resp.Error().String());
  273. }
  274. std::ifstream file(filename);
  275. file.seekg(0, std::ios::end);
  276. size_t length = file.tellg();
  277. file.seekg(0, std::ios::beg);
  278. char* buf = new char[length];
  279. file.read(buf, length);
  280. file.close();
  281. if (data != std::string(buf, length)) {
  282. throw std::runtime_error("DownloadObject(): expected: " + data +
  283. "; got: " + buf);
  284. }
  285. std::filesystem::remove(filename);
  286. RemoveObject(bucket_name_, object_name);
  287. } catch (const std::runtime_error& err) {
  288. RemoveObject(bucket_name_, object_name);
  289. throw err;
  290. }
  291. }
  292. void GetObject() {
  293. std::cout << "GetObject()" << std::endl;
  294. std::string object_name = RandObjectName();
  295. std::string data = "GetObject()";
  296. std::stringstream ss(data);
  297. minio::s3::PutObjectArgs args(ss, data.length(), 0);
  298. args.bucket = bucket_name_;
  299. args.object = object_name;
  300. minio::s3::PutObjectResponse resp = client_.PutObject(args);
  301. if (!resp) {
  302. throw std::runtime_error("PutObject(): " + resp.Error().String());
  303. }
  304. try {
  305. minio::s3::GetObjectArgs args;
  306. args.bucket = bucket_name_;
  307. args.object = object_name;
  308. std::string content;
  309. args.datafunc =
  310. [&content = content](minio::http::DataFunctionArgs args) -> bool {
  311. content += args.datachunk;
  312. return true;
  313. };
  314. minio::s3::GetObjectResponse resp = client_.GetObject(args);
  315. if (!resp) {
  316. throw std::runtime_error("GetObject(): " + resp.Error().String());
  317. }
  318. if (data != content) {
  319. throw std::runtime_error("GetObject(): expected: " + data +
  320. "; got: " + content);
  321. }
  322. RemoveObject(bucket_name_, object_name);
  323. } catch (const std::runtime_error& err) {
  324. RemoveObject(bucket_name_, object_name);
  325. throw err;
  326. }
  327. }
  328. void listObjects(std::string testname, int count) {
  329. std::cout << testname << std::endl;
  330. std::list<std::string> object_names;
  331. try {
  332. for (int i = 0; i < count; i++) {
  333. std::string object_name = RandObjectName();
  334. std::stringstream ss;
  335. minio::s3::PutObjectArgs args(ss, 0, 0);
  336. args.bucket = bucket_name_;
  337. args.object = object_name;
  338. minio::s3::PutObjectResponse resp = client_.PutObject(args);
  339. if (!resp) {
  340. throw std::runtime_error("PutObject(): " + resp.Error().String());
  341. }
  342. object_names.push_back(object_name);
  343. }
  344. int c = 0;
  345. minio::s3::ListObjectsArgs args;
  346. args.bucket = bucket_name_;
  347. minio::s3::ListObjectsResult result = client_.ListObjects(args);
  348. for (; result; result++) {
  349. minio::s3::Item item = *result;
  350. if (!item) {
  351. throw std::runtime_error("ListObjects(): " + item.Error().String());
  352. }
  353. if (std::find(object_names.begin(), object_names.end(), item.name) !=
  354. object_names.end()) {
  355. c++;
  356. }
  357. }
  358. if (c != object_names.size()) {
  359. throw std::runtime_error(
  360. "ListObjects(): expected: " + std::to_string(object_names.size()) +
  361. "; got: " + std::to_string(c));
  362. }
  363. RemoveObjects(object_names);
  364. } catch (const std::runtime_error& err) {
  365. RemoveObjects(object_names);
  366. throw err;
  367. }
  368. }
  369. void ListObjects() { listObjects("ListObjects()", 3); }
  370. void ListObjects1010() { listObjects("ListObjects() 1010 objects", 1010); }
  371. void PutObject() {
  372. std::cout << "PutObject()" << std::endl;
  373. {
  374. std::string object_name = RandObjectName();
  375. std::string data = "PutObject()";
  376. std::stringstream ss(data);
  377. minio::s3::PutObjectArgs args(ss, data.length(), 0);
  378. args.bucket = bucket_name_;
  379. args.object = object_name;
  380. minio::s3::PutObjectResponse resp = client_.PutObject(args);
  381. if (!resp) {
  382. throw std::runtime_error("PutObject(): " + resp.Error().String());
  383. }
  384. RemoveObject(bucket_name_, object_name);
  385. }
  386. {
  387. std::string object_name = RandObjectName();
  388. size_t size = 13930573;
  389. RandCharStream stream(size);
  390. minio::s3::PutObjectArgs args(stream, size, 0);
  391. args.bucket = bucket_name_;
  392. args.object = object_name;
  393. minio::s3::PutObjectResponse resp = client_.PutObject(args);
  394. if (!resp) {
  395. throw std::runtime_error("<Multipart> PutObject(): " +
  396. resp.Error().String());
  397. }
  398. RemoveObject(bucket_name_, object_name);
  399. }
  400. }
  401. void CopyObject() {
  402. std::cout << "CopyObject()" << std::endl;
  403. std::string object_name = RandObjectName();
  404. std::string src_object_name = RandObjectName();
  405. std::string data = "CopyObject()";
  406. std::stringstream ss(data);
  407. minio::s3::PutObjectArgs args(ss, data.length(), 0);
  408. args.bucket = bucket_name_;
  409. args.object = src_object_name;
  410. minio::s3::PutObjectResponse resp = client_.PutObject(args);
  411. if (!resp) {
  412. throw std::runtime_error("PutObject(): " + resp.Error().String());
  413. }
  414. try {
  415. minio::s3::CopySource source;
  416. source.bucket = bucket_name_;
  417. source.object = src_object_name;
  418. minio::s3::CopyObjectArgs args;
  419. args.bucket = bucket_name_;
  420. args.object = object_name;
  421. args.source = source;
  422. minio::s3::CopyObjectResponse resp = client_.CopyObject(args);
  423. if (!resp) {
  424. throw std::runtime_error("CopyObject(): " + resp.Error().String());
  425. }
  426. RemoveObject(bucket_name_, src_object_name);
  427. RemoveObject(bucket_name_, object_name);
  428. } catch (const std::runtime_error& err) {
  429. RemoveObject(bucket_name_, src_object_name);
  430. RemoveObject(bucket_name_, object_name);
  431. throw err;
  432. }
  433. }
  434. void UploadObject() {
  435. std::cout << "UploadObject()" << std::endl;
  436. std::string data = "UploadObject()";
  437. std::string filename = RandObjectName();
  438. std::ofstream file(filename);
  439. file << data;
  440. file.close();
  441. std::string object_name = RandObjectName();
  442. minio::s3::UploadObjectArgs args;
  443. args.bucket = bucket_name_;
  444. args.object = object_name;
  445. args.filename = filename;
  446. minio::s3::UploadObjectResponse resp = client_.UploadObject(args);
  447. if (!resp) {
  448. throw std::runtime_error("UploadObject(): " + resp.Error().String());
  449. }
  450. std::filesystem::remove(filename);
  451. RemoveObject(bucket_name_, object_name);
  452. }
  453. void RemoveObjects() {
  454. std::cout << "RemoveObjects()" << std::endl;
  455. std::list<std::string> object_names;
  456. try {
  457. for (int i = 0; i < 3; i++) {
  458. std::string object_name = RandObjectName();
  459. std::stringstream ss;
  460. minio::s3::PutObjectArgs args(ss, 0, 0);
  461. args.bucket = bucket_name_;
  462. args.object = object_name;
  463. minio::s3::PutObjectResponse resp = client_.PutObject(args);
  464. if (!resp) std::runtime_error("PutObject(): " + resp.Error().String());
  465. object_names.push_back(object_name);
  466. }
  467. RemoveObjects(object_names);
  468. } catch (const std::runtime_error& err) {
  469. RemoveObjects(object_names);
  470. throw err;
  471. }
  472. }
  473. void SelectObjectContent() {
  474. std::cout << "SelectObjectContent()" << std::endl;
  475. std::string object_name = RandObjectName();
  476. std::string data =
  477. "1997,Ford,E350,\"ac, abs, moon\",3000.00\n"
  478. "1999,Chevy,\"Venture \"\"Extended Edition\"\"\",,4900.00\n"
  479. "1999,Chevy,\"Venture \"\"Extended Edition, Very Large\"\"\",,5000.00\n"
  480. "1996,Jeep,Grand Cherokee,\"MUST SELL!\n"
  481. "air, moon roof, loaded\",4799.00\n";
  482. std::stringstream ss("Year,Make,Model,Description,Price\n" + data);
  483. minio::s3::PutObjectArgs args(ss, ss.str().length(), 0);
  484. args.bucket = bucket_name_;
  485. args.object = object_name;
  486. minio::s3::PutObjectResponse resp = client_.PutObject(args);
  487. if (!resp) {
  488. throw std::runtime_error("PutObject(): " + resp.Error().String());
  489. }
  490. std::string expression = "select * from S3Object";
  491. minio::s3::CsvInputSerialization csv_input;
  492. minio::s3::FileHeaderInfo file_header_info =
  493. minio::s3::FileHeaderInfo::kUse;
  494. csv_input.file_header_info = &file_header_info;
  495. minio::s3::CsvOutputSerialization csv_output;
  496. minio::s3::QuoteFields quote_fields = minio::s3::QuoteFields::kAsNeeded;
  497. csv_output.quote_fields = &quote_fields;
  498. minio::s3::SelectRequest request(expression, &csv_input, &csv_output);
  499. try {
  500. std::string records;
  501. auto func = [&records = records](minio::s3::SelectResult result) -> bool {
  502. if (result.err) {
  503. throw std::runtime_error("SelectResult: " + result.err.String());
  504. return false;
  505. }
  506. records += result.records;
  507. return true;
  508. };
  509. minio::s3::SelectObjectContentArgs args(request, func);
  510. args.bucket = bucket_name_;
  511. args.object = object_name;
  512. minio::s3::SelectObjectContentResponse resp =
  513. client_.SelectObjectContent(args);
  514. if (!resp) {
  515. throw std::runtime_error("SelectObjectContent(): " +
  516. resp.Error().String());
  517. }
  518. if (records != data) {
  519. throw std::runtime_error("expected: " + data + ", got: " + records);
  520. }
  521. RemoveObject(bucket_name_, object_name);
  522. } catch (const std::runtime_error& err) {
  523. RemoveObject(bucket_name_, object_name);
  524. throw err;
  525. }
  526. }
  527. void ListenBucketNotification() {
  528. std::cout << "ListenBucketNotification()" << std::endl;
  529. std::list<minio::s3::NotificationRecord> records;
  530. std::thread task{[&client_ = client_, &bucket_name_ = bucket_name_,
  531. &records = records]() {
  532. minio::s3::ListenBucketNotificationArgs args;
  533. args.bucket = bucket_name_;
  534. args.func = [&records = records](
  535. std::list<minio::s3::NotificationRecord> values) -> bool {
  536. records.insert(records.end(), values.begin(), values.end());
  537. return false;
  538. };
  539. minio::s3::ListenBucketNotificationResponse resp =
  540. client_.ListenBucketNotification(args);
  541. if (!resp) {
  542. throw std::runtime_error("ListenBucketNotification(): " +
  543. resp.Error().String());
  544. }
  545. }};
  546. usleep(10 * 1000); // sleep for 10ms.
  547. std::string object_name = RandObjectName();
  548. try {
  549. std::string data = "ListenBucketNotification()";
  550. std::stringstream ss(data);
  551. minio::s3::PutObjectArgs args(ss, data.length(), 0);
  552. args.bucket = bucket_name_;
  553. args.object = object_name;
  554. minio::s3::PutObjectResponse resp = client_.PutObject(args);
  555. if (!resp) {
  556. throw std::runtime_error("PutObject(): " + resp.Error().String());
  557. }
  558. task.join();
  559. if (records.empty()) {
  560. throw std::runtime_error(
  561. "ListenBucketNotification(): records length: expected: 1, got: 0");
  562. }
  563. minio::s3::NotificationRecord record = records.front();
  564. if (record.event_name != "s3:ObjectCreated:Put") {
  565. throw std::runtime_error(
  566. "ListenBucketNotification(): record.event_name: expected: "
  567. "s3:ObjectCreated:Put, got: " +
  568. record.event_name);
  569. }
  570. if (record.s3.bucket.name != bucket_name_) {
  571. throw std::runtime_error(
  572. "ListenBucketNotification(): record.s3.bucket.name: expected: " +
  573. bucket_name_ + ", got: " + record.s3.bucket.name);
  574. }
  575. if (record.s3.object.key != object_name) {
  576. throw std::runtime_error(
  577. "ListenBucketNotification(): record.s3.object.name: expected: " +
  578. object_name + ", got: " + record.s3.object.key);
  579. }
  580. RemoveObject(bucket_name_, object_name);
  581. } catch (const std::runtime_error& err) {
  582. RemoveObject(bucket_name_, object_name);
  583. throw err;
  584. }
  585. }
  586. }; // class Tests
  587. int main(int argc, char* argv[]) {
  588. std::string host;
  589. if (!minio::utils::GetEnv(host, "SERVER_ENDPOINT")) {
  590. std::cerr << "SERVER_ENDPOINT environment variable must be set"
  591. << std::endl;
  592. return EXIT_FAILURE;
  593. }
  594. std::string access_key;
  595. if (!minio::utils::GetEnv(access_key, "ACCESS_KEY")) {
  596. std::cerr << "ACCESS_KEY environment variable must be set" << std::endl;
  597. return EXIT_FAILURE;
  598. }
  599. std::string secret_key;
  600. if (!minio::utils::GetEnv(secret_key, "SECRET_KEY")) {
  601. std::cerr << "SECRET_KEY environment variable must be set" << std::endl;
  602. return EXIT_FAILURE;
  603. }
  604. std::string value;
  605. bool secure = false;
  606. if (minio::utils::GetEnv(value, "ENABLE_HTTPS")) secure = true;
  607. bool ignore_cert_check = false;
  608. if (minio::utils::GetEnv(value, "IGNORE_CERT_CHECK")) {
  609. ignore_cert_check = true;
  610. }
  611. std::string region;
  612. minio::utils::GetEnv(region, "SERVER_REGION");
  613. minio::s3::BaseUrl base_url(host, secure);
  614. minio::creds::StaticProvider provider(access_key, secret_key);
  615. minio::s3::Client client(base_url, &provider);
  616. if (secure) client.IgnoreCertCheck(ignore_cert_check);
  617. Tests tests(client);
  618. tests.MakeBucket();
  619. tests.RemoveBucket();
  620. tests.BucketExists();
  621. tests.ListBuckets();
  622. tests.StatObject();
  623. tests.RemoveObject();
  624. tests.DownloadObject();
  625. tests.GetObject();
  626. tests.ListObjects();
  627. tests.ListObjects1010();
  628. tests.PutObject();
  629. tests.CopyObject();
  630. tests.UploadObject();
  631. tests.RemoveObjects();
  632. tests.SelectObjectContent();
  633. tests.ListenBucketNotification();
  634. return EXIT_SUCCESS;
  635. }