1414
1515#include " google/cloud/storage/async/client.h"
1616#include " google/cloud/storage/mocks/mock_async_connection.h"
17+ #include " google/cloud/storage/mocks/mock_async_reader_connection.h"
1718#include " google/cloud/storage/mocks/mock_async_writer_connection.h"
1819#include " google/cloud/testing_util/status_matchers.h"
1920#include < gmock/gmock.h>
@@ -26,8 +27,14 @@ GOOGLE_CLOUD_CPP_INLINE_NAMESPACE_BEGIN
2627namespace {
2728
2829using ::google::cloud::storage_mocks::MockAsyncConnection;
30+ using ::google::cloud::storage_mocks::MockAsyncReaderConnection;
2931using ::google::cloud::storage_mocks::MockAsyncWriterConnection;
32+ using ::google::cloud::testing_util::IsOk;
3033using ::google::cloud::testing_util::IsOkAndHolds;
34+ using ::testing::ElementsAre;
35+ using ::testing::Eq;
36+ using ::testing::Optional;
37+ using ::testing::ResultOf;
3138using ::testing::Return;
3239using ::testing::VariantWith;
3340
@@ -43,6 +50,180 @@ storage::ObjectMetadata TestObject() {
4350 .set_size (0 );
4451}
4552
53+ TEST (AsyncClient, InsertObject) {
54+ auto mock = std::make_shared<MockAsyncConnection>();
55+ EXPECT_CALL (*mock, options)
56+ .WillRepeatedly (
57+ Return (Options{}.set <TestOption<0 >>(" O0" ).set <TestOption<1 >>(" O1" )));
58+
59+ EXPECT_CALL (*mock, InsertObject)
60+ .WillOnce ([](AsyncConnection::InsertObjectParams const & p) {
61+ EXPECT_THAT (p.options .get <TestOption<0 >>(), " O0" );
62+ EXPECT_THAT (p.options .get <TestOption<1 >>(), " O1-function" );
63+ EXPECT_THAT (p.options .get <TestOption<2 >>(), " O2-function" );
64+ EXPECT_EQ (p.request .bucket_name (), " test-bucket" );
65+ EXPECT_EQ (p.request .object_name (), " test-object" );
66+ EXPECT_EQ (p.request .GetOption <storage::IfGenerationMatch>().value_or (0 ),
67+ 42 );
68+ return make_ready_future (make_status_or (TestObject ()));
69+ });
70+
71+ auto client = AsyncClient (mock);
72+ auto response = client
73+ .InsertObject (" test-bucket" , " test-object" , " Contents" ,
74+ storage::IfGenerationMatch (42 ),
75+ Options{}
76+ .set <TestOption<1 >>(" O1-function" )
77+ .set <TestOption<2 >>(" O2-function" ))
78+ .get ();
79+ EXPECT_THAT (response, IsOkAndHolds (TestObject ()));
80+ }
81+
82+ TEST (AsyncClient, ReadObject) {
83+ auto mock = std::make_shared<MockAsyncConnection>();
84+ EXPECT_CALL (*mock, options)
85+ .WillRepeatedly (
86+ Return (Options{}.set <TestOption<0 >>(" O0" ).set <TestOption<1 >>(" O1" )));
87+
88+ EXPECT_CALL (*mock, ReadObject)
89+ .WillOnce ([](AsyncConnection::ReadObjectParams const & p) {
90+ EXPECT_THAT (p.options .get <TestOption<0 >>(), " O0" );
91+ EXPECT_THAT (p.options .get <TestOption<1 >>(), " O1-function" );
92+ EXPECT_THAT (p.options .get <TestOption<2 >>(), " O2-function" );
93+ EXPECT_EQ (p.request .bucket_name (), " test-bucket" );
94+ EXPECT_EQ (p.request .object_name (), " test-object" );
95+ EXPECT_EQ (p.request .GetOption <storage::Generation>().value_or (0 ), 42 );
96+ auto reader = std::make_unique<MockAsyncReaderConnection>();
97+ EXPECT_CALL (*reader, Read).WillOnce ([] {
98+ return make_ready_future (
99+ AsyncReaderConnection::ReadResponse{Status{}});
100+ });
101+ return make_ready_future (make_status_or (
102+ std::unique_ptr<AsyncReaderConnection>(std::move (reader))));
103+ });
104+
105+ auto client = AsyncClient (mock);
106+ auto rt =
107+ client
108+ .ReadObject (" test-bucket" , " test-object" , storage::Generation (42 ),
109+ Options{}
110+ .set <TestOption<1 >>(" O1-function" )
111+ .set <TestOption<2 >>(" O2-function" ))
112+ .get ();
113+ ASSERT_STATUS_OK (rt);
114+ AsyncReader r;
115+ AsyncToken t;
116+ std::tie (r, t) = *std::move (rt);
117+ EXPECT_TRUE (t.valid ());
118+
119+ auto pt = r.Read (std::move (t)).get ();
120+ AsyncReaderConnection::ReadResponse p;
121+ AsyncToken t2;
122+ ASSERT_STATUS_OK (pt);
123+ std::tie (p, t2) = *std::move (pt);
124+ EXPECT_FALSE (t2.valid ());
125+ EXPECT_THAT (
126+ p, VariantWith<ReadPayload>(ResultOf (
127+ " empty response" , [](auto const & p) { return p.size (); }, 0 )));
128+ }
129+
130+ TEST (AsyncClient, ReadObjectRange) {
131+ auto mock = std::make_shared<MockAsyncConnection>();
132+ EXPECT_CALL (*mock, options)
133+ .WillRepeatedly (
134+ Return (Options{}.set <TestOption<0 >>(" O0" ).set <TestOption<1 >>(" O1" )));
135+
136+ EXPECT_CALL (*mock, ReadObjectRange)
137+ .WillOnce ([](AsyncConnection::ReadObjectParams const & p) {
138+ EXPECT_THAT (p.options .get <TestOption<0 >>(), " O0" );
139+ EXPECT_THAT (p.options .get <TestOption<1 >>(), " O1-function" );
140+ EXPECT_THAT (p.options .get <TestOption<2 >>(), " O2-function" );
141+ EXPECT_EQ (p.request .bucket_name (), " test-bucket" );
142+ EXPECT_EQ (p.request .object_name (), " test-object" );
143+ EXPECT_EQ (p.request .GetOption <storage::Generation>().value_or (0 ), 42 );
144+ auto const range = p.request .GetOption <storage::ReadRange>().value_or (
145+ storage::ReadRangeData{0 , 0 });
146+ EXPECT_EQ (range.begin , 100 );
147+ EXPECT_EQ (range.end , 142 );
148+ return make_ready_future (
149+ make_status_or (ReadPayload{}.set_metadata (TestObject ())));
150+ });
151+
152+ auto client = AsyncClient (mock);
153+ auto payload = client
154+ .ReadObjectRange (" test-bucket" , " test-object" , 100 , 42 ,
155+ storage::Generation (42 ),
156+ Options{}
157+ .set <TestOption<1 >>(" O1-function" )
158+ .set <TestOption<2 >>(" O2-function" ))
159+ .get ();
160+ ASSERT_STATUS_OK (payload);
161+ EXPECT_THAT (payload->metadata (), Optional (Eq (TestObject ())));
162+ }
163+
164+ TEST (AsyncClient, StartUnbufferedUpload) {
165+ auto mock = std::make_shared<MockAsyncConnection>();
166+ EXPECT_CALL (*mock, options)
167+ .WillRepeatedly (
168+ Return (Options{}.set <TestOption<0 >>(" O0" ).set <TestOption<1 >>(" O1" )));
169+
170+ EXPECT_CALL (*mock, StartUnbufferedUpload)
171+ .WillOnce ([](AsyncConnection::UploadParams const & p) {
172+ EXPECT_THAT (p.options .get <TestOption<0 >>(), " O0" );
173+ EXPECT_THAT (p.options .get <TestOption<1 >>(), " O1-function" );
174+ EXPECT_THAT (p.options .get <TestOption<2 >>(), " O2-function" );
175+ EXPECT_EQ (p.request .bucket_name (), " test-bucket" );
176+ EXPECT_EQ (p.request .object_name (), " test-object" );
177+ EXPECT_EQ (p.request .GetOption <storage::IfGenerationMatch>().value_or (0 ),
178+ 42 );
179+ auto writer = std::make_unique<MockAsyncWriterConnection>();
180+ EXPECT_CALL (*writer, PersistedState).WillOnce (Return (0 ));
181+ EXPECT_CALL (*writer, Finalize).WillRepeatedly ([] {
182+ return make_ready_future (make_status_or (TestObject ()));
183+ });
184+ return make_ready_future (make_status_or (
185+ std::unique_ptr<AsyncWriterConnection>(std::move (writer))));
186+ });
187+
188+ auto client = AsyncClient (mock);
189+ auto wt = client
190+ .StartUnbufferedUpload (" test-bucket" , " test-object" ,
191+ storage::IfGenerationMatch (42 ),
192+ Options{}
193+ .set <TestOption<1 >>(" O1-function" )
194+ .set <TestOption<2 >>(" O2-function" ))
195+ .get ();
196+ ASSERT_STATUS_OK (wt);
197+ AsyncWriter w;
198+ AsyncToken t;
199+ std::tie (w, t) = *std::move (wt);
200+ EXPECT_TRUE (t.valid ());
201+ auto object = w.Finalize (std::move (t)).get ();
202+ EXPECT_THAT (object, IsOkAndHolds (TestObject ()));
203+ }
204+
205+ TEST (AsyncClient, StartUnbufferedUploadResumeFinalized) {
206+ auto mock = std::make_shared<MockAsyncConnection>();
207+ EXPECT_CALL (*mock, options).WillRepeatedly (Return (Options{}));
208+ EXPECT_CALL (*mock, StartUnbufferedUpload).WillOnce ([] {
209+ auto writer = std::make_unique<MockAsyncWriterConnection>();
210+ EXPECT_CALL (*writer, PersistedState).WillRepeatedly (Return (TestObject ()));
211+
212+ return make_ready_future (make_status_or (
213+ std::unique_ptr<AsyncWriterConnection>(std::move (writer))));
214+ });
215+
216+ auto client = AsyncClient (mock);
217+ auto wt = client.StartUnbufferedUpload (" test-bucket" , " test-object" ).get ();
218+ ASSERT_STATUS_OK (wt);
219+ AsyncWriter w;
220+ AsyncToken t;
221+ std::tie (w, t) = *std::move (wt);
222+ EXPECT_FALSE (t.valid ());
223+ EXPECT_THAT (w.PersistedState (),
224+ VariantWith<storage::ObjectMetadata>(TestObject ()));
225+ }
226+
46227TEST (AsyncClient, StartBufferedUpload) {
47228 auto mock = std::make_shared<MockAsyncConnection>();
48229 EXPECT_CALL (*mock, options)
@@ -106,6 +287,76 @@ TEST(AsyncClient, StartBufferedUploadResumeFinalized) {
106287 VariantWith<storage::ObjectMetadata>(TestObject ()));
107288}
108289
290+ TEST (AsyncClient, ComposeObject) {
291+ auto mock = std::make_shared<MockAsyncConnection>();
292+ EXPECT_CALL (*mock, options)
293+ .WillRepeatedly (
294+ Return (Options{}.set <TestOption<0 >>(" O0" ).set <TestOption<1 >>(" O1" )));
295+
296+ EXPECT_CALL (*mock, ComposeObject)
297+ .WillOnce ([](AsyncConnection::ComposeObjectParams const & p) {
298+ EXPECT_THAT (p.options .get <TestOption<0 >>(), " O0" );
299+ EXPECT_THAT (p.options .get <TestOption<1 >>(), " O1-function" );
300+ EXPECT_THAT (p.options .get <TestOption<2 >>(), " O2-function" );
301+ EXPECT_EQ (p.request .bucket_name (), " test-bucket" );
302+ auto source_is = [](std::string name) {
303+ return ResultOf (
304+ " source object name" , [](auto const & s) { return s.object_name ; },
305+ std::move (name));
306+ };
307+ EXPECT_THAT (p.request .source_objects (),
308+ ElementsAre (source_is (" source0" ), source_is (" source1" )));
309+ EXPECT_EQ (p.request .object_name (), " test-object" );
310+ EXPECT_EQ (p.request .GetOption <storage::IfGenerationMatch>().value_or (0 ),
311+ 42 );
312+ return make_ready_future (make_status_or (TestObject ()));
313+ });
314+
315+ auto client = AsyncClient (mock);
316+ auto response =
317+ client
318+ .ComposeObject (" test-bucket" ,
319+ {storage::ComposeSourceObject{" source0" , absl::nullopt ,
320+ absl::nullopt },
321+ storage::ComposeSourceObject{" source1" , absl::nullopt ,
322+ absl::nullopt }},
323+ " test-object" , storage::IfGenerationMatch (42 ),
324+ Options{}
325+ .set <TestOption<1 >>(" O1-function" )
326+ .set <TestOption<2 >>(" O2-function" ))
327+ .get ();
328+ EXPECT_THAT (response, IsOkAndHolds (TestObject ()));
329+ }
330+
331+ TEST (AsyncClient, DeleteObject) {
332+ auto mock = std::make_shared<MockAsyncConnection>();
333+ EXPECT_CALL (*mock, options)
334+ .WillRepeatedly (
335+ Return (Options{}.set <TestOption<0 >>(" O0" ).set <TestOption<1 >>(" O1" )));
336+
337+ EXPECT_CALL (*mock, DeleteObject)
338+ .WillOnce ([](AsyncConnection::DeleteObjectParams const & p) {
339+ EXPECT_THAT (p.options .get <TestOption<0 >>(), " O0" );
340+ EXPECT_THAT (p.options .get <TestOption<1 >>(), " O1-function" );
341+ EXPECT_THAT (p.options .get <TestOption<2 >>(), " O2-function" );
342+ EXPECT_EQ (p.request .bucket_name (), " test-bucket" );
343+ EXPECT_EQ (p.request .object_name (), " test-object" );
344+ EXPECT_EQ (p.request .GetOption <storage::IfGenerationMatch>().value_or (0 ),
345+ 42 );
346+ return make_ready_future (Status{});
347+ });
348+
349+ auto client = AsyncClient (mock);
350+ auto response = client
351+ .DeleteObject (" test-bucket" , " test-object" ,
352+ storage::IfGenerationMatch (42 ),
353+ Options{}
354+ .set <TestOption<1 >>(" O1-function" )
355+ .set <TestOption<2 >>(" O2-function" ))
356+ .get ();
357+ EXPECT_THAT (response, IsOk ());
358+ }
359+
109360} // namespace
110361GOOGLE_CLOUD_CPP_INLINE_NAMESPACE_END
111362} // namespace storage_experimental
0 commit comments