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