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());
29 const std::string* copy_source = USERVER_NAMESPACE
::utils
::FindOrNullptr(request.headers
, headers::kAmzCopySource
);
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"}
71 EXPECT_EQ(expected_headers, result.headers);
75 request.key =
"some-key";
77 const auto result = CreateInternalApiRequest(
"bucket", request);
79 EXPECT_EQ(result.bucket,
"bucket");
80 EXPECT_EQ(result.req,
"some-key?uploads");
81 EXPECT_EQ(result.method, clients::http::
HttpMethod::kPost);
82 EXPECT_TRUE(result.body.empty());
83 EXPECT_EQ(clients
::http
::Headers
{}, result.headers);
87TEST(S3ApiMethods, UploadPart) {
89 request.key =
"some/key.bin";
90 request.upload_id =
"some_id";
91 request.part_number = 2;
92 request.data =
"some data";
94 const auto result = CreateInternalApiRequest(
"some-bucket", request);
95 EXPECT_EQ(result.bucket,
"some-bucket");
96 EXPECT_EQ(result.method, clients::http::
HttpMethod::kPut);
99 std::unordered_set<std::string_view>({
"partNumber=2",
"uploadId=some_id"}),
100 std::unordered_set<std::string_view>(requested_query_params.begin(), requested_query_params.end())
102 EXPECT_EQ(result.req.substr(0, result.req.find(
'?')),
"some/key.bin");
104 const auto expected_headers = clients
::http
::Headers{
105 {USERVER_NAMESPACE::
http::
headers::kContentType,
"application/octet-stream"},
106 {USERVER_NAMESPACE::
http::
headers::kContentLength, std::to_string(result.body.size())},
108 EXPECT_EQ(expected_headers, result.headers);
109 EXPECT_EQ(result.body, request.data);
112TEST(S3ApiMethods, AbortMultipartUpload) {
114 request.key =
"some/key.bin";
115 request.upload_id =
"some_id";
117 const auto result = CreateInternalApiRequest(
"some-bucket", request);
118 EXPECT_EQ(result.bucket,
"some-bucket");
119 EXPECT_EQ(result.method, clients::http::
HttpMethod::kDelete);
120 EXPECT_EQ(result.req,
"some/key.bin?uploadId=some_id");
123TEST(S3ApiMethods, CompleteMultipartUpload) {
125 request.key =
"some-key";
126 request.upload_id =
"some_id";
127 request.completed_parts = {{1,
"\"etag1\""}, {2,
"\"etag2\""}, {3,
"\"etag3\""}};
129 const auto result = CreateInternalApiRequest(
"some-bucket", request);
131 EXPECT_EQ(result.bucket,
"some-bucket");
132 EXPECT_EQ(result.method, clients::http::
HttpMethod::kPost);
133 EXPECT_EQ(result.req,
"some-key?uploadId=some_id");
135 const auto expected_headers = clients
::http
::Headers{
136 {USERVER_NAMESPACE::
http::
headers::kContentType,
"application/xml; charset=UTF-8"},
137 {USERVER_NAMESPACE::
http::
headers::kContentLength, std::to_string(result.body.size())},
139 EXPECT_EQ(expected_headers, result.headers);
142 "<?xml version=\"1.0\"?><CompleteMultipartUpload xmlns=\"http://s3.amazonaws.com/doc/2006-03-01/\">"
143 "<Part><PartNumber>1</PartNumber><ETag>\"etag1\"</ETag></Part>"
144 "<Part><PartNumber>2</PartNumber><ETag>\"etag2\"</ETag></Part>"
145 "<Part><PartNumber>3</PartNumber><ETag>\"etag3\"</ETag></Part>"
146 "</CompleteMultipartUpload>"
150TEST(S3ApiMethods, ListMultipartUploads) {
153 const auto result = CreateInternalApiRequest(
"some-bucket", request);
154 EXPECT_EQ(result.bucket,
"some-bucket");
155 EXPECT_EQ(result.method, clients::http::
HttpMethod::kGet);
156 EXPECT_EQ(result.req,
"?uploads");
157 EXPECT_EQ(result.headers, clients
::http
::Headers
{});
158 EXPECT_TRUE(result.body.empty());
162 request.prefix =
"some/prefix/to";
163 const auto result = CreateInternalApiRequest(
"some-bucket", request);
164 EXPECT_EQ(result.bucket,
"some-bucket");
165 EXPECT_EQ(result.method, clients::http::
HttpMethod::kGet);
166 EXPECT_EQ(result.headers, clients
::http
::Headers
{});
167 EXPECT_TRUE(result.body.empty());
171 std::unordered_set<std::string_view>({
"?uploads",
"prefix=some%2Fprefix%2Fto"}),
172 std::unordered_set<std::string_view>(requested_query_params.begin(), requested_query_params.end())
177 request.prefix =
"some/prefix/to";
178 request.max_uploads = 100;
179 request.delimiter =
"/";
180 request.key_marker =
"abc";
181 request.upload_id_marker =
"def";
183 const auto result = CreateInternalApiRequest(
"some-bucket", request);
184 EXPECT_EQ(result.bucket,
"some-bucket");
185 EXPECT_EQ(result.method, clients::http::
HttpMethod::kGet);
186 EXPECT_EQ(result.headers, clients
::http
::Headers
{});
187 EXPECT_TRUE(result.body.empty());
191 std::unordered_set<std::string_view>(
193 "prefix=some%2Fprefix%2Fto",
197 "upload-id-marker=def"}
199 std::unordered_set<std::string_view>(requested_query_params.begin(), requested_query_params.end())
204TEST(S3ApiMethods, ListParts) {
207 request.key =
"some/path/to";
208 request.upload_id =
"some_id";
209 const auto result = CreateInternalApiRequest(
"some-bucket", request);
210 EXPECT_EQ(result.bucket,
"some-bucket");
211 EXPECT_EQ(result.method, clients::http::
HttpMethod::kGet);
212 EXPECT_EQ(result.req,
"some/path/to?uploadId=some_id");
213 EXPECT_EQ(result.headers, clients
::http
::Headers
{});
217 request.key =
"some/path/to";
218 request.upload_id =
"some_id";
219 request.max_parts = 10;
220 request.part_number_marker = 11;
222 const auto result = CreateInternalApiRequest(
"some-bucket", request);
223 EXPECT_EQ(result.bucket,
"some-bucket");
224 EXPECT_EQ(result.method, clients::http::
HttpMethod::kGet);
229 std::unordered_set<std::string_view>({
"uploadId=some_id",
"max-parts=10",
"part-number-marker=11"}),
230 std::unordered_set<std::string_view>(requested_query_params.begin(), requested_query_params.end())
232 EXPECT_EQ(result.req.substr(0, result.req.find(
'?')),
"some/path/to");
234 EXPECT_EQ(result.headers, clients
::http
::Headers
{});