| /* |
| * |
| * Copyright 2018 gRPC authors. |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| * |
| */ |
| |
| #include <memory> |
| #include <vector> |
| |
| #include <grpcpp/channel.h> |
| #include <grpcpp/client_context.h> |
| #include <grpcpp/create_channel.h> |
| #include <grpcpp/generic/generic_stub.h> |
| #include <grpcpp/impl/codegen/proto_utils.h> |
| #include <grpcpp/server.h> |
| #include <grpcpp/server_builder.h> |
| #include <grpcpp/server_context.h> |
| #include <grpcpp/support/client_interceptor.h> |
| |
| #include "absl/memory/memory.h" |
| #include "src/proto/grpc/testing/echo.grpc.pb.h" |
| #include "test/core/util/port.h" |
| #include "test/core/util/test_config.h" |
| #include "test/cpp/end2end/interceptors_util.h" |
| #include "test/cpp/end2end/test_service_impl.h" |
| #include "test/cpp/util/byte_buffer_proto_helper.h" |
| #include "test/cpp/util/string_ref_helper.h" |
| |
| #include <gtest/gtest.h> |
| |
| namespace grpc { |
| namespace testing { |
| namespace { |
| |
| enum class RPCType { |
| kSyncUnary, |
| kSyncClientStreaming, |
| kSyncServerStreaming, |
| kSyncBidiStreaming, |
| kAsyncCQUnary, |
| kAsyncCQClientStreaming, |
| kAsyncCQServerStreaming, |
| kAsyncCQBidiStreaming, |
| }; |
| |
| /* Hijacks Echo RPC and fills in the expected values */ |
| class HijackingInterceptor : public experimental::Interceptor { |
| public: |
| HijackingInterceptor(experimental::ClientRpcInfo* info) { |
| info_ = info; |
| // Make sure it is the right method |
| EXPECT_EQ(strcmp("/grpc.testing.EchoTestService/Echo", info->method()), 0); |
| EXPECT_EQ(info->type(), experimental::ClientRpcInfo::Type::UNARY); |
| } |
| |
| virtual void Intercept(experimental::InterceptorBatchMethods* methods) { |
| bool hijack = false; |
| if (methods->QueryInterceptionHookPoint( |
| experimental::InterceptionHookPoints::PRE_SEND_INITIAL_METADATA)) { |
| auto* map = methods->GetSendInitialMetadata(); |
| // Check that we can see the test metadata |
| ASSERT_EQ(map->size(), static_cast<unsigned>(1)); |
| auto iterator = map->begin(); |
| EXPECT_EQ("testkey", iterator->first); |
| EXPECT_EQ("testvalue", iterator->second); |
| hijack = true; |
| } |
| if (methods->QueryInterceptionHookPoint( |
| experimental::InterceptionHookPoints::PRE_SEND_MESSAGE)) { |
| EchoRequest req; |
| auto* buffer = methods->GetSerializedSendMessage(); |
| auto copied_buffer = *buffer; |
| EXPECT_TRUE( |
| SerializationTraits<EchoRequest>::Deserialize(&copied_buffer, &req) |
| .ok()); |
| EXPECT_EQ(req.message(), "Hello"); |
| } |
| if (methods->QueryInterceptionHookPoint( |
| experimental::InterceptionHookPoints::PRE_SEND_CLOSE)) { |
| // Got nothing to do here for now |
| } |
| if (methods->QueryInterceptionHookPoint( |
| experimental::InterceptionHookPoints::POST_RECV_INITIAL_METADATA)) { |
| auto* map = methods->GetRecvInitialMetadata(); |
| // Got nothing better to do here for now |
| EXPECT_EQ(map->size(), static_cast<unsigned>(0)); |
| } |
| if (methods->QueryInterceptionHookPoint( |
| experimental::InterceptionHookPoints::POST_RECV_MESSAGE)) { |
| EchoResponse* resp = |
| static_cast<EchoResponse*>(methods->GetRecvMessage()); |
| // Check that we got the hijacked message, and re-insert the expected |
| // message |
| EXPECT_EQ(resp->message(), "Hello1"); |
| resp->set_message("Hello"); |
| } |
| if (methods->QueryInterceptionHookPoint( |
| experimental::InterceptionHookPoints::POST_RECV_STATUS)) { |
| auto* map = methods->GetRecvTrailingMetadata(); |
| bool found = false; |
| // Check that we received the metadata as an echo |
| for (const auto& pair : *map) { |
| found = pair.first.starts_with("testkey") && |
| pair.second.starts_with("testvalue"); |
| if (found) break; |
| } |
| EXPECT_EQ(found, true); |
| auto* status = methods->GetRecvStatus(); |
| EXPECT_EQ(status->ok(), true); |
| } |
| if (methods->QueryInterceptionHookPoint( |
| experimental::InterceptionHookPoints::PRE_RECV_INITIAL_METADATA)) { |
| auto* map = methods->GetRecvInitialMetadata(); |
| // Got nothing better to do here at the moment |
| EXPECT_EQ(map->size(), static_cast<unsigned>(0)); |
| } |
| if (methods->QueryInterceptionHookPoint( |
| experimental::InterceptionHookPoints::PRE_RECV_MESSAGE)) { |
| // Insert a different message than expected |
| EchoResponse* resp = |
| static_cast<EchoResponse*>(methods->GetRecvMessage()); |
| resp->set_message("Hello1"); |
| } |
| if (methods->QueryInterceptionHookPoint( |
| experimental::InterceptionHookPoints::PRE_RECV_STATUS)) { |
| auto* map = methods->GetRecvTrailingMetadata(); |
| // insert the metadata that we want |
| EXPECT_EQ(map->size(), static_cast<unsigned>(0)); |
| map->insert(std::make_pair("testkey", "testvalue")); |
| auto* status = methods->GetRecvStatus(); |
| *status = Status(StatusCode::OK, ""); |
| } |
| if (hijack) { |
| methods->Hijack(); |
| } else { |
| methods->Proceed(); |
| } |
| } |
| |
| private: |
| experimental::ClientRpcInfo* info_; |
| }; |
| |
| class HijackingInterceptorFactory |
| : public experimental::ClientInterceptorFactoryInterface { |
| public: |
| virtual experimental::Interceptor* CreateClientInterceptor( |
| experimental::ClientRpcInfo* info) override { |
| return new HijackingInterceptor(info); |
| } |
| }; |
| |
| class HijackingInterceptorMakesAnotherCall : public experimental::Interceptor { |
| public: |
| HijackingInterceptorMakesAnotherCall(experimental::ClientRpcInfo* info) { |
| info_ = info; |
| // Make sure it is the right method |
| EXPECT_EQ(strcmp("/grpc.testing.EchoTestService/Echo", info->method()), 0); |
| } |
| |
| virtual void Intercept(experimental::InterceptorBatchMethods* methods) { |
| if (methods->QueryInterceptionHookPoint( |
| experimental::InterceptionHookPoints::PRE_SEND_INITIAL_METADATA)) { |
| auto* map = methods->GetSendInitialMetadata(); |
| // Check that we can see the test metadata |
| ASSERT_EQ(map->size(), static_cast<unsigned>(1)); |
| auto iterator = map->begin(); |
| EXPECT_EQ("testkey", iterator->first); |
| EXPECT_EQ("testvalue", iterator->second); |
| // Make a copy of the map |
| metadata_map_ = *map; |
| } |
| if (methods->QueryInterceptionHookPoint( |
| experimental::InterceptionHookPoints::PRE_SEND_MESSAGE)) { |
| EchoRequest req; |
| auto* buffer = methods->GetSerializedSendMessage(); |
| auto copied_buffer = *buffer; |
| EXPECT_TRUE( |
| SerializationTraits<EchoRequest>::Deserialize(&copied_buffer, &req) |
| .ok()); |
| EXPECT_EQ(req.message(), "Hello"); |
| req_ = req; |
| stub_ = grpc::testing::EchoTestService::NewStub( |
| methods->GetInterceptedChannel()); |
| ctx_.AddMetadata(metadata_map_.begin()->first, |
| metadata_map_.begin()->second); |
| stub_->experimental_async()->Echo(&ctx_, &req_, &resp_, |
| [this, methods](Status s) { |
| EXPECT_EQ(s.ok(), true); |
| EXPECT_EQ(resp_.message(), "Hello"); |
| methods->Hijack(); |
| }); |
| // This is a Unary RPC and we have got nothing interesting to do in the |
| // PRE_SEND_CLOSE interception hook point for this interceptor, so let's |
| // return here. (We do not want to call methods->Proceed(). When the new |
| // RPC returns, we will call methods->Hijack() instead.) |
| return; |
| } |
| if (methods->QueryInterceptionHookPoint( |
| experimental::InterceptionHookPoints::PRE_SEND_CLOSE)) { |
| // Got nothing to do here for now |
| } |
| if (methods->QueryInterceptionHookPoint( |
| experimental::InterceptionHookPoints::POST_RECV_INITIAL_METADATA)) { |
| auto* map = methods->GetRecvInitialMetadata(); |
| // Got nothing better to do here for now |
| EXPECT_EQ(map->size(), static_cast<unsigned>(0)); |
| } |
| if (methods->QueryInterceptionHookPoint( |
| experimental::InterceptionHookPoints::POST_RECV_MESSAGE)) { |
| EchoResponse* resp = |
| static_cast<EchoResponse*>(methods->GetRecvMessage()); |
| // Check that we got the hijacked message, and re-insert the expected |
| // message |
| EXPECT_EQ(resp->message(), "Hello"); |
| } |
| if (methods->QueryInterceptionHookPoint( |
| experimental::InterceptionHookPoints::POST_RECV_STATUS)) { |
| auto* map = methods->GetRecvTrailingMetadata(); |
| bool found = false; |
| // Check that we received the metadata as an echo |
| for (const auto& pair : *map) { |
| found = pair.first.starts_with("testkey") && |
| pair.second.starts_with("testvalue"); |
| if (found) break; |
| } |
| EXPECT_EQ(found, true); |
| auto* status = methods->GetRecvStatus(); |
| EXPECT_EQ(status->ok(), true); |
| } |
| if (methods->QueryInterceptionHookPoint( |
| experimental::InterceptionHookPoints::PRE_RECV_INITIAL_METADATA)) { |
| auto* map = methods->GetRecvInitialMetadata(); |
| // Got nothing better to do here at the moment |
| EXPECT_EQ(map->size(), static_cast<unsigned>(0)); |
| } |
| if (methods->QueryInterceptionHookPoint( |
| experimental::InterceptionHookPoints::PRE_RECV_MESSAGE)) { |
| // Insert a different message than expected |
| EchoResponse* resp = |
| static_cast<EchoResponse*>(methods->GetRecvMessage()); |
| resp->set_message(resp_.message()); |
| } |
| if (methods->QueryInterceptionHookPoint( |
| experimental::InterceptionHookPoints::PRE_RECV_STATUS)) { |
| auto* map = methods->GetRecvTrailingMetadata(); |
| // insert the metadata that we want |
| EXPECT_EQ(map->size(), static_cast<unsigned>(0)); |
| map->insert(std::make_pair("testkey", "testvalue")); |
| auto* status = methods->GetRecvStatus(); |
| *status = Status(StatusCode::OK, ""); |
| } |
| |
| methods->Proceed(); |
| } |
| |
| private: |
| experimental::ClientRpcInfo* info_; |
| std::multimap<std::string, std::string> metadata_map_; |
| ClientContext ctx_; |
| EchoRequest req_; |
| EchoResponse resp_; |
| std::unique_ptr<grpc::testing::EchoTestService::Stub> stub_; |
| }; |
| |
| class HijackingInterceptorMakesAnotherCallFactory |
| : public experimental::ClientInterceptorFactoryInterface { |
| public: |
| virtual experimental::Interceptor* CreateClientInterceptor( |
| experimental::ClientRpcInfo* info) override { |
| return new HijackingInterceptorMakesAnotherCall(info); |
| } |
| }; |
| |
| class BidiStreamingRpcHijackingInterceptor : public experimental::Interceptor { |
| public: |
| BidiStreamingRpcHijackingInterceptor(experimental::ClientRpcInfo* info) { |
| info_ = info; |
| } |
| |
| virtual void Intercept(experimental::InterceptorBatchMethods* methods) { |
| bool hijack = false; |
| if (methods->QueryInterceptionHookPoint( |
| experimental::InterceptionHookPoints::PRE_SEND_INITIAL_METADATA)) { |
| CheckMetadata(*methods->GetSendInitialMetadata(), "testkey", "testvalue"); |
| hijack = true; |
| } |
| if (methods->QueryInterceptionHookPoint( |
| experimental::InterceptionHookPoints::PRE_SEND_MESSAGE)) { |
| EchoRequest req; |
| auto* buffer = methods->GetSerializedSendMessage(); |
| auto copied_buffer = *buffer; |
| EXPECT_TRUE( |
| SerializationTraits<EchoRequest>::Deserialize(&copied_buffer, &req) |
| .ok()); |
| EXPECT_EQ(req.message().find("Hello"), 0u); |
| msg = req.message(); |
| } |
| if (methods->QueryInterceptionHookPoint( |
| experimental::InterceptionHookPoints::PRE_SEND_CLOSE)) { |
| // Got nothing to do here for now |
| } |
| if (methods->QueryInterceptionHookPoint( |
| experimental::InterceptionHookPoints::POST_RECV_STATUS)) { |
| CheckMetadata(*methods->GetRecvTrailingMetadata(), "testkey", |
| "testvalue"); |
| auto* status = methods->GetRecvStatus(); |
| EXPECT_EQ(status->ok(), true); |
| } |
| if (methods->QueryInterceptionHookPoint( |
| experimental::InterceptionHookPoints::PRE_RECV_MESSAGE)) { |
| EchoResponse* resp = |
| static_cast<EchoResponse*>(methods->GetRecvMessage()); |
| resp->set_message(msg); |
| } |
| if (methods->QueryInterceptionHookPoint( |
| experimental::InterceptionHookPoints::POST_RECV_MESSAGE)) { |
| EXPECT_EQ(static_cast<EchoResponse*>(methods->GetRecvMessage()) |
| ->message() |
| .find("Hello"), |
| 0u); |
| } |
| if (methods->QueryInterceptionHookPoint( |
| experimental::InterceptionHookPoints::PRE_RECV_STATUS)) { |
| auto* map = methods->GetRecvTrailingMetadata(); |
| // insert the metadata that we want |
| EXPECT_EQ(map->size(), static_cast<unsigned>(0)); |
| map->insert(std::make_pair("testkey", "testvalue")); |
| auto* status = methods->GetRecvStatus(); |
| *status = Status(StatusCode::OK, ""); |
| } |
| if (hijack) { |
| methods->Hijack(); |
| } else { |
| methods->Proceed(); |
| } |
| } |
| |
| private: |
| experimental::ClientRpcInfo* info_; |
| std::string msg; |
| }; |
| |
| class ClientStreamingRpcHijackingInterceptor |
| : public experimental::Interceptor { |
| public: |
| ClientStreamingRpcHijackingInterceptor(experimental::ClientRpcInfo* info) { |
| info_ = info; |
| } |
| virtual void Intercept(experimental::InterceptorBatchMethods* methods) { |
| bool hijack = false; |
| if (methods->QueryInterceptionHookPoint( |
| experimental::InterceptionHookPoints::PRE_SEND_INITIAL_METADATA)) { |
| hijack = true; |
| } |
| if (methods->QueryInterceptionHookPoint( |
| experimental::InterceptionHookPoints::PRE_SEND_MESSAGE)) { |
| if (++count_ > 10) { |
| methods->FailHijackedSendMessage(); |
| } |
| } |
| if (methods->QueryInterceptionHookPoint( |
| experimental::InterceptionHookPoints::POST_SEND_MESSAGE)) { |
| EXPECT_FALSE(got_failed_send_); |
| got_failed_send_ = !methods->GetSendMessageStatus(); |
| } |
| if (methods->QueryInterceptionHookPoint( |
| experimental::InterceptionHookPoints::PRE_RECV_STATUS)) { |
| auto* status = methods->GetRecvStatus(); |
| *status = Status(StatusCode::UNAVAILABLE, "Done sending 10 messages"); |
| } |
| if (hijack) { |
| methods->Hijack(); |
| } else { |
| methods->Proceed(); |
| } |
| } |
| |
| static bool GotFailedSend() { return got_failed_send_; } |
| |
| private: |
| experimental::ClientRpcInfo* info_; |
| int count_ = 0; |
| static bool got_failed_send_; |
| }; |
| |
| bool ClientStreamingRpcHijackingInterceptor::got_failed_send_ = false; |
| |
| class ClientStreamingRpcHijackingInterceptorFactory |
| : public experimental::ClientInterceptorFactoryInterface { |
| public: |
| virtual experimental::Interceptor* CreateClientInterceptor( |
| experimental::ClientRpcInfo* info) override { |
| return new ClientStreamingRpcHijackingInterceptor(info); |
| } |
| }; |
| |
| class ServerStreamingRpcHijackingInterceptor |
| : public experimental::Interceptor { |
| public: |
| ServerStreamingRpcHijackingInterceptor(experimental::ClientRpcInfo* info) { |
| info_ = info; |
| got_failed_message_ = false; |
| } |
| |
| virtual void Intercept(experimental::InterceptorBatchMethods* methods) { |
| bool hijack = false; |
| if (methods->QueryInterceptionHookPoint( |
| experimental::InterceptionHookPoints::PRE_SEND_INITIAL_METADATA)) { |
| auto* map = methods->GetSendInitialMetadata(); |
| // Check that we can see the test metadata |
| ASSERT_EQ(map->size(), static_cast<unsigned>(1)); |
| auto iterator = map->begin(); |
| EXPECT_EQ("testkey", iterator->first); |
| EXPECT_EQ("testvalue", iterator->second); |
| hijack = true; |
| } |
| if (methods->QueryInterceptionHookPoint( |
| experimental::InterceptionHookPoints::PRE_SEND_MESSAGE)) { |
| EchoRequest req; |
| auto* buffer = methods->GetSerializedSendMessage(); |
| auto copied_buffer = *buffer; |
| EXPECT_TRUE( |
| SerializationTraits<EchoRequest>::Deserialize(&copied_buffer, &req) |
| .ok()); |
| EXPECT_EQ(req.message(), "Hello"); |
| } |
| if (methods->QueryInterceptionHookPoint( |
| experimental::InterceptionHookPoints::PRE_SEND_CLOSE)) { |
| // Got nothing to do here for now |
| } |
| if (methods->QueryInterceptionHookPoint( |
| experimental::InterceptionHookPoints::POST_RECV_STATUS)) { |
| auto* map = methods->GetRecvTrailingMetadata(); |
| bool found = false; |
| // Check that we received the metadata as an echo |
| for (const auto& pair : *map) { |
| found = pair.first.starts_with("testkey") && |
| pair.second.starts_with("testvalue"); |
| if (found) break; |
| } |
| EXPECT_EQ(found, true); |
| auto* status = methods->GetRecvStatus(); |
| EXPECT_EQ(status->ok(), true); |
| } |
| if (methods->QueryInterceptionHookPoint( |
| experimental::InterceptionHookPoints::PRE_RECV_MESSAGE)) { |
| if (++count_ > 10) { |
| methods->FailHijackedRecvMessage(); |
| } |
| EchoResponse* resp = |
| static_cast<EchoResponse*>(methods->GetRecvMessage()); |
| resp->set_message("Hello"); |
| } |
| if (methods->QueryInterceptionHookPoint( |
| experimental::InterceptionHookPoints::POST_RECV_MESSAGE)) { |
| // Only the last message will be a failure |
| EXPECT_FALSE(got_failed_message_); |
| got_failed_message_ = methods->GetRecvMessage() == nullptr; |
| } |
| if (methods->QueryInterceptionHookPoint( |
| experimental::InterceptionHookPoints::PRE_RECV_STATUS)) { |
| auto* map = methods->GetRecvTrailingMetadata(); |
| // insert the metadata that we want |
| EXPECT_EQ(map->size(), static_cast<unsigned>(0)); |
| map->insert(std::make_pair("testkey", "testvalue")); |
| auto* status = methods->GetRecvStatus(); |
| *status = Status(StatusCode::OK, ""); |
| } |
| if (hijack) { |
| methods->Hijack(); |
| } else { |
| methods->Proceed(); |
| } |
| } |
| |
| static bool GotFailedMessage() { return got_failed_message_; } |
| |
| private: |
| experimental::ClientRpcInfo* info_; |
| static bool got_failed_message_; |
| int count_ = 0; |
| }; |
| |
| bool ServerStreamingRpcHijackingInterceptor::got_failed_message_ = false; |
| |
| class ServerStreamingRpcHijackingInterceptorFactory |
| : public experimental::ClientInterceptorFactoryInterface { |
| public: |
| virtual experimental::Interceptor* CreateClientInterceptor( |
| experimental::ClientRpcInfo* info) override { |
| return new ServerStreamingRpcHijackingInterceptor(info); |
| } |
| }; |
| |
| class BidiStreamingRpcHijackingInterceptorFactory |
| : public experimental::ClientInterceptorFactoryInterface { |
| public: |
| virtual experimental::Interceptor* CreateClientInterceptor( |
| experimental::ClientRpcInfo* info) override { |
| return new BidiStreamingRpcHijackingInterceptor(info); |
| } |
| }; |
| |
| // The logging interceptor is for testing purposes only. It is used to verify |
| // that all the appropriate hook points are invoked for an RPC. The counts are |
| // reset each time a new object of LoggingInterceptor is created, so only a |
| // single RPC should be made on the channel before calling the Verify methods. |
| class LoggingInterceptor : public experimental::Interceptor { |
| public: |
| LoggingInterceptor(experimental::ClientRpcInfo* /*info*/) { |
| pre_send_initial_metadata_ = false; |
| pre_send_message_count_ = 0; |
| pre_send_close_ = false; |
| post_recv_initial_metadata_ = false; |
| post_recv_message_count_ = 0; |
| post_recv_status_ = false; |
| } |
| |
| virtual void Intercept(experimental::InterceptorBatchMethods* methods) { |
| if (methods->QueryInterceptionHookPoint( |
| experimental::InterceptionHookPoints::PRE_SEND_INITIAL_METADATA)) { |
| auto* map = methods->GetSendInitialMetadata(); |
| // Check that we can see the test metadata |
| ASSERT_EQ(map->size(), static_cast<unsigned>(1)); |
| auto iterator = map->begin(); |
| EXPECT_EQ("testkey", iterator->first); |
| EXPECT_EQ("testvalue", iterator->second); |
| ASSERT_FALSE(pre_send_initial_metadata_); |
| pre_send_initial_metadata_ = true; |
| } |
| if (methods->QueryInterceptionHookPoint( |
| experimental::InterceptionHookPoints::PRE_SEND_MESSAGE)) { |
| EchoRequest req; |
| auto* send_msg = methods->GetSendMessage(); |
| if (send_msg == nullptr) { |
| // We did not get the non-serialized form of the message. Get the |
| // serialized form. |
| auto* buffer = methods->GetSerializedSendMessage(); |
| auto copied_buffer = *buffer; |
| EchoRequest req; |
| EXPECT_TRUE( |
| SerializationTraits<EchoRequest>::Deserialize(&copied_buffer, &req) |
| .ok()); |
| EXPECT_EQ(req.message(), "Hello"); |
| } else { |
| EXPECT_EQ( |
| static_cast<const EchoRequest*>(send_msg)->message().find("Hello"), |
| 0u); |
| } |
| auto* buffer = methods->GetSerializedSendMessage(); |
| auto copied_buffer = *buffer; |
| EXPECT_TRUE( |
| SerializationTraits<EchoRequest>::Deserialize(&copied_buffer, &req) |
| .ok()); |
| EXPECT_TRUE(req.message().find("Hello") == 0u); |
| pre_send_message_count_++; |
| } |
| if (methods->QueryInterceptionHookPoint( |
| experimental::InterceptionHookPoints::PRE_SEND_CLOSE)) { |
| // Got nothing to do here for now |
| pre_send_close_ = true; |
| } |
| if (methods->QueryInterceptionHookPoint( |
| experimental::InterceptionHookPoints::POST_RECV_INITIAL_METADATA)) { |
| auto* map = methods->GetRecvInitialMetadata(); |
| // Got nothing better to do here for now |
| EXPECT_EQ(map->size(), static_cast<unsigned>(0)); |
| post_recv_initial_metadata_ = true; |
| } |
| if (methods->QueryInterceptionHookPoint( |
| experimental::InterceptionHookPoints::POST_RECV_MESSAGE)) { |
| EchoResponse* resp = |
| static_cast<EchoResponse*>(methods->GetRecvMessage()); |
| if (resp != nullptr) { |
| EXPECT_TRUE(resp->message().find("Hello") == 0u); |
| post_recv_message_count_++; |
| } |
| } |
| if (methods->QueryInterceptionHookPoint( |
| experimental::InterceptionHookPoints::POST_RECV_STATUS)) { |
| auto* map = methods->GetRecvTrailingMetadata(); |
| bool found = false; |
| // Check that we received the metadata as an echo |
| for (const auto& pair : *map) { |
| found = pair.first.starts_with("testkey") && |
| pair.second.starts_with("testvalue"); |
| if (found) break; |
| } |
| EXPECT_EQ(found, true); |
| auto* status = methods->GetRecvStatus(); |
| EXPECT_EQ(status->ok(), true); |
| post_recv_status_ = true; |
| } |
| methods->Proceed(); |
| } |
| |
| static void VerifyCall(RPCType type) { |
| switch (type) { |
| case RPCType::kSyncUnary: |
| case RPCType::kAsyncCQUnary: |
| VerifyUnaryCall(); |
| break; |
| case RPCType::kSyncClientStreaming: |
| case RPCType::kAsyncCQClientStreaming: |
| VerifyClientStreamingCall(); |
| break; |
| case RPCType::kSyncServerStreaming: |
| case RPCType::kAsyncCQServerStreaming: |
| VerifyServerStreamingCall(); |
| break; |
| case RPCType::kSyncBidiStreaming: |
| case RPCType::kAsyncCQBidiStreaming: |
| VerifyBidiStreamingCall(); |
| break; |
| } |
| } |
| |
| static void VerifyCallCommon() { |
| EXPECT_TRUE(pre_send_initial_metadata_); |
| EXPECT_TRUE(pre_send_close_); |
| EXPECT_TRUE(post_recv_initial_metadata_); |
| EXPECT_TRUE(post_recv_status_); |
| } |
| |
| static void VerifyUnaryCall() { |
| VerifyCallCommon(); |
| EXPECT_EQ(pre_send_message_count_, 1); |
| EXPECT_EQ(post_recv_message_count_, 1); |
| } |
| |
| static void VerifyClientStreamingCall() { |
| VerifyCallCommon(); |
| EXPECT_EQ(pre_send_message_count_, kNumStreamingMessages); |
| EXPECT_EQ(post_recv_message_count_, 1); |
| } |
| |
| static void VerifyServerStreamingCall() { |
| VerifyCallCommon(); |
| EXPECT_EQ(pre_send_message_count_, 1); |
| EXPECT_EQ(post_recv_message_count_, kNumStreamingMessages); |
| } |
| |
| static void VerifyBidiStreamingCall() { |
| VerifyCallCommon(); |
| EXPECT_EQ(pre_send_message_count_, kNumStreamingMessages); |
| EXPECT_EQ(post_recv_message_count_, kNumStreamingMessages); |
| } |
| |
| private: |
| static bool pre_send_initial_metadata_; |
| static int pre_send_message_count_; |
| static bool pre_send_close_; |
| static bool post_recv_initial_metadata_; |
| static int post_recv_message_count_; |
| static bool post_recv_status_; |
| }; |
| |
| bool LoggingInterceptor::pre_send_initial_metadata_; |
| int LoggingInterceptor::pre_send_message_count_; |
| bool LoggingInterceptor::pre_send_close_; |
| bool LoggingInterceptor::post_recv_initial_metadata_; |
| int LoggingInterceptor::post_recv_message_count_; |
| bool LoggingInterceptor::post_recv_status_; |
| |
| class LoggingInterceptorFactory |
| : public experimental::ClientInterceptorFactoryInterface { |
| public: |
| virtual experimental::Interceptor* CreateClientInterceptor( |
| experimental::ClientRpcInfo* info) override { |
| return new LoggingInterceptor(info); |
| } |
| }; |
| |
| class TestScenario { |
| public: |
| explicit TestScenario(const RPCType& type) : type_(type) {} |
| |
| RPCType type() const { return type_; } |
| |
| private: |
| RPCType type_; |
| }; |
| |
| std::vector<TestScenario> CreateTestScenarios() { |
| std::vector<TestScenario> scenarios; |
| scenarios.emplace_back(RPCType::kSyncUnary); |
| scenarios.emplace_back(RPCType::kSyncClientStreaming); |
| scenarios.emplace_back(RPCType::kSyncServerStreaming); |
| scenarios.emplace_back(RPCType::kSyncBidiStreaming); |
| scenarios.emplace_back(RPCType::kAsyncCQUnary); |
| scenarios.emplace_back(RPCType::kAsyncCQServerStreaming); |
| return scenarios; |
| } |
| |
| class ParameterizedClientInterceptorsEnd2endTest |
| : public ::testing::TestWithParam<TestScenario> { |
| protected: |
| ParameterizedClientInterceptorsEnd2endTest() { |
| int port = grpc_pick_unused_port_or_die(); |
| |
| ServerBuilder builder; |
| server_address_ = "localhost:" + std::to_string(port); |
| builder.AddListeningPort(server_address_, InsecureServerCredentials()); |
| builder.RegisterService(&service_); |
| server_ = builder.BuildAndStart(); |
| } |
| |
| ~ParameterizedClientInterceptorsEnd2endTest() { server_->Shutdown(); } |
| |
| void SendRPC(const std::shared_ptr<Channel>& channel) { |
| switch (GetParam().type()) { |
| case RPCType::kSyncUnary: |
| MakeCall(channel); |
| break; |
| case RPCType::kSyncClientStreaming: |
| MakeClientStreamingCall(channel); |
| break; |
| case RPCType::kSyncServerStreaming: |
| MakeServerStreamingCall(channel); |
| break; |
| case RPCType::kSyncBidiStreaming: |
| MakeBidiStreamingCall(channel); |
| break; |
| case RPCType::kAsyncCQUnary: |
| MakeAsyncCQCall(channel); |
| break; |
| case RPCType::kAsyncCQClientStreaming: |
| // TODO(yashykt) : Fill this out |
| break; |
| case RPCType::kAsyncCQServerStreaming: |
| MakeAsyncCQServerStreamingCall(channel); |
| break; |
| case RPCType::kAsyncCQBidiStreaming: |
| // TODO(yashykt) : Fill this out |
| break; |
| } |
| } |
| |
| std::string server_address_; |
| EchoTestServiceStreamingImpl service_; |
| std::unique_ptr<Server> server_; |
| }; |
| |
| TEST_P(ParameterizedClientInterceptorsEnd2endTest, |
| ClientInterceptorLoggingTest) { |
| ChannelArguments args; |
| DummyInterceptor::Reset(); |
| std::vector<std::unique_ptr<experimental::ClientInterceptorFactoryInterface>> |
| creators; |
| creators.push_back(absl::make_unique<LoggingInterceptorFactory>()); |
| // Add 20 dummy interceptors |
| for (auto i = 0; i < 20; i++) { |
| creators.push_back(absl::make_unique<DummyInterceptorFactory>()); |
| } |
| auto channel = experimental::CreateCustomChannelWithInterceptors( |
| server_address_, InsecureChannelCredentials(), args, std::move(creators)); |
| SendRPC(channel); |
| LoggingInterceptor::VerifyCall(GetParam().type()); |
| // Make sure all 20 dummy interceptors were run |
| EXPECT_EQ(DummyInterceptor::GetNumTimesRun(), 20); |
| } |
| |
| INSTANTIATE_TEST_SUITE_P(ParameterizedClientInterceptorsEnd2end, |
| ParameterizedClientInterceptorsEnd2endTest, |
| ::testing::ValuesIn(CreateTestScenarios())); |
| |
| class ClientInterceptorsEnd2endTest |
| : public ::testing::TestWithParam<TestScenario> { |
| protected: |
| ClientInterceptorsEnd2endTest() { |
| int port = grpc_pick_unused_port_or_die(); |
| |
| ServerBuilder builder; |
| server_address_ = "localhost:" + std::to_string(port); |
| builder.AddListeningPort(server_address_, InsecureServerCredentials()); |
| builder.RegisterService(&service_); |
| server_ = builder.BuildAndStart(); |
| } |
| |
| ~ClientInterceptorsEnd2endTest() { server_->Shutdown(); } |
| |
| std::string server_address_; |
| TestServiceImpl service_; |
| std::unique_ptr<Server> server_; |
| }; |
| |
| TEST_F(ClientInterceptorsEnd2endTest, |
| LameChannelClientInterceptorHijackingTest) { |
| ChannelArguments args; |
| std::vector<std::unique_ptr<experimental::ClientInterceptorFactoryInterface>> |
| creators; |
| creators.push_back(absl::make_unique<HijackingInterceptorFactory>()); |
| auto channel = experimental::CreateCustomChannelWithInterceptors( |
| server_address_, nullptr, args, std::move(creators)); |
| MakeCall(channel); |
| } |
| |
| TEST_F(ClientInterceptorsEnd2endTest, ClientInterceptorHijackingTest) { |
| ChannelArguments args; |
| DummyInterceptor::Reset(); |
| std::vector<std::unique_ptr<experimental::ClientInterceptorFactoryInterface>> |
| creators; |
| // Add 20 dummy interceptors before hijacking interceptor |
| creators.reserve(20); |
| for (auto i = 0; i < 20; i++) { |
| creators.push_back(absl::make_unique<DummyInterceptorFactory>()); |
| } |
| creators.push_back(absl::make_unique<HijackingInterceptorFactory>()); |
| // Add 20 dummy interceptors after hijacking interceptor |
| for (auto i = 0; i < 20; i++) { |
| creators.push_back(absl::make_unique<DummyInterceptorFactory>()); |
| } |
| auto channel = experimental::CreateCustomChannelWithInterceptors( |
| server_address_, InsecureChannelCredentials(), args, std::move(creators)); |
| MakeCall(channel); |
| // Make sure only 20 dummy interceptors were run |
| EXPECT_EQ(DummyInterceptor::GetNumTimesRun(), 20); |
| } |
| |
| TEST_F(ClientInterceptorsEnd2endTest, ClientInterceptorLogThenHijackTest) { |
| ChannelArguments args; |
| std::vector<std::unique_ptr<experimental::ClientInterceptorFactoryInterface>> |
| creators; |
| creators.push_back(absl::make_unique<LoggingInterceptorFactory>()); |
| creators.push_back(absl::make_unique<HijackingInterceptorFactory>()); |
| auto channel = experimental::CreateCustomChannelWithInterceptors( |
| server_address_, InsecureChannelCredentials(), args, std::move(creators)); |
| MakeCall(channel); |
| LoggingInterceptor::VerifyUnaryCall(); |
| } |
| |
| TEST_F(ClientInterceptorsEnd2endTest, |
| ClientInterceptorHijackingMakesAnotherCallTest) { |
| ChannelArguments args; |
| DummyInterceptor::Reset(); |
| std::vector<std::unique_ptr<experimental::ClientInterceptorFactoryInterface>> |
| creators; |
| // Add 5 dummy interceptors before hijacking interceptor |
| creators.reserve(5); |
| for (auto i = 0; i < 5; i++) { |
| creators.push_back(absl::make_unique<DummyInterceptorFactory>()); |
| } |
| creators.push_back( |
| std::unique_ptr<experimental::ClientInterceptorFactoryInterface>( |
| new HijackingInterceptorMakesAnotherCallFactory())); |
| // Add 7 dummy interceptors after hijacking interceptor |
| for (auto i = 0; i < 7; i++) { |
| creators.push_back(absl::make_unique<DummyInterceptorFactory>()); |
| } |
| auto channel = server_->experimental().InProcessChannelWithInterceptors( |
| args, std::move(creators)); |
| |
| MakeCall(channel); |
| // Make sure all interceptors were run once, since the hijacking interceptor |
| // makes an RPC on the intercepted channel |
| EXPECT_EQ(DummyInterceptor::GetNumTimesRun(), 12); |
| } |
| |
| class ClientInterceptorsCallbackEnd2endTest : public ::testing::Test { |
| protected: |
| ClientInterceptorsCallbackEnd2endTest() { |
| int port = grpc_pick_unused_port_or_die(); |
| |
| ServerBuilder builder; |
| server_address_ = "localhost:" + std::to_string(port); |
| builder.AddListeningPort(server_address_, InsecureServerCredentials()); |
| builder.RegisterService(&service_); |
| server_ = builder.BuildAndStart(); |
| } |
| |
| ~ClientInterceptorsCallbackEnd2endTest() { server_->Shutdown(); } |
| |
| std::string server_address_; |
| TestServiceImpl service_; |
| std::unique_ptr<Server> server_; |
| }; |
| |
| TEST_F(ClientInterceptorsCallbackEnd2endTest, |
| ClientInterceptorLoggingTestWithCallback) { |
| ChannelArguments args; |
| DummyInterceptor::Reset(); |
| std::vector<std::unique_ptr<experimental::ClientInterceptorFactoryInterface>> |
| creators; |
| creators.push_back(absl::make_unique<LoggingInterceptorFactory>()); |
| // Add 20 dummy interceptors |
| for (auto i = 0; i < 20; i++) { |
| creators.push_back(absl::make_unique<DummyInterceptorFactory>()); |
| } |
| auto channel = server_->experimental().InProcessChannelWithInterceptors( |
| args, std::move(creators)); |
| MakeCallbackCall(channel); |
| LoggingInterceptor::VerifyUnaryCall(); |
| // Make sure all 20 dummy interceptors were run |
| EXPECT_EQ(DummyInterceptor::GetNumTimesRun(), 20); |
| } |
| |
| TEST_F(ClientInterceptorsCallbackEnd2endTest, |
| ClientInterceptorFactoryAllowsNullptrReturn) { |
| ChannelArguments args; |
| DummyInterceptor::Reset(); |
| std::vector<std::unique_ptr<experimental::ClientInterceptorFactoryInterface>> |
| creators; |
| creators.push_back(absl::make_unique<LoggingInterceptorFactory>()); |
| // Add 20 dummy interceptors and 20 null interceptors |
| for (auto i = 0; i < 20; i++) { |
| creators.push_back(absl::make_unique<DummyInterceptorFactory>()); |
| creators.push_back(absl::make_unique<NullInterceptorFactory>()); |
| } |
| auto channel = server_->experimental().InProcessChannelWithInterceptors( |
| args, std::move(creators)); |
| MakeCallbackCall(channel); |
| LoggingInterceptor::VerifyUnaryCall(); |
| // Make sure all 20 dummy interceptors were run |
| EXPECT_EQ(DummyInterceptor::GetNumTimesRun(), 20); |
| } |
| |
| class ClientInterceptorsStreamingEnd2endTest : public ::testing::Test { |
| protected: |
| ClientInterceptorsStreamingEnd2endTest() { |
| int port = grpc_pick_unused_port_or_die(); |
| |
| ServerBuilder builder; |
| server_address_ = "localhost:" + std::to_string(port); |
| builder.AddListeningPort(server_address_, InsecureServerCredentials()); |
| builder.RegisterService(&service_); |
| server_ = builder.BuildAndStart(); |
| } |
| |
| ~ClientInterceptorsStreamingEnd2endTest() { server_->Shutdown(); } |
| |
| std::string server_address_; |
| EchoTestServiceStreamingImpl service_; |
| std::unique_ptr<Server> server_; |
| }; |
| |
| TEST_F(ClientInterceptorsStreamingEnd2endTest, ClientStreamingTest) { |
| ChannelArguments args; |
| DummyInterceptor::Reset(); |
| std::vector<std::unique_ptr<experimental::ClientInterceptorFactoryInterface>> |
| creators; |
| creators.push_back(absl::make_unique<LoggingInterceptorFactory>()); |
| // Add 20 dummy interceptors |
| for (auto i = 0; i < 20; i++) { |
| creators.push_back(absl::make_unique<DummyInterceptorFactory>()); |
| } |
| auto channel = experimental::CreateCustomChannelWithInterceptors( |
| server_address_, InsecureChannelCredentials(), args, std::move(creators)); |
| MakeClientStreamingCall(channel); |
| LoggingInterceptor::VerifyClientStreamingCall(); |
| // Make sure all 20 dummy interceptors were run |
| EXPECT_EQ(DummyInterceptor::GetNumTimesRun(), 20); |
| } |
| |
| TEST_F(ClientInterceptorsStreamingEnd2endTest, ServerStreamingTest) { |
| ChannelArguments args; |
| DummyInterceptor::Reset(); |
| std::vector<std::unique_ptr<experimental::ClientInterceptorFactoryInterface>> |
| creators; |
| creators.push_back(absl::make_unique<LoggingInterceptorFactory>()); |
| // Add 20 dummy interceptors |
| for (auto i = 0; i < 20; i++) { |
| creators.push_back(absl::make_unique<DummyInterceptorFactory>()); |
| } |
| auto channel = experimental::CreateCustomChannelWithInterceptors( |
| server_address_, InsecureChannelCredentials(), args, std::move(creators)); |
| MakeServerStreamingCall(channel); |
| LoggingInterceptor::VerifyServerStreamingCall(); |
| // Make sure all 20 dummy interceptors were run |
| EXPECT_EQ(DummyInterceptor::GetNumTimesRun(), 20); |
| } |
| |
| TEST_F(ClientInterceptorsStreamingEnd2endTest, ClientStreamingHijackingTest) { |
| ChannelArguments args; |
| std::vector<std::unique_ptr<experimental::ClientInterceptorFactoryInterface>> |
| creators; |
| creators.push_back( |
| absl::make_unique<ClientStreamingRpcHijackingInterceptorFactory>()); |
| auto channel = experimental::CreateCustomChannelWithInterceptors( |
| server_address_, InsecureChannelCredentials(), args, std::move(creators)); |
| |
| auto stub = grpc::testing::EchoTestService::NewStub(channel); |
| ClientContext ctx; |
| EchoRequest req; |
| EchoResponse resp; |
| req.mutable_param()->set_echo_metadata(true); |
| req.set_message("Hello"); |
| string expected_resp = ""; |
| auto writer = stub->RequestStream(&ctx, &resp); |
| for (int i = 0; i < 10; i++) { |
| EXPECT_TRUE(writer->Write(req)); |
| expected_resp += "Hello"; |
| } |
| // The interceptor will reject the 11th message |
| writer->Write(req); |
| Status s = writer->Finish(); |
| EXPECT_EQ(s.ok(), false); |
| EXPECT_TRUE(ClientStreamingRpcHijackingInterceptor::GotFailedSend()); |
| } |
| |
| TEST_F(ClientInterceptorsStreamingEnd2endTest, ServerStreamingHijackingTest) { |
| ChannelArguments args; |
| DummyInterceptor::Reset(); |
| std::vector<std::unique_ptr<experimental::ClientInterceptorFactoryInterface>> |
| creators; |
| creators.push_back( |
| absl::make_unique<ServerStreamingRpcHijackingInterceptorFactory>()); |
| auto channel = experimental::CreateCustomChannelWithInterceptors( |
| server_address_, InsecureChannelCredentials(), args, std::move(creators)); |
| MakeServerStreamingCall(channel); |
| EXPECT_TRUE(ServerStreamingRpcHijackingInterceptor::GotFailedMessage()); |
| } |
| |
| TEST_F(ClientInterceptorsStreamingEnd2endTest, |
| AsyncCQServerStreamingHijackingTest) { |
| ChannelArguments args; |
| DummyInterceptor::Reset(); |
| std::vector<std::unique_ptr<experimental::ClientInterceptorFactoryInterface>> |
| creators; |
| creators.push_back( |
| absl::make_unique<ServerStreamingRpcHijackingInterceptorFactory>()); |
| auto channel = experimental::CreateCustomChannelWithInterceptors( |
| server_address_, InsecureChannelCredentials(), args, std::move(creators)); |
| MakeAsyncCQServerStreamingCall(channel); |
| EXPECT_TRUE(ServerStreamingRpcHijackingInterceptor::GotFailedMessage()); |
| } |
| |
| TEST_F(ClientInterceptorsStreamingEnd2endTest, BidiStreamingHijackingTest) { |
| ChannelArguments args; |
| DummyInterceptor::Reset(); |
| std::vector<std::unique_ptr<experimental::ClientInterceptorFactoryInterface>> |
| creators; |
| creators.push_back( |
| absl::make_unique<BidiStreamingRpcHijackingInterceptorFactory>()); |
| auto channel = experimental::CreateCustomChannelWithInterceptors( |
| server_address_, InsecureChannelCredentials(), args, std::move(creators)); |
| MakeBidiStreamingCall(channel); |
| } |
| |
| TEST_F(ClientInterceptorsStreamingEnd2endTest, BidiStreamingTest) { |
| ChannelArguments args; |
| DummyInterceptor::Reset(); |
| std::vector<std::unique_ptr<experimental::ClientInterceptorFactoryInterface>> |
| creators; |
| creators.push_back(absl::make_unique<LoggingInterceptorFactory>()); |
| // Add 20 dummy interceptors |
| for (auto i = 0; i < 20; i++) { |
| creators.push_back(absl::make_unique<DummyInterceptorFactory>()); |
| } |
| auto channel = experimental::CreateCustomChannelWithInterceptors( |
| server_address_, InsecureChannelCredentials(), args, std::move(creators)); |
| MakeBidiStreamingCall(channel); |
| LoggingInterceptor::VerifyBidiStreamingCall(); |
| // Make sure all 20 dummy interceptors were run |
| EXPECT_EQ(DummyInterceptor::GetNumTimesRun(), 20); |
| } |
| |
| class ClientGlobalInterceptorEnd2endTest : public ::testing::Test { |
| protected: |
| ClientGlobalInterceptorEnd2endTest() { |
| int port = grpc_pick_unused_port_or_die(); |
| |
| ServerBuilder builder; |
| server_address_ = "localhost:" + std::to_string(port); |
| builder.AddListeningPort(server_address_, InsecureServerCredentials()); |
| builder.RegisterService(&service_); |
| server_ = builder.BuildAndStart(); |
| } |
| |
| ~ClientGlobalInterceptorEnd2endTest() { server_->Shutdown(); } |
| |
| std::string server_address_; |
| TestServiceImpl service_; |
| std::unique_ptr<Server> server_; |
| }; |
| |
| TEST_F(ClientGlobalInterceptorEnd2endTest, DummyGlobalInterceptor) { |
| // We should ideally be registering a global interceptor only once per |
| // process, but for the purposes of testing, it should be fine to modify the |
| // registered global interceptor when there are no ongoing gRPC operations |
| DummyInterceptorFactory global_factory; |
| experimental::RegisterGlobalClientInterceptorFactory(&global_factory); |
| ChannelArguments args; |
| DummyInterceptor::Reset(); |
| std::vector<std::unique_ptr<experimental::ClientInterceptorFactoryInterface>> |
| creators; |
| // Add 20 dummy interceptors |
| creators.reserve(20); |
| for (auto i = 0; i < 20; i++) { |
| creators.push_back(absl::make_unique<DummyInterceptorFactory>()); |
| } |
| auto channel = experimental::CreateCustomChannelWithInterceptors( |
| server_address_, InsecureChannelCredentials(), args, std::move(creators)); |
| MakeCall(channel); |
| // Make sure all 20 dummy interceptors were run with the global interceptor |
| EXPECT_EQ(DummyInterceptor::GetNumTimesRun(), 21); |
| experimental::TestOnlyResetGlobalClientInterceptorFactory(); |
| } |
| |
| TEST_F(ClientGlobalInterceptorEnd2endTest, LoggingGlobalInterceptor) { |
| // We should ideally be registering a global interceptor only once per |
| // process, but for the purposes of testing, it should be fine to modify the |
| // registered global interceptor when there are no ongoing gRPC operations |
| LoggingInterceptorFactory global_factory; |
| experimental::RegisterGlobalClientInterceptorFactory(&global_factory); |
| ChannelArguments args; |
| DummyInterceptor::Reset(); |
| std::vector<std::unique_ptr<experimental::ClientInterceptorFactoryInterface>> |
| creators; |
| // Add 20 dummy interceptors |
| creators.reserve(20); |
| for (auto i = 0; i < 20; i++) { |
| creators.push_back(absl::make_unique<DummyInterceptorFactory>()); |
| } |
| auto channel = experimental::CreateCustomChannelWithInterceptors( |
| server_address_, InsecureChannelCredentials(), args, std::move(creators)); |
| MakeCall(channel); |
| LoggingInterceptor::VerifyUnaryCall(); |
| // Make sure all 20 dummy interceptors were run |
| EXPECT_EQ(DummyInterceptor::GetNumTimesRun(), 20); |
| experimental::TestOnlyResetGlobalClientInterceptorFactory(); |
| } |
| |
| TEST_F(ClientGlobalInterceptorEnd2endTest, HijackingGlobalInterceptor) { |
| // We should ideally be registering a global interceptor only once per |
| // process, but for the purposes of testing, it should be fine to modify the |
| // registered global interceptor when there are no ongoing gRPC operations |
| HijackingInterceptorFactory global_factory; |
| experimental::RegisterGlobalClientInterceptorFactory(&global_factory); |
| ChannelArguments args; |
| DummyInterceptor::Reset(); |
| std::vector<std::unique_ptr<experimental::ClientInterceptorFactoryInterface>> |
| creators; |
| // Add 20 dummy interceptors |
| creators.reserve(20); |
| for (auto i = 0; i < 20; i++) { |
| creators.push_back(absl::make_unique<DummyInterceptorFactory>()); |
| } |
| auto channel = experimental::CreateCustomChannelWithInterceptors( |
| server_address_, InsecureChannelCredentials(), args, std::move(creators)); |
| MakeCall(channel); |
| // Make sure all 20 dummy interceptors were run |
| EXPECT_EQ(DummyInterceptor::GetNumTimesRun(), 20); |
| experimental::TestOnlyResetGlobalClientInterceptorFactory(); |
| } |
| |
| } // namespace |
| } // namespace testing |
| } // namespace grpc |
| |
| int main(int argc, char** argv) { |
| grpc::testing::TestEnvironment env(argc, argv); |
| ::testing::InitGoogleTest(&argc, argv); |
| return RUN_ALL_TESTS(); |
| } |