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 };
71 EXPECT_EQ(expected_headers, result.headers);
72 }
73 {
74 multipart_upload::CreateMultipartUploadRequest request;
75 request.key = "some-key";
76
77 const auto result = CreateInternalApiRequest("bucket", request);
78
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);
84 }
85}
86
87TEST(S3ApiMethods, UploadPart) {
88 multipart_upload::UploadPartRequest request;
89 request.key = "some/key.bin";
90 request.upload_id = "some_id";
91 request.part_number = 2;
92 request.data = "some data";
93
94 const auto result = CreateInternalApiRequest("some-bucket", request);
95 EXPECT_EQ(result.bucket, "some-bucket");
96 EXPECT_EQ(result.method, clients::http::HttpMethod::kPut);
97 const auto requested_query_params = utils::text::SplitIntoStringViewVector(http::ExtractQueryView(result.req), "&");
98 EXPECT_EQ(
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())
101 );
102 EXPECT_EQ(result.req.substr(0, result.req.find('?')), "some/key.bin");
103
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())},
107 };
108 EXPECT_EQ(expected_headers, result.headers);
109 EXPECT_EQ(result.body, request.data);
110}
111
112TEST(S3ApiMethods, AbortMultipartUpload) {
113 multipart_upload::AbortMultipartUploadRequest request;
114 request.key = "some/key.bin";
115 request.upload_id = "some_id";
116
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");
121}
122
123TEST(S3ApiMethods, CompleteMultipartUpload) {
124 multipart_upload::CompleteMultipartUploadRequest request;
125 request.key = "some-key";
126 request.upload_id = "some_id";
127 request.completed_parts = {{1, "\"etag1\""}, {2, "\"etag2\""}, {3, "\"etag3\""}};
128
129 const auto result = CreateInternalApiRequest("some-bucket", request);
130
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");
134
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())},
138 };
139 EXPECT_EQ(expected_headers, result.headers);
140 EXPECT_EQ(
141 result.body,
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>"
147 );
148}
149
150TEST(S3ApiMethods, ListMultipartUploads) {
151 {
152 multipart_upload::ListMultipartUploadsRequest request;
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());
159 }
160 {
161 multipart_upload::ListMultipartUploadsRequest request;
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());
168
169 const auto requested_query_params = utils::text::SplitIntoStringViewVector(result.req, "&");
170 EXPECT_EQ(
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())
173 );
174 }
175 {
176 multipart_upload::ListMultipartUploadsRequest request;
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";
182
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());
188
189 const auto requested_query_params = utils::text::SplitIntoStringViewVector(result.req, "&");
190 EXPECT_EQ(
191 std::unordered_set<std::string_view>(
192 {"?uploads",
193 "prefix=some%2Fprefix%2Fto",
194 "max-uploads=100",
195 "marker=abc",
196 "delimiter=%2F",
197 "upload-id-marker=def"}
198 ),
199 std::unordered_set<std::string_view>(requested_query_params.begin(), requested_query_params.end())
200 );
201 }
202}
203
204TEST(S3ApiMethods, ListParts) {
205 {
206 multipart_upload::ListPartsRequest request;
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{});
214 }
215 {
216 multipart_upload::ListPartsRequest request;
217 request.key = "some/path/to";
218 request.upload_id = "some_id";
219 request.max_parts = 10;
220 request.part_number_marker = 11;
221
222 const auto result = CreateInternalApiRequest("some-bucket", request);
223 EXPECT_EQ(result.bucket, "some-bucket");
224 EXPECT_EQ(result.method, clients::http::HttpMethod::kGet);
225
226 const auto
227 requested_query_params = utils::text::SplitIntoStringViewVector(http::ExtractQueryView(result.req), "&");
228 EXPECT_EQ(
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())
231 );
232 EXPECT_EQ(result.req.substr(0, result.req.find('?')), "some/path/to");
233
234 EXPECT_EQ(result.headers, clients::http::Headers{});
235 }
236}
237
238} // namespace s3api::api_methods
239
240USERVER_NAMESPACE_END