xref: /aosp_15_r20/external/grpc-grpc/test/cpp/end2end/channelz_service_test.cc (revision cc02d7e222339f7a4f6ba5f422e6413f4bd931f2)
1 //
2 //
3 // Copyright 2018 gRPC authors.
4 //
5 // Licensed under the Apache License, Version 2.0 (the "License");
6 // you may not use this file except in compliance with the License.
7 // You may obtain a copy of the License at
8 //
9 //     http://www.apache.org/licenses/LICENSE-2.0
10 //
11 // Unless required by applicable law or agreed to in writing, software
12 // distributed under the License is distributed on an "AS IS" BASIS,
13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 // See the License for the specific language governing permissions and
15 // limitations under the License.
16 //
17 //
18 
19 #include <gmock/gmock.h>
20 #include <gtest/gtest.h>
21 
22 #include "absl/memory/memory.h"
23 
24 #include <grpc/grpc.h>
25 #include <grpc/grpc_security.h>
26 #include <grpc/support/port_platform.h>
27 #include <grpcpp/channel.h>
28 #include <grpcpp/client_context.h>
29 #include <grpcpp/create_channel.h>
30 #include <grpcpp/ext/channelz_service_plugin.h>
31 #include <grpcpp/security/credentials.h>
32 #include <grpcpp/security/server_credentials.h>
33 #include <grpcpp/server.h>
34 #include <grpcpp/server_builder.h>
35 #include <grpcpp/server_context.h>
36 
37 #include "src/core/lib/event_engine/default_event_engine.h"
38 #include "src/core/lib/gprpp/env.h"
39 #include "src/core/lib/security/credentials/tls/grpc_tls_certificate_provider.h"
40 #include "src/core/lib/security/security_connector/ssl_utils.h"
41 #include "src/core/lib/slice/slice_internal.h"
42 #include "src/cpp/client/secure_credentials.h"
43 #include "src/proto/grpc/channelz/channelz.grpc.pb.h"
44 #include "src/proto/grpc/testing/echo.grpc.pb.h"
45 #include "test/core/event_engine/event_engine_test_utils.h"
46 #include "test/core/util/port.h"
47 #include "test/core/util/resolve_localhost_ip46.h"
48 #include "test/core/util/test_config.h"
49 #include "test/core/util/tls_utils.h"
50 #include "test/cpp/end2end/test_service_impl.h"
51 #include "test/cpp/util/test_credentials_provider.h"
52 
53 using grpc::channelz::v1::Address;
54 using grpc::channelz::v1::GetChannelRequest;
55 using grpc::channelz::v1::GetChannelResponse;
56 using grpc::channelz::v1::GetServerRequest;
57 using grpc::channelz::v1::GetServerResponse;
58 using grpc::channelz::v1::GetServerSocketsRequest;
59 using grpc::channelz::v1::GetServerSocketsResponse;
60 using grpc::channelz::v1::GetServersRequest;
61 using grpc::channelz::v1::GetServersResponse;
62 using grpc::channelz::v1::GetSocketRequest;
63 using grpc::channelz::v1::GetSocketResponse;
64 using grpc::channelz::v1::GetSubchannelRequest;
65 using grpc::channelz::v1::GetSubchannelResponse;
66 using grpc::channelz::v1::GetTopChannelsRequest;
67 using grpc::channelz::v1::GetTopChannelsResponse;
68 using grpc_core::testing::GetFileContents;
69 
70 namespace grpc {
71 namespace testing {
72 namespace {
73 
ValidateAddress(const Address & address)74 bool ValidateAddress(const Address& address) {
75   if (address.address_case() != Address::kTcpipAddress) {
76     return true;
77   }
78   return address.tcpip_address().ip_address().size() == 4 ||
79          address.tcpip_address().ip_address().size() == 16;
80 }
81 
82 // Proxy service supports N backends. Sends RPC to backend dictated by
83 // request->backend_channel_idx().
84 class Proxy : public grpc::testing::EchoTestService::Service {
85  public:
Proxy()86   Proxy() {}
87 
AddChannelToBackend(const std::shared_ptr<Channel> & channel)88   void AddChannelToBackend(const std::shared_ptr<Channel>& channel) {
89     stubs_.push_back(grpc::testing::EchoTestService::NewStub(channel));
90   }
91 
Echo(ServerContext * server_context,const EchoRequest * request,EchoResponse * response)92   Status Echo(ServerContext* server_context, const EchoRequest* request,
93               EchoResponse* response) override {
94     std::unique_ptr<ClientContext> client_context =
95         ClientContext::FromServerContext(*server_context);
96     size_t idx = request->param().backend_channel_idx();
97     GPR_ASSERT(idx < stubs_.size());
98     return stubs_[idx]->Echo(client_context.get(), *request, response);
99   }
100 
BidiStream(ServerContext * server_context,ServerReaderWriter<EchoResponse,EchoRequest> * stream_from_client)101   Status BidiStream(ServerContext* server_context,
102                     ServerReaderWriter<EchoResponse, EchoRequest>*
103                         stream_from_client) override {
104     EchoRequest request;
105     EchoResponse response;
106     std::unique_ptr<ClientContext> client_context =
107         ClientContext::FromServerContext(*server_context);
108 
109     // always use the first proxy for streaming
110     auto stream_to_backend = stubs_[0]->BidiStream(client_context.get());
111     while (stream_from_client->Read(&request)) {
112       stream_to_backend->Write(request);
113       stream_to_backend->Read(&response);
114       stream_from_client->Write(response);
115     }
116 
117     stream_to_backend->WritesDone();
118     return stream_to_backend->Finish();
119   }
120 
121  private:
122   std::vector<std::unique_ptr<grpc::testing::EchoTestService::Stub>> stubs_;
123 };
124 
125 enum class CredentialsType {
126   kInsecure = 0,
127   kTls = 1,
128   kMtls = 2,
129 };
130 
131 constexpr char kCaCertPath[] = "src/core/tsi/test_creds/ca.pem";
132 constexpr char kServerCertPath[] = "src/core/tsi/test_creds/server1.pem";
133 constexpr char kServerKeyPath[] = "src/core/tsi/test_creds/server1.key";
134 constexpr char kClientCertPath[] = "src/core/tsi/test_creds/client.pem";
135 constexpr char kClientKeyPath[] = "src/core/tsi/test_creds/client.key";
136 
GetChannelCredentials(CredentialsType type,ChannelArguments * args)137 std::shared_ptr<grpc::ChannelCredentials> GetChannelCredentials(
138     CredentialsType type, ChannelArguments* args) {
139   if (type == CredentialsType::kInsecure) {
140     return InsecureChannelCredentials();
141   }
142   args->SetSslTargetNameOverride("foo.test.google.fr");
143   std::vector<experimental::IdentityKeyCertPair> identity_key_cert_pairs = {
144       {GetFileContents(kClientKeyPath), GetFileContents(kClientCertPath)}};
145   grpc::experimental::TlsChannelCredentialsOptions options;
146   options.set_certificate_provider(
147       std::make_shared<grpc::experimental::StaticDataCertificateProvider>(
148           GetFileContents(kCaCertPath), identity_key_cert_pairs));
149   if (type == CredentialsType::kMtls) {
150     options.watch_identity_key_cert_pairs();
151   }
152   options.watch_root_certs();
153   return grpc::experimental::TlsCredentials(options);
154 }
155 
GetServerCredentials(CredentialsType type)156 std::shared_ptr<grpc::ServerCredentials> GetServerCredentials(
157     CredentialsType type) {
158   if (type == CredentialsType::kInsecure) {
159     return InsecureServerCredentials();
160   }
161   std::vector<experimental::IdentityKeyCertPair> identity_key_cert_pairs = {
162       {GetFileContents(kServerKeyPath), GetFileContents(kServerCertPath)}};
163   auto certificate_provider =
164       std::make_shared<grpc::experimental::StaticDataCertificateProvider>(
165           GetFileContents(kCaCertPath), identity_key_cert_pairs);
166   grpc::experimental::TlsServerCredentialsOptions options(certificate_provider);
167   options.watch_root_certs();
168   options.watch_identity_key_cert_pairs();
169   options.set_cert_request_type(GRPC_SSL_REQUEST_CLIENT_CERTIFICATE_AND_VERIFY);
170   return grpc::experimental::TlsServerCredentials(options);
171 }
172 
RemoveWhitespaces(std::string input)173 std::string RemoveWhitespaces(std::string input) {
174   input.erase(remove_if(input.begin(), input.end(), isspace), input.end());
175   return input;
176 }
177 
178 class ChannelzServerTest : public ::testing::TestWithParam<CredentialsType> {
179  public:
ChannelzServerTest()180   ChannelzServerTest() {}
SetUpTestSuite()181   static void SetUpTestSuite() {
182 #if TARGET_OS_IPHONE
183     // Workaround Apple CFStream bug
184     grpc_core::SetEnv("grpc_cfstream", "0");
185 #endif
186   }
SetUp()187   void SetUp() override {
188     grpc_init();
189 
190     // ensure channel server is brought up on all severs we build.
191     grpc::channelz::experimental::InitChannelzService();
192 
193     // We set up a proxy server with channelz enabled.
194     proxy_port_ = grpc_pick_unused_port_or_die();
195     ServerBuilder proxy_builder;
196     std::string proxy_server_address = grpc_core::LocalIpAndPort(proxy_port_);
197     proxy_builder.AddListeningPort(proxy_server_address,
198                                    GetServerCredentials(GetParam()));
199     // forces channelz and channel tracing to be enabled.
200     proxy_builder.AddChannelArgument(GRPC_ARG_ENABLE_CHANNELZ, 1);
201     proxy_builder.AddChannelArgument(
202         GRPC_ARG_MAX_CHANNEL_TRACE_EVENT_MEMORY_PER_NODE, 1024);
203     proxy_service_ = std::make_unique<Proxy>();
204     proxy_builder.RegisterService(proxy_service_.get());
205     proxy_server_ = proxy_builder.BuildAndStart();
206   }
207 
TearDown()208   void TearDown() override {
209     for (auto& backend : backends_) {
210       backend.server->Shutdown(grpc_timeout_milliseconds_to_deadline(0));
211     }
212     proxy_server_->Shutdown(grpc_timeout_milliseconds_to_deadline(0));
213     grpc_shutdown();
214     proxy_server_.reset();
215     echo_stub_.reset();
216     channelz_stub_.reset();
217     backends_.clear();
218     proxy_service_.reset();
219     // Ensure all pending callbacks are handled before finishing the test
220     // to ensure hygene between test cases.
221     // (requires any grpc-object-holding values be cleared out first).
222     grpc_event_engine::experimental::WaitForSingleOwner(
223         grpc_event_engine::experimental::GetDefaultEventEngine());
224   }
225 
226   // Sets the proxy up to have an arbitrary number of backends.
ConfigureProxy(size_t num_backends)227   void ConfigureProxy(size_t num_backends) {
228     backends_.resize(num_backends);
229     for (size_t i = 0; i < num_backends; ++i) {
230       // create a new backend.
231       backends_[i].port = grpc_pick_unused_port_or_die();
232       ServerBuilder backend_builder;
233       std::string backend_server_address =
234           grpc_core::LocalIpAndPort(backends_[i].port);
235       backend_builder.AddListeningPort(backend_server_address,
236                                        GetServerCredentials(GetParam()));
237       backends_[i].service = std::make_unique<TestServiceImpl>();
238       // ensure that the backend itself has channelz disabled.
239       backend_builder.AddChannelArgument(GRPC_ARG_ENABLE_CHANNELZ, 0);
240       backend_builder.RegisterService(backends_[i].service.get());
241       backends_[i].server = backend_builder.BuildAndStart();
242       // set up a channel to the backend. We ensure that this channel has
243       // channelz enabled since these channels (proxy outbound to backends)
244       // are the ones that our test will actually be validating.
245       ChannelArguments args;
246       args.SetInt(GRPC_ARG_ENABLE_CHANNELZ, 1);
247       args.SetInt(GRPC_ARG_MAX_CHANNEL_TRACE_EVENT_MEMORY_PER_NODE, 1024);
248       std::shared_ptr<Channel> channel_to_backend = grpc::CreateCustomChannel(
249           backend_server_address, GetChannelCredentials(GetParam(), &args),
250           args);
251       proxy_service_->AddChannelToBackend(channel_to_backend);
252     }
253   }
254 
ResetStubs()255   void ResetStubs() {
256     string target =
257         absl::StrCat("dns:", grpc_core::LocalIp(), ":", proxy_port_);
258     ChannelArguments args;
259     // disable channelz. We only want to focus on proxy to backend outbound.
260     args.SetInt(GRPC_ARG_ENABLE_CHANNELZ, 0);
261     std::shared_ptr<Channel> channel = grpc::CreateCustomChannel(
262         target, GetChannelCredentials(GetParam(), &args), args);
263     channelz_stub_ = grpc::channelz::v1::Channelz::NewStub(channel);
264     echo_stub_ = grpc::testing::EchoTestService::NewStub(channel);
265   }
266 
NewEchoStub()267   std::unique_ptr<grpc::testing::EchoTestService::Stub> NewEchoStub() {
268     string target =
269         absl::StrCat("dns:", grpc_core::LocalIp(), ":", proxy_port_);
270     ChannelArguments args;
271     // disable channelz. We only want to focus on proxy to backend outbound.
272     args.SetInt(GRPC_ARG_ENABLE_CHANNELZ, 0);
273     // This ensures that gRPC will not do connection sharing.
274     args.SetInt(GRPC_ARG_USE_LOCAL_SUBCHANNEL_POOL, true);
275     std::shared_ptr<Channel> channel = grpc::CreateCustomChannel(
276         target, GetChannelCredentials(GetParam(), &args), args);
277     return grpc::testing::EchoTestService::NewStub(channel);
278   }
279 
SendSuccessfulEcho(int channel_idx)280   void SendSuccessfulEcho(int channel_idx) {
281     EchoRequest request;
282     EchoResponse response;
283     request.set_message("Hello channelz");
284     request.mutable_param()->set_backend_channel_idx(channel_idx);
285     ClientContext context;
286     Status s = echo_stub_->Echo(&context, request, &response);
287     EXPECT_TRUE(s.ok()) << "s.error_message() = " << s.error_message();
288     if (s.ok()) EXPECT_EQ(response.message(), request.message());
289   }
290 
SendSuccessfulStream(int num_messages)291   void SendSuccessfulStream(int num_messages) {
292     EchoRequest request;
293     EchoResponse response;
294     request.set_message("Hello channelz");
295     ClientContext context;
296     auto stream_to_proxy = echo_stub_->BidiStream(&context);
297     for (int i = 0; i < num_messages; ++i) {
298       EXPECT_TRUE(stream_to_proxy->Write(request));
299       EXPECT_TRUE(stream_to_proxy->Read(&response));
300     }
301     stream_to_proxy->WritesDone();
302     Status s = stream_to_proxy->Finish();
303     EXPECT_TRUE(s.ok()) << "s.error_message() = " << s.error_message();
304   }
305 
SendFailedEcho(int channel_idx)306   void SendFailedEcho(int channel_idx) {
307     EchoRequest request;
308     EchoResponse response;
309     request.set_message("Hello channelz");
310     request.mutable_param()->set_backend_channel_idx(channel_idx);
311     auto* error = request.mutable_param()->mutable_expected_error();
312     error->set_code(13);  // INTERNAL
313     error->set_error_message("error");
314     ClientContext context;
315     Status s = echo_stub_->Echo(&context, request, &response);
316     EXPECT_FALSE(s.ok());
317   }
318 
319   // Uses GetTopChannels to return the channel_id of a particular channel,
320   // so that the unit tests may test GetChannel call.
GetChannelId(int channel_idx)321   intptr_t GetChannelId(int channel_idx) {
322     GetTopChannelsRequest request;
323     GetTopChannelsResponse response;
324     request.set_start_channel_id(0);
325     ClientContext context;
326     Status s = channelz_stub_->GetTopChannels(&context, request, &response);
327     EXPECT_TRUE(s.ok()) << "s.error_message() = " << s.error_message();
328     EXPECT_GT(response.channel_size(), channel_idx);
329     return response.channel(channel_idx).ref().channel_id();
330   }
331 
to_string(const int number)332   static string to_string(const int number) {
333     std::stringstream strs;
334     strs << number;
335     return strs.str();
336   }
337 
338  protected:
339   // package of data needed for each backend server.
340   struct BackendData {
341     std::unique_ptr<Server> server;
342     int port;
343     std::unique_ptr<TestServiceImpl> service;
344   };
345 
346   std::unique_ptr<grpc::channelz::v1::Channelz::Stub> channelz_stub_;
347   std::unique_ptr<grpc::testing::EchoTestService::Stub> echo_stub_;
348 
349   // proxy server to ping with channelz requests.
350   std::unique_ptr<Server> proxy_server_;
351   int proxy_port_;
352   std::unique_ptr<Proxy> proxy_service_;
353 
354   // backends. All implement the echo service.
355   std::vector<BackendData> backends_;
356 };
357 
TEST_P(ChannelzServerTest,BasicTest)358 TEST_P(ChannelzServerTest, BasicTest) {
359   ResetStubs();
360   ConfigureProxy(1);
361   GetTopChannelsRequest request;
362   GetTopChannelsResponse response;
363   request.set_start_channel_id(0);
364   ClientContext context;
365   Status s = channelz_stub_->GetTopChannels(&context, request, &response);
366   EXPECT_TRUE(s.ok()) << "s.error_message() = " << s.error_message();
367   EXPECT_EQ(response.channel_size(), 1);
368 }
369 
TEST_P(ChannelzServerTest,HighStartId)370 TEST_P(ChannelzServerTest, HighStartId) {
371   ResetStubs();
372   ConfigureProxy(1);
373   GetTopChannelsRequest request;
374   GetTopChannelsResponse response;
375   request.set_start_channel_id(10000);
376   ClientContext context;
377   Status s = channelz_stub_->GetTopChannels(&context, request, &response);
378   EXPECT_TRUE(s.ok()) << "s.error_message() = " << s.error_message();
379   EXPECT_EQ(response.channel_size(), 0);
380 }
381 
TEST_P(ChannelzServerTest,SuccessfulRequestTest)382 TEST_P(ChannelzServerTest, SuccessfulRequestTest) {
383   ResetStubs();
384   ConfigureProxy(1);
385   SendSuccessfulEcho(0);
386   GetChannelRequest request;
387   GetChannelResponse response;
388   request.set_channel_id(GetChannelId(0));
389   ClientContext context;
390   Status s = channelz_stub_->GetChannel(&context, request, &response);
391   EXPECT_TRUE(s.ok()) << "s.error_message() = " << s.error_message();
392   EXPECT_EQ(response.channel().data().calls_started(), 1);
393   EXPECT_EQ(response.channel().data().calls_succeeded(), 1);
394   EXPECT_EQ(response.channel().data().calls_failed(), 0);
395 }
396 
TEST_P(ChannelzServerTest,FailedRequestTest)397 TEST_P(ChannelzServerTest, FailedRequestTest) {
398   ResetStubs();
399   ConfigureProxy(1);
400   SendFailedEcho(0);
401   GetChannelRequest request;
402   GetChannelResponse response;
403   request.set_channel_id(GetChannelId(0));
404   ClientContext context;
405   Status s = channelz_stub_->GetChannel(&context, request, &response);
406   EXPECT_TRUE(s.ok()) << "s.error_message() = " << s.error_message();
407   EXPECT_EQ(response.channel().data().calls_started(), 1);
408   EXPECT_EQ(response.channel().data().calls_succeeded(), 0);
409   EXPECT_EQ(response.channel().data().calls_failed(), 1);
410 }
411 
TEST_P(ChannelzServerTest,ManyRequestsTest)412 TEST_P(ChannelzServerTest, ManyRequestsTest) {
413   ResetStubs();
414   ConfigureProxy(1);
415   // send some RPCs
416   const int kNumSuccess = 10;
417   const int kNumFailed = 11;
418   for (int i = 0; i < kNumSuccess; ++i) {
419     SendSuccessfulEcho(0);
420   }
421   for (int i = 0; i < kNumFailed; ++i) {
422     SendFailedEcho(0);
423   }
424   GetChannelRequest request;
425   GetChannelResponse response;
426   request.set_channel_id(GetChannelId(0));
427   ClientContext context;
428   Status s = channelz_stub_->GetChannel(&context, request, &response);
429   EXPECT_TRUE(s.ok()) << "s.error_message() = " << s.error_message();
430   EXPECT_EQ(response.channel().data().calls_started(),
431             kNumSuccess + kNumFailed);
432   EXPECT_EQ(response.channel().data().calls_succeeded(), kNumSuccess);
433   EXPECT_EQ(response.channel().data().calls_failed(), kNumFailed);
434 }
435 
TEST_P(ChannelzServerTest,ManyChannels)436 TEST_P(ChannelzServerTest, ManyChannels) {
437   ResetStubs();
438   const int kNumChannels = 4;
439   ConfigureProxy(kNumChannels);
440   GetTopChannelsRequest request;
441   GetTopChannelsResponse response;
442   request.set_start_channel_id(0);
443   ClientContext context;
444   Status s = channelz_stub_->GetTopChannels(&context, request, &response);
445   EXPECT_TRUE(s.ok()) << "s.error_message() = " << s.error_message();
446   EXPECT_EQ(response.channel_size(), kNumChannels);
447 }
448 
TEST_P(ChannelzServerTest,ManyRequestsManyChannels)449 TEST_P(ChannelzServerTest, ManyRequestsManyChannels) {
450   ResetStubs();
451   const int kNumChannels = 4;
452   ConfigureProxy(kNumChannels);
453   const int kNumSuccess = 10;
454   const int kNumFailed = 11;
455   for (int i = 0; i < kNumSuccess; ++i) {
456     SendSuccessfulEcho(0);
457     SendSuccessfulEcho(2);
458   }
459   for (int i = 0; i < kNumFailed; ++i) {
460     SendFailedEcho(1);
461     SendFailedEcho(2);
462   }
463 
464   // the first channel saw only successes
465   {
466     GetChannelRequest request;
467     GetChannelResponse response;
468     request.set_channel_id(GetChannelId(0));
469     ClientContext context;
470     Status s = channelz_stub_->GetChannel(&context, request, &response);
471     EXPECT_TRUE(s.ok()) << "s.error_message() = " << s.error_message();
472     EXPECT_EQ(response.channel().data().calls_started(), kNumSuccess);
473     EXPECT_EQ(response.channel().data().calls_succeeded(), kNumSuccess);
474     EXPECT_EQ(response.channel().data().calls_failed(), 0);
475   }
476 
477   // the second channel saw only failures
478   {
479     GetChannelRequest request;
480     GetChannelResponse response;
481     request.set_channel_id(GetChannelId(1));
482     ClientContext context;
483     Status s = channelz_stub_->GetChannel(&context, request, &response);
484     EXPECT_TRUE(s.ok()) << "s.error_message() = " << s.error_message();
485     EXPECT_EQ(response.channel().data().calls_started(), kNumFailed);
486     EXPECT_EQ(response.channel().data().calls_succeeded(), 0);
487     EXPECT_EQ(response.channel().data().calls_failed(), kNumFailed);
488   }
489 
490   // the third channel saw both
491   {
492     GetChannelRequest request;
493     GetChannelResponse response;
494     request.set_channel_id(GetChannelId(2));
495     ClientContext context;
496     Status s = channelz_stub_->GetChannel(&context, request, &response);
497     EXPECT_TRUE(s.ok()) << "s.error_message() = " << s.error_message();
498     EXPECT_EQ(response.channel().data().calls_started(),
499               kNumSuccess + kNumFailed);
500     EXPECT_EQ(response.channel().data().calls_succeeded(), kNumSuccess);
501     EXPECT_EQ(response.channel().data().calls_failed(), kNumFailed);
502   }
503 
504   // the fourth channel saw nothing
505   {
506     GetChannelRequest request;
507     GetChannelResponse response;
508     request.set_channel_id(GetChannelId(3));
509     ClientContext context;
510     Status s = channelz_stub_->GetChannel(&context, request, &response);
511     EXPECT_TRUE(s.ok()) << "s.error_message() = " << s.error_message();
512     EXPECT_EQ(response.channel().data().calls_started(), 0);
513     EXPECT_EQ(response.channel().data().calls_succeeded(), 0);
514     EXPECT_EQ(response.channel().data().calls_failed(), 0);
515   }
516 }
517 
TEST_P(ChannelzServerTest,ManySubchannels)518 TEST_P(ChannelzServerTest, ManySubchannels) {
519   ResetStubs();
520   const int kNumChannels = 4;
521   ConfigureProxy(kNumChannels);
522   const int kNumSuccess = 10;
523   const int kNumFailed = 11;
524   for (int i = 0; i < kNumSuccess; ++i) {
525     SendSuccessfulEcho(0);
526     SendSuccessfulEcho(2);
527   }
528   for (int i = 0; i < kNumFailed; ++i) {
529     SendFailedEcho(1);
530     SendFailedEcho(2);
531   }
532   GetTopChannelsRequest gtc_request;
533   GetTopChannelsResponse gtc_response;
534   gtc_request.set_start_channel_id(0);
535   ClientContext context;
536   Status s =
537       channelz_stub_->GetTopChannels(&context, gtc_request, &gtc_response);
538   EXPECT_TRUE(s.ok()) << s.error_message();
539   EXPECT_EQ(gtc_response.channel_size(), kNumChannels);
540   for (int i = 0; i < gtc_response.channel_size(); ++i) {
541     // if the channel sent no RPCs, then expect no subchannels to have been
542     // created.
543     if (gtc_response.channel(i).data().calls_started() == 0) {
544       EXPECT_EQ(gtc_response.channel(i).subchannel_ref_size(), 0);
545       continue;
546     }
547     // The resolver must return at least one address.
548     ASSERT_GT(gtc_response.channel(i).subchannel_ref_size(), 0);
549     GetSubchannelRequest gsc_request;
550     GetSubchannelResponse gsc_response;
551     gsc_request.set_subchannel_id(
552         gtc_response.channel(i).subchannel_ref(0).subchannel_id());
553     ClientContext context;
554     Status s =
555         channelz_stub_->GetSubchannel(&context, gsc_request, &gsc_response);
556     EXPECT_TRUE(s.ok()) << s.error_message();
557     EXPECT_EQ(gtc_response.channel(i).data().calls_started(),
558               gsc_response.subchannel().data().calls_started());
559     EXPECT_EQ(gtc_response.channel(i).data().calls_succeeded(),
560               gsc_response.subchannel().data().calls_succeeded());
561     EXPECT_EQ(gtc_response.channel(i).data().calls_failed(),
562               gsc_response.subchannel().data().calls_failed());
563   }
564 }
565 
TEST_P(ChannelzServerTest,BasicServerTest)566 TEST_P(ChannelzServerTest, BasicServerTest) {
567   ResetStubs();
568   ConfigureProxy(1);
569   GetServersRequest request;
570   GetServersResponse response;
571   request.set_start_server_id(0);
572   ClientContext context;
573   Status s = channelz_stub_->GetServers(&context, request, &response);
574   EXPECT_TRUE(s.ok()) << "s.error_message() = " << s.error_message();
575   EXPECT_EQ(response.server_size(), 1);
576 }
577 
TEST_P(ChannelzServerTest,BasicGetServerTest)578 TEST_P(ChannelzServerTest, BasicGetServerTest) {
579   ResetStubs();
580   ConfigureProxy(1);
581   GetServersRequest get_servers_request;
582   GetServersResponse get_servers_response;
583   get_servers_request.set_start_server_id(0);
584   ClientContext get_servers_context;
585   Status s = channelz_stub_->GetServers(
586       &get_servers_context, get_servers_request, &get_servers_response);
587   EXPECT_TRUE(s.ok()) << "s.error_message() = " << s.error_message();
588   EXPECT_EQ(get_servers_response.server_size(), 1);
589   GetServerRequest get_server_request;
590   GetServerResponse get_server_response;
591   get_server_request.set_server_id(
592       get_servers_response.server(0).ref().server_id());
593   ClientContext get_server_context;
594   s = channelz_stub_->GetServer(&get_server_context, get_server_request,
595                                 &get_server_response);
596   EXPECT_TRUE(s.ok()) << "s.error_message() = " << s.error_message();
597   EXPECT_EQ(get_servers_response.server(0).ref().server_id(),
598             get_server_response.server().ref().server_id());
599 }
600 
TEST_P(ChannelzServerTest,ServerCallTest)601 TEST_P(ChannelzServerTest, ServerCallTest) {
602   ResetStubs();
603   ConfigureProxy(1);
604   const int kNumSuccess = 10;
605   const int kNumFailed = 11;
606   for (int i = 0; i < kNumSuccess; ++i) {
607     SendSuccessfulEcho(0);
608   }
609   for (int i = 0; i < kNumFailed; ++i) {
610     SendFailedEcho(0);
611   }
612   GetServersRequest request;
613   GetServersResponse response;
614   request.set_start_server_id(0);
615   ClientContext context;
616   Status s = channelz_stub_->GetServers(&context, request, &response);
617   EXPECT_TRUE(s.ok()) << "s.error_message() = " << s.error_message();
618   EXPECT_EQ(response.server_size(), 1);
619   EXPECT_EQ(response.server(0).data().calls_succeeded(), kNumSuccess);
620   EXPECT_EQ(response.server(0).data().calls_failed(), kNumFailed);
621   // This is success+failure+1 because the call that retrieved this information
622   // will be counted as started. It will not track success/failure until after
623   // it has returned, so that is not included in the response.
624   EXPECT_EQ(response.server(0).data().calls_started(),
625             kNumSuccess + kNumFailed + 1);
626 }
627 
TEST_P(ChannelzServerTest,ManySubchannelsAndSockets)628 TEST_P(ChannelzServerTest, ManySubchannelsAndSockets) {
629   ResetStubs();
630   const int kNumChannels = 4;
631   ConfigureProxy(kNumChannels);
632   const int kNumSuccess = 10;
633   const int kNumFailed = 11;
634   for (int i = 0; i < kNumSuccess; ++i) {
635     SendSuccessfulEcho(0);
636     SendSuccessfulEcho(2);
637   }
638   for (int i = 0; i < kNumFailed; ++i) {
639     SendFailedEcho(1);
640     SendFailedEcho(2);
641   }
642   GetTopChannelsRequest gtc_request;
643   GetTopChannelsResponse gtc_response;
644   gtc_request.set_start_channel_id(0);
645   ClientContext context;
646   Status s =
647       channelz_stub_->GetTopChannels(&context, gtc_request, &gtc_response);
648   EXPECT_TRUE(s.ok()) << s.error_message();
649   EXPECT_EQ(gtc_response.channel_size(), kNumChannels);
650   for (int i = 0; i < gtc_response.channel_size(); ++i) {
651     // if the channel sent no RPCs, then expect no subchannels to have been
652     // created.
653     if (gtc_response.channel(i).data().calls_started() == 0) {
654       EXPECT_EQ(gtc_response.channel(i).subchannel_ref_size(), 0);
655       continue;
656     }
657     // The resolver must return at least one address.
658     ASSERT_GT(gtc_response.channel(i).subchannel_ref_size(), 0);
659     // First grab the subchannel
660     GetSubchannelRequest get_subchannel_req;
661     GetSubchannelResponse get_subchannel_resp;
662     get_subchannel_req.set_subchannel_id(
663         gtc_response.channel(i).subchannel_ref(0).subchannel_id());
664     ClientContext get_subchannel_ctx;
665     Status s = channelz_stub_->GetSubchannel(
666         &get_subchannel_ctx, get_subchannel_req, &get_subchannel_resp);
667     EXPECT_TRUE(s.ok()) << s.error_message();
668     EXPECT_EQ(get_subchannel_resp.subchannel().socket_ref_size(), 1);
669     // Now grab the socket.
670     GetSocketRequest get_socket_req;
671     GetSocketResponse get_socket_resp;
672     ClientContext get_socket_ctx;
673     get_socket_req.set_socket_id(
674         get_subchannel_resp.subchannel().socket_ref(0).socket_id());
675     s = channelz_stub_->GetSocket(&get_socket_ctx, get_socket_req,
676                                   &get_socket_resp);
677     EXPECT_TRUE(
678         get_subchannel_resp.subchannel().socket_ref(0).name().find("http"));
679     EXPECT_TRUE(s.ok()) << s.error_message();
680     // calls started == streams started AND stream succeeded. Since none of
681     // these RPCs were canceled, all of the streams will succeeded even though
682     // the RPCs they represent might have failed.
683     EXPECT_EQ(get_subchannel_resp.subchannel().data().calls_started(),
684               get_socket_resp.socket().data().streams_started());
685     EXPECT_EQ(get_subchannel_resp.subchannel().data().calls_started(),
686               get_socket_resp.socket().data().streams_succeeded());
687     // All of the calls were unary, so calls started == messages sent.
688     EXPECT_EQ(get_subchannel_resp.subchannel().data().calls_started(),
689               get_socket_resp.socket().data().messages_sent());
690     // We only get responses when the RPC was successful, so
691     // calls succeeded == messages received.
692     EXPECT_EQ(get_subchannel_resp.subchannel().data().calls_succeeded(),
693               get_socket_resp.socket().data().messages_received());
694     switch (GetParam()) {
695       case CredentialsType::kInsecure:
696         EXPECT_FALSE(get_socket_resp.socket().has_security());
697         break;
698       case CredentialsType::kTls:
699       case CredentialsType::kMtls:
700         EXPECT_TRUE(get_socket_resp.socket().has_security());
701         EXPECT_TRUE(get_socket_resp.socket().security().has_tls());
702         EXPECT_EQ(
703             RemoveWhitespaces(
704                 get_socket_resp.socket().security().tls().remote_certificate()),
705             RemoveWhitespaces(GetFileContents(kServerCertPath)));
706         break;
707     }
708   }
709 }
710 
TEST_P(ChannelzServerTest,StreamingRPC)711 TEST_P(ChannelzServerTest, StreamingRPC) {
712   ResetStubs();
713   ConfigureProxy(1);
714   const int kNumMessages = 5;
715   SendSuccessfulStream(kNumMessages);
716   // Get the channel
717   GetChannelRequest get_channel_request;
718   GetChannelResponse get_channel_response;
719   get_channel_request.set_channel_id(GetChannelId(0));
720   ClientContext get_channel_context;
721   Status s = channelz_stub_->GetChannel(
722       &get_channel_context, get_channel_request, &get_channel_response);
723   EXPECT_TRUE(s.ok()) << "s.error_message() = " << s.error_message();
724   EXPECT_EQ(get_channel_response.channel().data().calls_started(), 1);
725   EXPECT_EQ(get_channel_response.channel().data().calls_succeeded(), 1);
726   EXPECT_EQ(get_channel_response.channel().data().calls_failed(), 0);
727   // Get the subchannel
728   ASSERT_GT(get_channel_response.channel().subchannel_ref_size(), 0);
729   GetSubchannelRequest get_subchannel_request;
730   GetSubchannelResponse get_subchannel_response;
731   ClientContext get_subchannel_context;
732   get_subchannel_request.set_subchannel_id(
733       get_channel_response.channel().subchannel_ref(0).subchannel_id());
734   s = channelz_stub_->GetSubchannel(&get_subchannel_context,
735                                     get_subchannel_request,
736                                     &get_subchannel_response);
737   EXPECT_TRUE(s.ok()) << "s.error_message() = " << s.error_message();
738   EXPECT_EQ(get_subchannel_response.subchannel().data().calls_started(), 1);
739   EXPECT_EQ(get_subchannel_response.subchannel().data().calls_succeeded(), 1);
740   EXPECT_EQ(get_subchannel_response.subchannel().data().calls_failed(), 0);
741   // Get the socket
742   ASSERT_GT(get_subchannel_response.subchannel().socket_ref_size(), 0);
743   GetSocketRequest get_socket_request;
744   GetSocketResponse get_socket_response;
745   ClientContext get_socket_context;
746   get_socket_request.set_socket_id(
747       get_subchannel_response.subchannel().socket_ref(0).socket_id());
748   EXPECT_TRUE(
749       get_subchannel_response.subchannel().socket_ref(0).name().find("http"));
750   s = channelz_stub_->GetSocket(&get_socket_context, get_socket_request,
751                                 &get_socket_response);
752   EXPECT_TRUE(s.ok()) << "s.error_message() = " << s.error_message();
753   EXPECT_EQ(get_socket_response.socket().data().streams_started(), 1);
754   EXPECT_EQ(get_socket_response.socket().data().streams_succeeded(), 1);
755   EXPECT_EQ(get_socket_response.socket().data().streams_failed(), 0);
756   EXPECT_EQ(get_socket_response.socket().data().messages_sent(), kNumMessages);
757   EXPECT_EQ(get_socket_response.socket().data().messages_received(),
758             kNumMessages);
759   switch (GetParam()) {
760     case CredentialsType::kInsecure:
761       EXPECT_FALSE(get_socket_response.socket().has_security());
762       break;
763     case CredentialsType::kTls:
764     case CredentialsType::kMtls:
765       EXPECT_TRUE(get_socket_response.socket().has_security());
766       EXPECT_TRUE(get_socket_response.socket().security().has_tls());
767       EXPECT_EQ(RemoveWhitespaces(get_socket_response.socket()
768                                       .security()
769                                       .tls()
770                                       .remote_certificate()),
771                 RemoveWhitespaces(GetFileContents(kServerCertPath)));
772       break;
773   }
774 }
775 
TEST_P(ChannelzServerTest,GetServerSocketsTest)776 TEST_P(ChannelzServerTest, GetServerSocketsTest) {
777   ResetStubs();
778   ConfigureProxy(1);
779   GetServersRequest get_server_request;
780   GetServersResponse get_server_response;
781   get_server_request.set_start_server_id(0);
782   ClientContext get_server_context;
783   Status s = channelz_stub_->GetServers(&get_server_context, get_server_request,
784                                         &get_server_response);
785   EXPECT_TRUE(s.ok()) << "s.error_message() = " << s.error_message();
786   EXPECT_EQ(get_server_response.server_size(), 1);
787   GetServerSocketsRequest get_server_sockets_request;
788   GetServerSocketsResponse get_server_sockets_response;
789   get_server_sockets_request.set_server_id(
790       get_server_response.server(0).ref().server_id());
791   get_server_sockets_request.set_start_socket_id(0);
792   ClientContext get_server_sockets_context;
793   s = channelz_stub_->GetServerSockets(&get_server_sockets_context,
794                                        get_server_sockets_request,
795                                        &get_server_sockets_response);
796   EXPECT_TRUE(s.ok()) << "s.error_message() = " << s.error_message();
797   EXPECT_EQ(get_server_sockets_response.socket_ref_size(), 1);
798   EXPECT_TRUE(get_server_sockets_response.socket_ref(0).name().find("http"));
799   // Get the socket to verify security information.
800   GetSocketRequest get_socket_request;
801   GetSocketResponse get_socket_response;
802   ClientContext get_socket_context;
803   get_socket_request.set_socket_id(
804       get_server_sockets_response.socket_ref(0).socket_id());
805   s = channelz_stub_->GetSocket(&get_socket_context, get_socket_request,
806                                 &get_socket_response);
807   EXPECT_TRUE(s.ok()) << "s.error_message() = " << s.error_message();
808   EXPECT_TRUE(ValidateAddress(get_socket_response.socket().remote()));
809   EXPECT_TRUE(ValidateAddress(get_socket_response.socket().local()));
810   switch (GetParam()) {
811     case CredentialsType::kInsecure:
812       EXPECT_FALSE(get_socket_response.socket().has_security());
813       break;
814     case CredentialsType::kTls:
815     case CredentialsType::kMtls:
816       EXPECT_TRUE(get_socket_response.socket().has_security());
817       EXPECT_TRUE(get_socket_response.socket().security().has_tls());
818       if (GetParam() == CredentialsType::kMtls) {
819         EXPECT_EQ(RemoveWhitespaces(get_socket_response.socket()
820                                         .security()
821                                         .tls()
822                                         .remote_certificate()),
823                   RemoveWhitespaces(GetFileContents(kClientCertPath)));
824       } else {
825         EXPECT_TRUE(get_socket_response.socket()
826                         .security()
827                         .tls()
828                         .remote_certificate()
829                         .empty());
830       }
831       break;
832   }
833 }
834 
TEST_P(ChannelzServerTest,GetServerSocketsPaginationTest)835 TEST_P(ChannelzServerTest, GetServerSocketsPaginationTest) {
836   ResetStubs();
837   ConfigureProxy(1);
838   std::vector<std::unique_ptr<grpc::testing::EchoTestService::Stub>> stubs;
839   const int kNumServerSocketsCreated = 20;
840   for (int i = 0; i < kNumServerSocketsCreated; ++i) {
841     stubs.push_back(NewEchoStub());
842     EchoRequest request;
843     EchoResponse response;
844     request.set_message("Hello channelz");
845     request.mutable_param()->set_backend_channel_idx(0);
846     ClientContext context;
847     Status s = stubs.back()->Echo(&context, request, &response);
848     EXPECT_TRUE(s.ok()) << "s.error_message() = " << s.error_message();
849     if (s.ok()) EXPECT_EQ(response.message(), request.message());
850   }
851   GetServersRequest get_server_request;
852   GetServersResponse get_server_response;
853   get_server_request.set_start_server_id(0);
854   ClientContext get_server_context;
855   Status s = channelz_stub_->GetServers(&get_server_context, get_server_request,
856                                         &get_server_response);
857   EXPECT_TRUE(s.ok()) << "s.error_message() = " << s.error_message();
858   EXPECT_EQ(get_server_response.server_size(), 1);
859   // Make a request that gets all of the serversockets
860   {
861     GetServerSocketsRequest get_server_sockets_request;
862     GetServerSocketsResponse get_server_sockets_response;
863     get_server_sockets_request.set_server_id(
864         get_server_response.server(0).ref().server_id());
865     get_server_sockets_request.set_start_socket_id(0);
866     ClientContext get_server_sockets_context;
867     s = channelz_stub_->GetServerSockets(&get_server_sockets_context,
868                                          get_server_sockets_request,
869                                          &get_server_sockets_response);
870     EXPECT_TRUE(s.ok()) << "s.error_message() = " << s.error_message();
871     // We add one to account the channelz stub that will end up creating
872     // a serversocket.
873     EXPECT_EQ(get_server_sockets_response.socket_ref_size(),
874               kNumServerSocketsCreated + 1);
875     EXPECT_TRUE(get_server_sockets_response.end());
876   }
877   // Now we make a request that exercises pagination.
878   {
879     GetServerSocketsRequest get_server_sockets_request;
880     GetServerSocketsResponse get_server_sockets_response;
881     get_server_sockets_request.set_server_id(
882         get_server_response.server(0).ref().server_id());
883     get_server_sockets_request.set_start_socket_id(0);
884     const int kMaxResults = 10;
885     get_server_sockets_request.set_max_results(kMaxResults);
886     ClientContext get_server_sockets_context;
887     s = channelz_stub_->GetServerSockets(&get_server_sockets_context,
888                                          get_server_sockets_request,
889                                          &get_server_sockets_response);
890     EXPECT_TRUE(s.ok()) << "s.error_message() = " << s.error_message();
891     EXPECT_EQ(get_server_sockets_response.socket_ref_size(), kMaxResults);
892     EXPECT_FALSE(get_server_sockets_response.end());
893   }
894 }
895 
TEST_P(ChannelzServerTest,GetServerListenSocketsTest)896 TEST_P(ChannelzServerTest, GetServerListenSocketsTest) {
897   ResetStubs();
898   ConfigureProxy(1);
899   GetServersRequest get_server_request;
900   GetServersResponse get_server_response;
901   get_server_request.set_start_server_id(0);
902   ClientContext get_server_context;
903   Status s = channelz_stub_->GetServers(&get_server_context, get_server_request,
904                                         &get_server_response);
905   EXPECT_TRUE(s.ok()) << "s.error_message() = " << s.error_message();
906   EXPECT_EQ(get_server_response.server_size(), 1);
907   // The resolver might return one or two addresses depending on the
908   // configuration, one for ipv4 and one for ipv6.
909   int listen_socket_size = get_server_response.server(0).listen_socket_size();
910   EXPECT_THAT(listen_socket_size, ::testing::AnyOf(1, 2));
911   GetSocketRequest get_socket_request;
912   GetSocketResponse get_socket_response;
913   get_socket_request.set_socket_id(
914       get_server_response.server(0).listen_socket(0).socket_id());
915   EXPECT_TRUE(
916       get_server_response.server(0).listen_socket(0).name().find("http"));
917   ClientContext get_socket_context_1;
918   s = channelz_stub_->GetSocket(&get_socket_context_1, get_socket_request,
919                                 &get_socket_response);
920   EXPECT_TRUE(s.ok()) << "s.error_message() = " << s.error_message();
921 
922   EXPECT_TRUE(ValidateAddress(get_socket_response.socket().remote()));
923   EXPECT_TRUE(ValidateAddress(get_socket_response.socket().local()));
924   if (listen_socket_size == 2) {
925     get_socket_request.set_socket_id(
926         get_server_response.server(0).listen_socket(1).socket_id());
927     ClientContext get_socket_context_2;
928     EXPECT_TRUE(
929         get_server_response.server(0).listen_socket(1).name().find("http"));
930     s = channelz_stub_->GetSocket(&get_socket_context_2, get_socket_request,
931                                   &get_socket_response);
932     EXPECT_TRUE(s.ok()) << "s.error_message() = " << s.error_message();
933   }
934 }
935 
936 INSTANTIATE_TEST_SUITE_P(ChannelzServer, ChannelzServerTest,
937                          ::testing::ValuesIn(std::vector<CredentialsType>(
938                              {CredentialsType::kInsecure, CredentialsType::kTls,
939                               CredentialsType::kMtls})));
940 
941 }  // namespace
942 }  // namespace testing
943 }  // namespace grpc
944 
main(int argc,char ** argv)945 int main(int argc, char** argv) {
946   grpc::testing::TestEnvironment env(&argc, argv);
947   ::testing::InitGoogleTest(&argc, argv);
948   return RUN_ALL_TESTS();
949 }
950