1 // Copyright 2019 Google LLC 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 #ifndef GOOGLE_CLOUD_CPP_GOOGLE_CLOUD_BIGTABLE_TESTING_MOCK_ASYNC_FAILING_RPC_FACTORY_H 16 #define GOOGLE_CLOUD_CPP_GOOGLE_CLOUD_BIGTABLE_TESTING_MOCK_ASYNC_FAILING_RPC_FACTORY_H 17 18 #include "google/cloud/bigtable/testing/mock_response_reader.h" 19 #include "google/cloud/internal/api_client_header.h" 20 #include "google/cloud/status.h" 21 #include "google/cloud/testing_util/validate_metadata.h" 22 #include <google/protobuf/text_format.h> 23 #include <google/protobuf/util/message_differencer.h> 24 #include <grpcpp/support/async_unary_call.h> 25 #include <string> 26 27 namespace google { 28 namespace cloud { 29 namespace bigtable { 30 namespace testing { 31 32 /** 33 * Helper class to create the expectations for a failing async RPC call. 34 * 35 * Given the type of the request and responses, this struct provides a function 36 * to create a mock implementation with the right signature and checks. 37 * 38 * @tparam RequestType the protobuf type for the request. 39 * @tparam ResponseType the protobuf type for the response. 40 */ 41 template <typename RequestType, typename ResponseType> 42 struct MockAsyncFailingRpcFactory { 43 using SignatureType = 44 std::unique_ptr<grpc::ClientAsyncResponseReaderInterface<ResponseType>>( 45 grpc::ClientContext* context, RequestType const& request, 46 grpc::CompletionQueue*); 47 MockAsyncFailingRpcFactoryMockAsyncFailingRpcFactory48 MockAsyncFailingRpcFactory() 49 : reader(new google::cloud::bigtable::testing::MockAsyncResponseReader< 50 ResponseType>) {} 51 52 /// Refactor the boilerplate common to most tests. CreateMockAsyncFailingRpcFactory53 std::function<SignatureType> Create(std::string const& expected_request, 54 std::string const& method) { 55 return std::function<SignatureType>([expected_request, method, this]( 56 grpc::ClientContext* context, 57 RequestType const& request, 58 grpc::CompletionQueue*) { 59 using ::testing::_; 60 EXPECT_STATUS_OK(google::cloud::testing_util::IsContextMDValid( 61 *context, method, google::cloud::internal::ApiClientHeader())); 62 RequestType expected; 63 // Cannot use ASSERT_TRUE() here, it has an embedded "return;" 64 EXPECT_TRUE(google::protobuf::TextFormat::ParseFromString( 65 expected_request, &expected)); 66 std::string delta; 67 google::protobuf::util::MessageDifferencer differencer; 68 differencer.ReportDifferencesToString(&delta); 69 EXPECT_TRUE(differencer.Compare(expected, request)) << delta; 70 71 EXPECT_CALL(*reader, Finish(_, _, _)) 72 .WillOnce([](ResponseType* response, grpc::Status* status, void*) { 73 EXPECT_NE(nullptr, response); 74 *status = grpc::Status(grpc::StatusCode::PERMISSION_DENIED, "nooo"); 75 }); 76 // This is safe, see comments in MockAsyncResponseReader. 77 return std::unique_ptr< 78 grpc::ClientAsyncResponseReaderInterface<ResponseType>>(reader.get()); 79 }); 80 } 81 82 std::unique_ptr< 83 google::cloud::bigtable::testing::MockAsyncResponseReader<ResponseType>> 84 reader; 85 }; 86 } // namespace testing 87 } // namespace bigtable 88 } // namespace cloud 89 } // namespace google 90 91 #endif // GOOGLE_CLOUD_CPP_GOOGLE_CLOUD_BIGTABLE_TESTING_MOCK_ASYNC_FAILING_RPC_FACTORY_H 92