userver: /data/code/userver/libraries/s3api/src/s3api/s3api_methods_test.cpp Source File
Loading...
Searching...
No Matches
s3api_methods_test.cpp
2
3#include <unordered_set>
4
5#include <fmt/format.h>
6
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>
12
13USERVER_NAMESPACE_BEGIN
14
15namespace s3api::api_methods {
16
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";
23
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));
32}
33
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";
41 EXPECT_STREQ(
42 USERVER_NAMESPACE::utils::FindOrNullptr(request.headers, USERVER_NAMESPACE::http::headers::kRange)->c_str(),
43 expected_value.c_str()
44 );
45}
46
47TEST(S3ApiMethods, CreateMultipartUpload) {
48 const std::string content_type = "application/octet-stream";
49 const std::string content_disposition = "attachment; filename=some_file.bin";
50 {
51 multipart_upload::CreateMultipartUploadRequest request;
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";
57
58 const auto result = CreateInternalApiRequest("bucket", request);
59
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());
64
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);
71 }
72 {
73 multipart_upload::CreateMultipartUploadRequest request;
74 request.key = "some-key";
75
76 const auto result = CreateInternalApiRequest("bucket", request);
77
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);
83 }
84}
85
86TEST(S3ApiMethods, UploadPart) {
87 multipart_upload::UploadPartRequest request;
88 request.key = "some/key.bin";
89 request.upload_id = "some_id";
90 request.part_number = 2;
91 request.data = "some data";
92
93 const auto result = CreateInternalApiRequest("some-bucket", request);
94 EXPECT_EQ(result.bucket, "some-bucket");
95 EXPECT_EQ(result.method, clients::http::HttpMethod::kPut);
96 const auto requested_query_params = utils::text::SplitIntoStringViewVector(http::ExtractQueryView(result.req), "&");
97 EXPECT_EQ(
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())
100 );
101 EXPECT_EQ(result.req.substr(0, result.req.find('?')), "some/key.bin");
102
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())},
106 };
107 EXPECT_EQ(expected_headers, result.headers);
108 EXPECT_EQ(result.body, request.data);
109}
110
111TEST(S3ApiMethods, AbortMultipartUpload) {
112 multipart_upload::AbortMultipartUploadRequest request;
113 request.key = "some/key.bin";
114 request.upload_id = "some_id";
115
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");
120}
121
122TEST(S3ApiMethods, CompleteMultipartUpload) {
123 multipart_upload::CompleteMultipartUploadRequest request;
124 request.key = "some-key";
125 request.upload_id = "some_id";
126 request.completed_parts = {{1, "\"etag1\""}, {2, "\"etag2\""}, {3, "\"etag3\""}};
127
128 const auto result = CreateInternalApiRequest("some-bucket", request);
129
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");
133
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())},
137 };
138 EXPECT_EQ(expected_headers, result.headers);
139 EXPECT_EQ(
140 result.body,
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>"
146 );
147}
148
149TEST(S3ApiMethods, ListMultipartUploads) {
150 {
151 multipart_upload::ListMultipartUploadsRequest request;
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());
158 }
159 {
160 multipart_upload::ListMultipartUploadsRequest request;
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());
167
168 const auto requested_query_params = utils::text::SplitIntoStringViewVector(result.req, "&");
169 EXPECT_EQ(
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())
172 );
173 }
174 {
175 multipart_upload::ListMultipartUploadsRequest request;
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";
181
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());
187
188 const auto requested_query_params = utils::text::SplitIntoStringViewVector(result.req, "&");
189 EXPECT_EQ(
190 std::unordered_set<std::string_view>(
191 {"?uploads",
192 "prefix=some%2Fprefix%2Fto",
193 "max-uploads=100",
194 "marker=abc",
195 "delimiter=%2F",
196 "upload-id-marker=def"}
197 ),
198 std::unordered_set<std::string_view>(requested_query_params.begin(), requested_query_params.end())
199 );
200 }
201}
202
203TEST(S3ApiMethods, ListParts) {
204 {
205 multipart_upload::ListPartsRequest request;
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{});
213 }
214 {
215 multipart_upload::ListPartsRequest request;
216 request.key = "some/path/to";
217 request.upload_id = "some_id";
218 request.max_parts = 10;
219 request.part_number_marker = 11;
220
221 const auto result = CreateInternalApiRequest("some-bucket", request);
222 EXPECT_EQ(result.bucket, "some-bucket");
223 EXPECT_EQ(result.method, clients::http::HttpMethod::kGet);
224
225 const auto requested_query_params =
226 utils::text::SplitIntoStringViewVector(http::ExtractQueryView(result.req), "&");
227 EXPECT_EQ(
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())
230 );
231 EXPECT_EQ(result.req.substr(0, result.req.find('?')), "some/path/to");
232
233 EXPECT_EQ(result.headers, clients::http::Headers{});
234 }
235}
236
237} // namespace s3api::api_methods
238
239USERVER_NAMESPACE_END