3#include <unordered_set>
7#include <userver/http/common_headers.hpp>
8#include <userver/http/url.hpp>
9#include <userver/utest/utest.hpp>
10#include <userver/utils/algo.hpp>
11#include <userver/utils/text.hpp>
13USERVER_NAMESPACE_BEGIN
15namespace s3api::api_methods {
17TEST(S3ApiMethods, CopyObject) {
18 const std::string source_bucket =
"source_bucket";
19 const std::string source_key =
"source_key";
20 const std::string dest_bucket =
"dest_bucket";
21 const std::string dest_key =
"dest_key";
22 const std::string content_type =
"application/json";
24 const Request request = CopyObject(source_bucket, source_key, dest_bucket, dest_key, content_type);
25 EXPECT_EQ(request.method, USERVER_NAMESPACE::clients::http::
HttpMethod::kPut);
26 EXPECT_EQ(request.req, dest_key);
27 EXPECT_EQ(request.bucket, dest_bucket);
28 EXPECT_TRUE(request.body.empty());
30 ASSERT_NE(copy_source,
nullptr);
31 EXPECT_EQ(*copy_source, fmt::format(
"/{}/{}", source_bucket, source_key));
34TEST(S3ApiMethods, GetObjectWithRange) {
35 const std::string bucket =
"bucket";
36 const std::string path =
"path";
37 const std::optional<std::string_view> version =
"version";
38 Request request = GetObject(bucket, path, version);
39 SetRange(request,
"Range: bytes=0-100");
40 const std::string expected_value =
"Range: bytes=0-100";
43 expected_value.c_str()
47TEST(S3ApiMethods, CreateMultipartUpload) {
48 const std::string content_type =
"application/octet-stream";
49 const std::string content_disposition =
"attachment; filename=some_file.bin";
52 request.key =
"some-key";
53 request.content_type =
"application/binary";
54 request.content_disposition =
"attachment; filename=\"some_file.bin\"";
55 request.content_encoding =
"gzip";
56 request.content_language =
"ru-RU";
58 const auto result = CreateInternalApiRequest(
"bucket", request);
60 EXPECT_EQ(result.bucket,
"bucket");
61 EXPECT_EQ(result.req,
"some-key?uploads");
62 EXPECT_EQ(result.method, clients::http::
HttpMethod::kPost);
63 EXPECT_TRUE(result.body.empty());
65 const auto expected_headers = clients
::http
::Headers{
66 {USERVER_NAMESPACE::
http::
headers::kContentType,
"application/binary"},
67 {USERVER_NAMESPACE::
http::
headers::kContentDisposition,
"attachment; filename=\"some_file.bin\""},
68 {USERVER_NAMESPACE::
http::
headers::kContentLanguage,
"ru-RU"},
69 {USERVER_NAMESPACE::
http::
headers::kContentEncoding,
"gzip"}};
70 EXPECT_EQ(expected_headers, result.headers);
74 request.key =
"some-key";
76 const auto result = CreateInternalApiRequest(
"bucket", request);
78 EXPECT_EQ(result.bucket,
"bucket");
79 EXPECT_EQ(result.req,
"some-key?uploads");
80 EXPECT_EQ(result.method, clients::http::
HttpMethod::kPost);
81 EXPECT_TRUE(result.body.empty());
82 EXPECT_EQ(clients
::http
::Headers
{}, result.headers);
86TEST(S3ApiMethods, UploadPart) {
88 request.key =
"some/key.bin";
89 request.upload_id =
"some_id";
90 request.part_number = 2;
91 request.data =
"some data";
93 const auto result = CreateInternalApiRequest(
"some-bucket", request);
94 EXPECT_EQ(result.bucket,
"some-bucket");
95 EXPECT_EQ(result.method, clients::http::
HttpMethod::kPut);
98 std::unordered_set<std::string_view>({
"partNumber=2",
"uploadId=some_id"}),
99 std::unordered_set<std::string_view>(requested_query_params.begin(), requested_query_params.end())
101 EXPECT_EQ(result.req.substr(0, result.req.find(
'?')),
"some/key.bin");
103 const auto expected_headers = clients
::http
::Headers{
104 {USERVER_NAMESPACE::
http::
headers::kContentType,
"application/octet-stream"},
105 {USERVER_NAMESPACE::
http::
headers::kContentLength, std::to_string(result.body.size())},
107 EXPECT_EQ(expected_headers, result.headers);
108 EXPECT_EQ(result.body, request.data);
111TEST(S3ApiMethods, AbortMultipartUpload) {
113 request.key =
"some/key.bin";
114 request.upload_id =
"some_id";
116 const auto result = CreateInternalApiRequest(
"some-bucket", request);
117 EXPECT_EQ(result.bucket,
"some-bucket");
118 EXPECT_EQ(result.method, clients::http::
HttpMethod::kDelete);
119 EXPECT_EQ(result.req,
"some/key.bin?uploadId=some_id");
122TEST(S3ApiMethods, CompleteMultipartUpload) {
124 request.key =
"some-key";
125 request.upload_id =
"some_id";
126 request.completed_parts = {{1,
"\"etag1\""}, {2,
"\"etag2\""}, {3,
"\"etag3\""}};
128 const auto result = CreateInternalApiRequest(
"some-bucket", request);
130 EXPECT_EQ(result.bucket,
"some-bucket");
131 EXPECT_EQ(result.method, clients::http::
HttpMethod::kPost);
132 EXPECT_EQ(result.req,
"some-key?uploadId=some_id");
134 const auto expected_headers = clients
::http
::Headers{
135 {USERVER_NAMESPACE::
http::
headers::kContentType,
"application/xml; charset=UTF-8"},
136 {USERVER_NAMESPACE::
http::
headers::kContentLength, std::to_string(result.body.size())},
138 EXPECT_EQ(expected_headers, result.headers);
141 "<?xml version=\"1.0\"?><CompleteMultipartUpload xmlns=\"http://s3.amazonaws.com/doc/2006-03-01/\">"
142 "<Part><PartNumber>1</PartNumber><ETag>\"etag1\"</ETag></Part>"
143 "<Part><PartNumber>2</PartNumber><ETag>\"etag2\"</ETag></Part>"
144 "<Part><PartNumber>3</PartNumber><ETag>\"etag3\"</ETag></Part>"
145 "</CompleteMultipartUpload>"
149TEST(S3ApiMethods, ListMultipartUploads) {
152 const auto result = CreateInternalApiRequest(
"some-bucket", request);
153 EXPECT_EQ(result.bucket,
"some-bucket");
154 EXPECT_EQ(result.method, clients::http::
HttpMethod::kGet);
155 EXPECT_EQ(result.req,
"?uploads");
156 EXPECT_EQ(result.headers, clients
::http
::Headers
{});
157 EXPECT_TRUE(result.body.empty());
161 request.prefix =
"some/prefix/to";
162 const auto result = CreateInternalApiRequest(
"some-bucket", request);
163 EXPECT_EQ(result.bucket,
"some-bucket");
164 EXPECT_EQ(result.method, clients::http::
HttpMethod::kGet);
165 EXPECT_EQ(result.headers, clients
::http
::Headers
{});
166 EXPECT_TRUE(result.body.empty());
170 std::unordered_set<std::string_view>({
"?uploads",
"prefix=some%2Fprefix%2Fto"}),
171 std::unordered_set<std::string_view>(requested_query_params.begin(), requested_query_params.end())
176 request.prefix =
"some/prefix/to";
177 request.max_uploads = 100;
178 request.delimiter =
"/";
179 request.key_marker =
"abc";
180 request.upload_id_marker =
"def";
182 const auto result = CreateInternalApiRequest(
"some-bucket", request);
183 EXPECT_EQ(result.bucket,
"some-bucket");
184 EXPECT_EQ(result.method, clients::http::
HttpMethod::kGet);
185 EXPECT_EQ(result.headers, clients
::http
::Headers
{});
186 EXPECT_TRUE(result.body.empty());
190 std::unordered_set<std::string_view>(
192 "prefix=some%2Fprefix%2Fto",
196 "upload-id-marker=def"}
198 std::unordered_set<std::string_view>(requested_query_params.begin(), requested_query_params.end())
203TEST(S3ApiMethods, ListParts) {
206 request.key =
"some/path/to";
207 request.upload_id =
"some_id";
208 const auto result = CreateInternalApiRequest(
"some-bucket", request);
209 EXPECT_EQ(result.bucket,
"some-bucket");
210 EXPECT_EQ(result.method, clients::http::
HttpMethod::kGet);
211 EXPECT_EQ(result.req,
"some/path/to?uploadId=some_id");
212 EXPECT_EQ(result.headers, clients
::http
::Headers
{});
216 request.key =
"some/path/to";
217 request.upload_id =
"some_id";
218 request.max_parts = 10;
219 request.part_number_marker = 11;
221 const auto result = CreateInternalApiRequest(
"some-bucket", request);
222 EXPECT_EQ(result.bucket,
"some-bucket");
223 EXPECT_EQ(result.method, clients::http::
HttpMethod::kGet);
225 const auto requested_query_params =
228 std::unordered_set<std::string_view>({
"uploadId=some_id",
"max-parts=10",
"part-number-marker=11"}),
229 std::unordered_set<std::string_view>(requested_query_params.begin(), requested_query_params.end())
231 EXPECT_EQ(result.req.substr(0, result.req.find(
'?')),
"some/path/to");
233 EXPECT_EQ(result.headers, clients
::http
::Headers
{});