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