1313// limitations under the License.
1414
1515#include " google/cloud/storage/internal/rest/stub.h"
16+ #include " google/cloud/storage/internal/hash_function.h"
1617#include " google/cloud/storage/testing/canonical_errors.h"
1718#include " google/cloud/internal/api_client_header.h"
1819#include " google/cloud/testing_util/mock_rest_client.h"
@@ -45,17 +46,44 @@ using ::testing::Pair;
4546using ::testing::ResultOf;
4647using ::testing::Return;
4748
49+ class NoOpHashFunction : public HashFunction {
50+ public:
51+ std::string Name () const override { return " NoOp" ; }
52+ void Update (absl::string_view b) override { Cormorant (b); }
53+ Status Update (std::int64_t o, absl::string_view b) override {
54+ Cormorant (o, b);
55+ return Status{};
56+ }
57+ Status Update (std::int64_t o, absl::string_view b,
58+ std::uint32_t c) override {
59+ Cormorant (o, b, c);
60+ return Status{};
61+ }
62+ Status Update (std::int64_t o, absl::Cord const & b,
63+ std::uint32_t c) override {
64+ Cormorant (o, b, c);
65+ return Status{};
66+ }
67+ HashValues Finish () override { return {}; }
68+
69+ private:
70+ template <typename ... Args>
71+ void Cormorant (Args const &...) {}
72+ };
73+
4874TEST (RestStubTest, ResolveStorageAuthorityProdEndpoint) {
4975 auto options =
50- Options{}.set <RestEndpointOption>(" https://storage.googleapis.com" );
76+ Options{}.set <RestEndpointOption>(" https://storage.googleapis.com" )
77+ .set <AuthorityOption>(" storage.googleapis.com" );
5178 auto result_options = RestStub::ResolveStorageAuthority (options);
5279 EXPECT_THAT (result_options.get <AuthorityOption>(),
5380 Eq (" storage.googleapis.com" ));
5481}
5582
5683TEST (RestStubTest, ResolveStorageAuthorityEapEndpoint) {
5784 auto options =
58- Options{}.set <RestEndpointOption>(" https://eap.googleapis.com" );
85+ Options{}.set <RestEndpointOption>(" https://eap.googleapis.com" )
86+ .set <AuthorityOption>(" storage.googleapis.com" );
5987 auto result_options = RestStub::ResolveStorageAuthority (options);
6088 EXPECT_THAT (result_options.get <AuthorityOption>(),
6189 Eq (" storage.googleapis.com" ));
@@ -78,13 +106,15 @@ TEST(RestStubTest, ResolveStorageAuthorityOptionSpecified) {
78106TEST (RestStubTest, ResolveIamAuthorityProdEndpoint) {
79107 auto options =
80108 Options{}.set <IamEndpointOption>(" https://iamcredentials.googleapis.com" );
81- auto result_options = RestStub::ResolveIamAuthority (options);
109+ auto result_options = RestStub::ResolveIamAuthority (options)
110+ .set <AuthorityOption>(" iamcredentials.googleapis.com" );
82111 EXPECT_THAT (result_options.get <AuthorityOption>(),
83112 Eq (" iamcredentials.googleapis.com" ));
84113}
85114
86115TEST (RestStubTest, ResolveIamAuthorityEapEndpoint) {
87- auto options = Options{}.set <IamEndpointOption>(" https://eap.googleapis.com" );
116+ auto options = Options{}.set <IamEndpointOption>(" https://eap.googleapis.com" )
117+ .set <AuthorityOption>(" iamcredentials.googleapis.com" );
88118 auto result_options = RestStub::ResolveIamAuthority (options);
89119 EXPECT_THAT (result_options.get <AuthorityOption>(),
90120 Eq (" iamcredentials.googleapis.com" ));
@@ -921,6 +951,90 @@ TEST(RestStubTest, DeleteNotification) {
921951 StatusIs (PermanentError ().code (), PermanentError ().message ()));
922952}
923953
954+ TEST (RestStubTest, UploadChunkLastChunkWithCrc32c) {
955+ auto mock = std::make_shared<MockRestClient>();
956+ EXPECT_CALL (
957+ *mock,
958+ Put (ExpectedContext (),
959+ ResultOf (
960+ " request headers contain x-goog-hash with crc32c" ,
961+ [](RestRequest const & r) { return r.headers (); },
962+ Contains (Pair (" x-goog-hash" , ElementsAre (" crc32c=test-crc32" )))),
963+ ExpectedPayload ()))
964+ .WillOnce (Return (PermanentError ()));
965+ auto tested = std::make_unique<RestStub>(Options{}, mock, mock);
966+ auto context = TestContext ();
967+ auto status = tested->UploadChunk (
968+ context, TestOptions (),
969+ UploadChunkRequest (" test-url" , 0 , {},
970+ std::make_shared<NoOpHashFunction>(),
971+ {" test-crc32c" , " " }));
972+ EXPECT_THAT (status,
973+ StatusIs (PermanentError ().code (), PermanentError ().message ()));
974+ }
975+
976+ TEST (RestStubTest, UploadChunkLastChunkWithMd5) {
977+ auto mock = std::make_shared<MockRestClient>();
978+ EXPECT_CALL (*mock,
979+ Put (ExpectedContext (),
980+ ResultOf (" request headers contain x-goog-hash with md5" ,
981+ [](RestRequest const & r) { return r.headers (); },
982+ Contains (Pair (" x-goog-hash" ,
983+ ElementsAre (" md5=test-md5" )))),
984+ ExpectedPayload ()))
985+ .WillOnce (Return (PermanentError ()));
986+ auto tested = std::make_unique<RestStub>(Options{}, mock, mock);
987+ auto context = TestContext ();
988+ auto status = tested->UploadChunk (
989+ context, TestOptions (),
990+ UploadChunkRequest (" test-url" , 0 , {},
991+ std::make_shared<NoOpHashFunction>(),
992+ {" " , " test-md5" }));
993+ EXPECT_THAT (status,
994+ StatusIs (PermanentError ().code (), PermanentError ().message ()));
995+ }
996+
997+ TEST (RestStubTest, UploadChunkLastChunkWithBoth) {
998+ auto mock = std::make_shared<MockRestClient>();
999+ EXPECT_CALL (
1000+ *mock,
1001+ Put (ExpectedContext (),
1002+ ResultOf (
1003+ " request headers contain x-goog-hash with crc32c and md5" ,
1004+ [](RestRequest const & r) { return r.headers (); },
1005+ Contains (Pair (" x-goog-hash" , ElementsAre (" crc32c=test-crc32c" ,
1006+ " md5=test-md5" )))),
1007+ ExpectedPayload ()))
1008+ .WillOnce (Return (PermanentError ()));
1009+ auto tested = std::make_unique<RestStub>(Options{}, mock, mock);
1010+ auto context = TestContext ();
1011+ auto status = tested->UploadChunk (
1012+ context, TestOptions (),
1013+ UploadChunkRequest (" test-url" , 0 , {},
1014+ std::make_shared<NoOpHashFunction>(),
1015+ {" test-crc32c" , " test-md5" }));
1016+ EXPECT_THAT (status,
1017+ StatusIs (PermanentError ().code (), PermanentError ().message ()));
1018+ }
1019+
1020+ TEST (RestStubTest, UploadChunkIntermediate) {
1021+ auto mock = std::make_shared<MockRestClient>();
1022+ EXPECT_CALL (*mock, Put (ExpectedContext (),
1023+ ResultOf (" request headers do not contain x-goog-hash" ,
1024+ [](RestRequest const & r) { return r.headers (); },
1025+ Not (Contains (Pair (" x-goog-hash" , _)))),
1026+ ExpectedPayload ()))
1027+ .WillOnce (Return (PermanentError ()));
1028+ auto tested = std::make_unique<RestStub>(Options{}, mock, mock);
1029+ auto context = TestContext ();
1030+ auto status = tested->UploadChunk (
1031+ context, TestOptions (),
1032+ UploadChunkRequest (" test-url" , 0 , {},
1033+ std::make_shared<NoOpHashFunction>()));
1034+ EXPECT_THAT (status,
1035+ StatusIs (PermanentError ().code (), PermanentError ().message ()));
1036+ }
1037+
9241038} // namespace
9251039} // namespace internal
9261040GOOGLE_CLOUD_CPP_INLINE_NAMESPACE_END
0 commit comments