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 <grpc/support/port_platform.h>
20
21 #include <grpc/grpc.h>
22 #include <grpcpp/channel.h>
23 #include <grpcpp/client_context.h>
24 #include <grpcpp/create_channel.h>
25 #include <grpcpp/security/credentials.h>
26 #include <grpcpp/security/server_credentials.h>
27 #include <grpcpp/server.h>
28 #include <grpcpp/server_builder.h>
29 #include <grpcpp/server_context.h>
30
31 #include <grpcpp/ext/channelz_service_plugin.h>
32 #include "src/core/lib/gpr/env.h"
33 #include "src/proto/grpc/channelz/channelz.grpc.pb.h"
34 #include "src/proto/grpc/testing/echo.grpc.pb.h"
35 #include "test/core/util/port.h"
36 #include "test/core/util/test_config.h"
37 #include "test/cpp/end2end/test_service_impl.h"
38
39 #include <gtest/gtest.h>
40
41 using grpc::channelz::v1::GetChannelRequest;
42 using grpc::channelz::v1::GetChannelResponse;
43 using grpc::channelz::v1::GetServerRequest;
44 using grpc::channelz::v1::GetServerResponse;
45 using grpc::channelz::v1::GetServerSocketsRequest;
46 using grpc::channelz::v1::GetServerSocketsResponse;
47 using grpc::channelz::v1::GetServersRequest;
48 using grpc::channelz::v1::GetServersResponse;
49 using grpc::channelz::v1::GetSocketRequest;
50 using grpc::channelz::v1::GetSocketResponse;
51 using grpc::channelz::v1::GetSubchannelRequest;
52 using grpc::channelz::v1::GetSubchannelResponse;
53 using grpc::channelz::v1::GetTopChannelsRequest;
54 using grpc::channelz::v1::GetTopChannelsResponse;
55
56 namespace grpc {
57 namespace testing {
58 namespace {
59
60 // Proxy service supports N backends. Sends RPC to backend dictated by
61 // request->backend_channel_idx().
62 class Proxy : public ::grpc::testing::EchoTestService::Service {
63 public:
Proxy()64 Proxy() {}
65
AddChannelToBackend(const std::shared_ptr<Channel> & channel)66 void AddChannelToBackend(const std::shared_ptr<Channel>& channel) {
67 stubs_.push_back(grpc::testing::EchoTestService::NewStub(channel));
68 }
69
Echo(ServerContext * server_context,const EchoRequest * request,EchoResponse * response)70 Status Echo(ServerContext* server_context, const EchoRequest* request,
71 EchoResponse* response) override {
72 std::unique_ptr<ClientContext> client_context =
73 ClientContext::FromServerContext(*server_context);
74 size_t idx = request->param().backend_channel_idx();
75 GPR_ASSERT(idx < stubs_.size());
76 return stubs_[idx]->Echo(client_context.get(), *request, response);
77 }
78
BidiStream(ServerContext * server_context,ServerReaderWriter<EchoResponse,EchoRequest> * stream_from_client)79 Status BidiStream(ServerContext* server_context,
80 ServerReaderWriter<EchoResponse, EchoRequest>*
81 stream_from_client) override {
82 EchoRequest request;
83 EchoResponse response;
84 std::unique_ptr<ClientContext> client_context =
85 ClientContext::FromServerContext(*server_context);
86
87 // always use the first proxy for streaming
88 auto stream_to_backend = stubs_[0]->BidiStream(client_context.get());
89 while (stream_from_client->Read(&request)) {
90 stream_to_backend->Write(request);
91 stream_to_backend->Read(&response);
92 stream_from_client->Write(response);
93 }
94
95 stream_to_backend->WritesDone();
96 return stream_to_backend->Finish();
97 }
98
99 private:
100 std::vector<std::unique_ptr<::grpc::testing::EchoTestService::Stub>> stubs_;
101 };
102
103 } // namespace
104
105 class ChannelzServerTest : public ::testing::Test {
106 public:
ChannelzServerTest()107 ChannelzServerTest() {}
SetUpTestCase()108 static void SetUpTestCase() {
109 #if TARGET_OS_IPHONE
110 // Workaround Apple CFStream bug
111 gpr_setenv("grpc_cfstream", "0");
112 #endif
113 }
SetUp()114 void SetUp() override {
115 // ensure channel server is brought up on all severs we build.
116 ::grpc::channelz::experimental::InitChannelzService();
117
118 // We set up a proxy server with channelz enabled.
119 proxy_port_ = grpc_pick_unused_port_or_die();
120 ServerBuilder proxy_builder;
121 std::string proxy_server_address = "localhost:" + to_string(proxy_port_);
122 proxy_builder.AddListeningPort(proxy_server_address,
123 InsecureServerCredentials());
124 // forces channelz and channel tracing to be enabled.
125 proxy_builder.AddChannelArgument(GRPC_ARG_ENABLE_CHANNELZ, 1);
126 proxy_builder.AddChannelArgument(
127 GRPC_ARG_MAX_CHANNEL_TRACE_EVENT_MEMORY_PER_NODE, 1024);
128 proxy_builder.RegisterService(&proxy_service_);
129 proxy_server_ = proxy_builder.BuildAndStart();
130 }
131
132 // Sets the proxy up to have an arbitrary number of backends.
ConfigureProxy(size_t num_backends)133 void ConfigureProxy(size_t num_backends) {
134 backends_.resize(num_backends);
135 for (size_t i = 0; i < num_backends; ++i) {
136 // create a new backend.
137 backends_[i].port = grpc_pick_unused_port_or_die();
138 ServerBuilder backend_builder;
139 std::string backend_server_address =
140 "localhost:" + to_string(backends_[i].port);
141 backend_builder.AddListeningPort(backend_server_address,
142 InsecureServerCredentials());
143 backends_[i].service.reset(new TestServiceImpl);
144 // ensure that the backend itself has channelz disabled.
145 backend_builder.AddChannelArgument(GRPC_ARG_ENABLE_CHANNELZ, 0);
146 backend_builder.RegisterService(backends_[i].service.get());
147 backends_[i].server = backend_builder.BuildAndStart();
148 // set up a channel to the backend. We ensure that this channel has
149 // channelz enabled since these channels (proxy outbound to backends)
150 // are the ones that our test will actually be validating.
151 ChannelArguments args;
152 args.SetInt(GRPC_ARG_ENABLE_CHANNELZ, 1);
153 args.SetInt(GRPC_ARG_MAX_CHANNEL_TRACE_EVENT_MEMORY_PER_NODE, 1024);
154 std::shared_ptr<Channel> channel_to_backend = ::grpc::CreateCustomChannel(
155 backend_server_address, InsecureChannelCredentials(), args);
156 proxy_service_.AddChannelToBackend(channel_to_backend);
157 }
158 }
159
ResetStubs()160 void ResetStubs() {
161 string target = "dns:localhost:" + to_string(proxy_port_);
162 ChannelArguments args;
163 // disable channelz. We only want to focus on proxy to backend outbound.
164 args.SetInt(GRPC_ARG_ENABLE_CHANNELZ, 0);
165 std::shared_ptr<Channel> channel =
166 ::grpc::CreateCustomChannel(target, InsecureChannelCredentials(), args);
167 channelz_stub_ = grpc::channelz::v1::Channelz::NewStub(channel);
168 echo_stub_ = grpc::testing::EchoTestService::NewStub(channel);
169 }
170
NewEchoStub()171 std::unique_ptr<grpc::testing::EchoTestService::Stub> NewEchoStub() {
172 string target = "dns:localhost:" + to_string(proxy_port_);
173 ChannelArguments args;
174 // disable channelz. We only want to focus on proxy to backend outbound.
175 args.SetInt(GRPC_ARG_ENABLE_CHANNELZ, 0);
176 // This ensures that gRPC will not do connection sharing.
177 args.SetInt(GRPC_ARG_USE_LOCAL_SUBCHANNEL_POOL, true);
178 std::shared_ptr<Channel> channel =
179 ::grpc::CreateCustomChannel(target, InsecureChannelCredentials(), args);
180 return grpc::testing::EchoTestService::NewStub(channel);
181 }
182
SendSuccessfulEcho(int channel_idx)183 void SendSuccessfulEcho(int channel_idx) {
184 EchoRequest request;
185 EchoResponse response;
186 request.set_message("Hello channelz");
187 request.mutable_param()->set_backend_channel_idx(channel_idx);
188 ClientContext context;
189 Status s = echo_stub_->Echo(&context, request, &response);
190 EXPECT_EQ(response.message(), request.message());
191 EXPECT_TRUE(s.ok()) << "s.error_message() = " << s.error_message();
192 }
193
SendSuccessfulStream(int num_messages)194 void SendSuccessfulStream(int num_messages) {
195 EchoRequest request;
196 EchoResponse response;
197 request.set_message("Hello channelz");
198 ClientContext context;
199 auto stream_to_proxy = echo_stub_->BidiStream(&context);
200 for (int i = 0; i < num_messages; ++i) {
201 EXPECT_TRUE(stream_to_proxy->Write(request));
202 EXPECT_TRUE(stream_to_proxy->Read(&response));
203 }
204 stream_to_proxy->WritesDone();
205 Status s = stream_to_proxy->Finish();
206 EXPECT_TRUE(s.ok()) << "s.error_message() = " << s.error_message();
207 }
208
SendFailedEcho(int channel_idx)209 void SendFailedEcho(int channel_idx) {
210 EchoRequest request;
211 EchoResponse response;
212 request.set_message("Hello channelz");
213 request.mutable_param()->set_backend_channel_idx(channel_idx);
214 auto* error = request.mutable_param()->mutable_expected_error();
215 error->set_code(13); // INTERNAL
216 error->set_error_message("error");
217 ClientContext context;
218 Status s = echo_stub_->Echo(&context, request, &response);
219 EXPECT_FALSE(s.ok());
220 }
221
222 // Uses GetTopChannels to return the channel_id of a particular channel,
223 // so that the unit tests may test GetChannel call.
GetChannelId(int channel_idx)224 intptr_t GetChannelId(int channel_idx) {
225 GetTopChannelsRequest request;
226 GetTopChannelsResponse response;
227 request.set_start_channel_id(0);
228 ClientContext context;
229 Status s = channelz_stub_->GetTopChannels(&context, request, &response);
230 EXPECT_TRUE(s.ok()) << "s.error_message() = " << s.error_message();
231 EXPECT_GT(response.channel_size(), channel_idx);
232 return response.channel(channel_idx).ref().channel_id();
233 }
234
to_string(const int number)235 static string to_string(const int number) {
236 std::stringstream strs;
237 strs << number;
238 return strs.str();
239 }
240
241 protected:
242 // package of data needed for each backend server.
243 struct BackendData {
244 std::unique_ptr<Server> server;
245 int port;
246 std::unique_ptr<TestServiceImpl> service;
247 };
248
249 std::unique_ptr<grpc::channelz::v1::Channelz::Stub> channelz_stub_;
250 std::unique_ptr<grpc::testing::EchoTestService::Stub> echo_stub_;
251
252 // proxy server to ping with channelz requests.
253 std::unique_ptr<Server> proxy_server_;
254 int proxy_port_;
255 Proxy proxy_service_;
256
257 // backends. All implement the echo service.
258 std::vector<BackendData> backends_;
259 };
260
TEST_F(ChannelzServerTest,BasicTest)261 TEST_F(ChannelzServerTest, BasicTest) {
262 ResetStubs();
263 ConfigureProxy(1);
264 GetTopChannelsRequest request;
265 GetTopChannelsResponse response;
266 request.set_start_channel_id(0);
267 ClientContext context;
268 Status s = channelz_stub_->GetTopChannels(&context, request, &response);
269 EXPECT_TRUE(s.ok()) << "s.error_message() = " << s.error_message();
270 EXPECT_EQ(response.channel_size(), 1);
271 }
272
TEST_F(ChannelzServerTest,HighStartId)273 TEST_F(ChannelzServerTest, HighStartId) {
274 ResetStubs();
275 ConfigureProxy(1);
276 GetTopChannelsRequest request;
277 GetTopChannelsResponse response;
278 request.set_start_channel_id(10000);
279 ClientContext context;
280 Status s = channelz_stub_->GetTopChannels(&context, request, &response);
281 EXPECT_TRUE(s.ok()) << "s.error_message() = " << s.error_message();
282 EXPECT_EQ(response.channel_size(), 0);
283 }
284
TEST_F(ChannelzServerTest,SuccessfulRequestTest)285 TEST_F(ChannelzServerTest, SuccessfulRequestTest) {
286 ResetStubs();
287 ConfigureProxy(1);
288 SendSuccessfulEcho(0);
289 GetChannelRequest request;
290 GetChannelResponse response;
291 request.set_channel_id(GetChannelId(0));
292 ClientContext context;
293 Status s = channelz_stub_->GetChannel(&context, request, &response);
294 EXPECT_TRUE(s.ok()) << "s.error_message() = " << s.error_message();
295 EXPECT_EQ(response.channel().data().calls_started(), 1);
296 EXPECT_EQ(response.channel().data().calls_succeeded(), 1);
297 EXPECT_EQ(response.channel().data().calls_failed(), 0);
298 }
299
TEST_F(ChannelzServerTest,FailedRequestTest)300 TEST_F(ChannelzServerTest, FailedRequestTest) {
301 ResetStubs();
302 ConfigureProxy(1);
303 SendFailedEcho(0);
304 GetChannelRequest request;
305 GetChannelResponse response;
306 request.set_channel_id(GetChannelId(0));
307 ClientContext context;
308 Status s = channelz_stub_->GetChannel(&context, request, &response);
309 EXPECT_TRUE(s.ok()) << "s.error_message() = " << s.error_message();
310 EXPECT_EQ(response.channel().data().calls_started(), 1);
311 EXPECT_EQ(response.channel().data().calls_succeeded(), 0);
312 EXPECT_EQ(response.channel().data().calls_failed(), 1);
313 }
314
TEST_F(ChannelzServerTest,ManyRequestsTest)315 TEST_F(ChannelzServerTest, ManyRequestsTest) {
316 ResetStubs();
317 ConfigureProxy(1);
318 // send some RPCs
319 const int kNumSuccess = 10;
320 const int kNumFailed = 11;
321 for (int i = 0; i < kNumSuccess; ++i) {
322 SendSuccessfulEcho(0);
323 }
324 for (int i = 0; i < kNumFailed; ++i) {
325 SendFailedEcho(0);
326 }
327 GetChannelRequest request;
328 GetChannelResponse response;
329 request.set_channel_id(GetChannelId(0));
330 ClientContext context;
331 Status s = channelz_stub_->GetChannel(&context, request, &response);
332 EXPECT_TRUE(s.ok()) << "s.error_message() = " << s.error_message();
333 EXPECT_EQ(response.channel().data().calls_started(),
334 kNumSuccess + kNumFailed);
335 EXPECT_EQ(response.channel().data().calls_succeeded(), kNumSuccess);
336 EXPECT_EQ(response.channel().data().calls_failed(), kNumFailed);
337 }
338
TEST_F(ChannelzServerTest,ManyChannels)339 TEST_F(ChannelzServerTest, ManyChannels) {
340 ResetStubs();
341 const int kNumChannels = 4;
342 ConfigureProxy(kNumChannels);
343 GetTopChannelsRequest request;
344 GetTopChannelsResponse response;
345 request.set_start_channel_id(0);
346 ClientContext context;
347 Status s = channelz_stub_->GetTopChannels(&context, request, &response);
348 EXPECT_TRUE(s.ok()) << "s.error_message() = " << s.error_message();
349 EXPECT_EQ(response.channel_size(), kNumChannels);
350 }
351
TEST_F(ChannelzServerTest,ManyRequestsManyChannels)352 TEST_F(ChannelzServerTest, ManyRequestsManyChannels) {
353 ResetStubs();
354 const int kNumChannels = 4;
355 ConfigureProxy(kNumChannels);
356 const int kNumSuccess = 10;
357 const int kNumFailed = 11;
358 for (int i = 0; i < kNumSuccess; ++i) {
359 SendSuccessfulEcho(0);
360 SendSuccessfulEcho(2);
361 }
362 for (int i = 0; i < kNumFailed; ++i) {
363 SendFailedEcho(1);
364 SendFailedEcho(2);
365 }
366
367 // the first channel saw only successes
368 {
369 GetChannelRequest request;
370 GetChannelResponse response;
371 request.set_channel_id(GetChannelId(0));
372 ClientContext context;
373 Status s = channelz_stub_->GetChannel(&context, request, &response);
374 EXPECT_TRUE(s.ok()) << "s.error_message() = " << s.error_message();
375 EXPECT_EQ(response.channel().data().calls_started(), kNumSuccess);
376 EXPECT_EQ(response.channel().data().calls_succeeded(), kNumSuccess);
377 EXPECT_EQ(response.channel().data().calls_failed(), 0);
378 }
379
380 // the second channel saw only failures
381 {
382 GetChannelRequest request;
383 GetChannelResponse response;
384 request.set_channel_id(GetChannelId(1));
385 ClientContext context;
386 Status s = channelz_stub_->GetChannel(&context, request, &response);
387 EXPECT_TRUE(s.ok()) << "s.error_message() = " << s.error_message();
388 EXPECT_EQ(response.channel().data().calls_started(), kNumFailed);
389 EXPECT_EQ(response.channel().data().calls_succeeded(), 0);
390 EXPECT_EQ(response.channel().data().calls_failed(), kNumFailed);
391 }
392
393 // the third channel saw both
394 {
395 GetChannelRequest request;
396 GetChannelResponse response;
397 request.set_channel_id(GetChannelId(2));
398 ClientContext context;
399 Status s = channelz_stub_->GetChannel(&context, request, &response);
400 EXPECT_TRUE(s.ok()) << "s.error_message() = " << s.error_message();
401 EXPECT_EQ(response.channel().data().calls_started(),
402 kNumSuccess + kNumFailed);
403 EXPECT_EQ(response.channel().data().calls_succeeded(), kNumSuccess);
404 EXPECT_EQ(response.channel().data().calls_failed(), kNumFailed);
405 }
406
407 // the fourth channel saw nothing
408 {
409 GetChannelRequest request;
410 GetChannelResponse response;
411 request.set_channel_id(GetChannelId(3));
412 ClientContext context;
413 Status s = channelz_stub_->GetChannel(&context, request, &response);
414 EXPECT_TRUE(s.ok()) << "s.error_message() = " << s.error_message();
415 EXPECT_EQ(response.channel().data().calls_started(), 0);
416 EXPECT_EQ(response.channel().data().calls_succeeded(), 0);
417 EXPECT_EQ(response.channel().data().calls_failed(), 0);
418 }
419 }
420
TEST_F(ChannelzServerTest,ManySubchannels)421 TEST_F(ChannelzServerTest, ManySubchannels) {
422 ResetStubs();
423 const int kNumChannels = 4;
424 ConfigureProxy(kNumChannels);
425 const int kNumSuccess = 10;
426 const int kNumFailed = 11;
427 for (int i = 0; i < kNumSuccess; ++i) {
428 SendSuccessfulEcho(0);
429 SendSuccessfulEcho(2);
430 }
431 for (int i = 0; i < kNumFailed; ++i) {
432 SendFailedEcho(1);
433 SendFailedEcho(2);
434 }
435 GetTopChannelsRequest gtc_request;
436 GetTopChannelsResponse gtc_response;
437 gtc_request.set_start_channel_id(0);
438 ClientContext context;
439 Status s =
440 channelz_stub_->GetTopChannels(&context, gtc_request, >c_response);
441 EXPECT_TRUE(s.ok()) << s.error_message();
442 EXPECT_EQ(gtc_response.channel_size(), kNumChannels);
443 for (int i = 0; i < gtc_response.channel_size(); ++i) {
444 // if the channel sent no RPCs, then expect no subchannels to have been
445 // created.
446 if (gtc_response.channel(i).data().calls_started() == 0) {
447 EXPECT_EQ(gtc_response.channel(i).subchannel_ref_size(), 0);
448 continue;
449 }
450 // The resolver must return at least one address.
451 ASSERT_GT(gtc_response.channel(i).subchannel_ref_size(), 0);
452 GetSubchannelRequest gsc_request;
453 GetSubchannelResponse gsc_response;
454 gsc_request.set_subchannel_id(
455 gtc_response.channel(i).subchannel_ref(0).subchannel_id());
456 ClientContext context;
457 Status s =
458 channelz_stub_->GetSubchannel(&context, gsc_request, &gsc_response);
459 EXPECT_TRUE(s.ok()) << s.error_message();
460 EXPECT_EQ(gtc_response.channel(i).data().calls_started(),
461 gsc_response.subchannel().data().calls_started());
462 EXPECT_EQ(gtc_response.channel(i).data().calls_succeeded(),
463 gsc_response.subchannel().data().calls_succeeded());
464 EXPECT_EQ(gtc_response.channel(i).data().calls_failed(),
465 gsc_response.subchannel().data().calls_failed());
466 }
467 }
468
TEST_F(ChannelzServerTest,BasicServerTest)469 TEST_F(ChannelzServerTest, BasicServerTest) {
470 ResetStubs();
471 ConfigureProxy(1);
472 GetServersRequest request;
473 GetServersResponse response;
474 request.set_start_server_id(0);
475 ClientContext context;
476 Status s = channelz_stub_->GetServers(&context, request, &response);
477 EXPECT_TRUE(s.ok()) << "s.error_message() = " << s.error_message();
478 EXPECT_EQ(response.server_size(), 1);
479 }
480
TEST_F(ChannelzServerTest,BasicGetServerTest)481 TEST_F(ChannelzServerTest, BasicGetServerTest) {
482 ResetStubs();
483 ConfigureProxy(1);
484 GetServersRequest get_servers_request;
485 GetServersResponse get_servers_response;
486 get_servers_request.set_start_server_id(0);
487 ClientContext get_servers_context;
488 Status s = channelz_stub_->GetServers(
489 &get_servers_context, get_servers_request, &get_servers_response);
490 EXPECT_TRUE(s.ok()) << "s.error_message() = " << s.error_message();
491 EXPECT_EQ(get_servers_response.server_size(), 1);
492 GetServerRequest get_server_request;
493 GetServerResponse get_server_response;
494 get_server_request.set_server_id(
495 get_servers_response.server(0).ref().server_id());
496 ClientContext get_server_context;
497 s = channelz_stub_->GetServer(&get_server_context, get_server_request,
498 &get_server_response);
499 EXPECT_TRUE(s.ok()) << "s.error_message() = " << s.error_message();
500 EXPECT_EQ(get_servers_response.server(0).ref().server_id(),
501 get_server_response.server().ref().server_id());
502 }
503
TEST_F(ChannelzServerTest,ServerCallTest)504 TEST_F(ChannelzServerTest, ServerCallTest) {
505 ResetStubs();
506 ConfigureProxy(1);
507 const int kNumSuccess = 10;
508 const int kNumFailed = 11;
509 for (int i = 0; i < kNumSuccess; ++i) {
510 SendSuccessfulEcho(0);
511 }
512 for (int i = 0; i < kNumFailed; ++i) {
513 SendFailedEcho(0);
514 }
515 GetServersRequest request;
516 GetServersResponse response;
517 request.set_start_server_id(0);
518 ClientContext context;
519 Status s = channelz_stub_->GetServers(&context, request, &response);
520 EXPECT_TRUE(s.ok()) << "s.error_message() = " << s.error_message();
521 EXPECT_EQ(response.server_size(), 1);
522 EXPECT_EQ(response.server(0).data().calls_succeeded(), kNumSuccess);
523 EXPECT_EQ(response.server(0).data().calls_failed(), kNumFailed);
524 // This is success+failure+1 because the call that retrieved this information
525 // will be counted as started. It will not track success/failure until after
526 // it has returned, so that is not included in the response.
527 EXPECT_EQ(response.server(0).data().calls_started(),
528 kNumSuccess + kNumFailed + 1);
529 }
530
TEST_F(ChannelzServerTest,ManySubchannelsAndSockets)531 TEST_F(ChannelzServerTest, ManySubchannelsAndSockets) {
532 ResetStubs();
533 const int kNumChannels = 4;
534 ConfigureProxy(kNumChannels);
535 const int kNumSuccess = 10;
536 const int kNumFailed = 11;
537 for (int i = 0; i < kNumSuccess; ++i) {
538 SendSuccessfulEcho(0);
539 SendSuccessfulEcho(2);
540 }
541 for (int i = 0; i < kNumFailed; ++i) {
542 SendFailedEcho(1);
543 SendFailedEcho(2);
544 }
545 GetTopChannelsRequest gtc_request;
546 GetTopChannelsResponse gtc_response;
547 gtc_request.set_start_channel_id(0);
548 ClientContext context;
549 Status s =
550 channelz_stub_->GetTopChannels(&context, gtc_request, >c_response);
551 EXPECT_TRUE(s.ok()) << s.error_message();
552 EXPECT_EQ(gtc_response.channel_size(), kNumChannels);
553 for (int i = 0; i < gtc_response.channel_size(); ++i) {
554 // if the channel sent no RPCs, then expect no subchannels to have been
555 // created.
556 if (gtc_response.channel(i).data().calls_started() == 0) {
557 EXPECT_EQ(gtc_response.channel(i).subchannel_ref_size(), 0);
558 continue;
559 }
560 // The resolver must return at least one address.
561 ASSERT_GT(gtc_response.channel(i).subchannel_ref_size(), 0);
562 // First grab the subchannel
563 GetSubchannelRequest get_subchannel_req;
564 GetSubchannelResponse get_subchannel_resp;
565 get_subchannel_req.set_subchannel_id(
566 gtc_response.channel(i).subchannel_ref(0).subchannel_id());
567 ClientContext get_subchannel_ctx;
568 Status s = channelz_stub_->GetSubchannel(
569 &get_subchannel_ctx, get_subchannel_req, &get_subchannel_resp);
570 EXPECT_TRUE(s.ok()) << s.error_message();
571 EXPECT_EQ(get_subchannel_resp.subchannel().socket_ref_size(), 1);
572 // Now grab the socket.
573 GetSocketRequest get_socket_req;
574 GetSocketResponse get_socket_resp;
575 ClientContext get_socket_ctx;
576 get_socket_req.set_socket_id(
577 get_subchannel_resp.subchannel().socket_ref(0).socket_id());
578 s = channelz_stub_->GetSocket(&get_socket_ctx, get_socket_req,
579 &get_socket_resp);
580 EXPECT_TRUE(
581 get_subchannel_resp.subchannel().socket_ref(0).name().find("http"));
582 EXPECT_TRUE(s.ok()) << s.error_message();
583 // calls started == streams started AND stream succeeded. Since none of
584 // these RPCs were canceled, all of the streams will succeeded even though
585 // the RPCs they represent might have failed.
586 EXPECT_EQ(get_subchannel_resp.subchannel().data().calls_started(),
587 get_socket_resp.socket().data().streams_started());
588 EXPECT_EQ(get_subchannel_resp.subchannel().data().calls_started(),
589 get_socket_resp.socket().data().streams_succeeded());
590 // All of the calls were unary, so calls started == messages sent.
591 EXPECT_EQ(get_subchannel_resp.subchannel().data().calls_started(),
592 get_socket_resp.socket().data().messages_sent());
593 // We only get responses when the RPC was successful, so
594 // calls succeeded == messages received.
595 EXPECT_EQ(get_subchannel_resp.subchannel().data().calls_succeeded(),
596 get_socket_resp.socket().data().messages_received());
597 }
598 }
599
TEST_F(ChannelzServerTest,StreamingRPC)600 TEST_F(ChannelzServerTest, StreamingRPC) {
601 ResetStubs();
602 ConfigureProxy(1);
603 const int kNumMessages = 5;
604 SendSuccessfulStream(kNumMessages);
605 // Get the channel
606 GetChannelRequest get_channel_request;
607 GetChannelResponse get_channel_response;
608 get_channel_request.set_channel_id(GetChannelId(0));
609 ClientContext get_channel_context;
610 Status s = channelz_stub_->GetChannel(
611 &get_channel_context, get_channel_request, &get_channel_response);
612 EXPECT_TRUE(s.ok()) << "s.error_message() = " << s.error_message();
613 EXPECT_EQ(get_channel_response.channel().data().calls_started(), 1);
614 EXPECT_EQ(get_channel_response.channel().data().calls_succeeded(), 1);
615 EXPECT_EQ(get_channel_response.channel().data().calls_failed(), 0);
616 // Get the subchannel
617 ASSERT_GT(get_channel_response.channel().subchannel_ref_size(), 0);
618 GetSubchannelRequest get_subchannel_request;
619 GetSubchannelResponse get_subchannel_response;
620 ClientContext get_subchannel_context;
621 get_subchannel_request.set_subchannel_id(
622 get_channel_response.channel().subchannel_ref(0).subchannel_id());
623 s = channelz_stub_->GetSubchannel(&get_subchannel_context,
624 get_subchannel_request,
625 &get_subchannel_response);
626 EXPECT_TRUE(s.ok()) << "s.error_message() = " << s.error_message();
627 EXPECT_EQ(get_subchannel_response.subchannel().data().calls_started(), 1);
628 EXPECT_EQ(get_subchannel_response.subchannel().data().calls_succeeded(), 1);
629 EXPECT_EQ(get_subchannel_response.subchannel().data().calls_failed(), 0);
630 // Get the socket
631 ASSERT_GT(get_subchannel_response.subchannel().socket_ref_size(), 0);
632 GetSocketRequest get_socket_request;
633 GetSocketResponse get_socket_response;
634 ClientContext get_socket_context;
635 get_socket_request.set_socket_id(
636 get_subchannel_response.subchannel().socket_ref(0).socket_id());
637 EXPECT_TRUE(
638 get_subchannel_response.subchannel().socket_ref(0).name().find("http"));
639 s = channelz_stub_->GetSocket(&get_socket_context, get_socket_request,
640 &get_socket_response);
641 EXPECT_TRUE(s.ok()) << "s.error_message() = " << s.error_message();
642 EXPECT_EQ(get_socket_response.socket().data().streams_started(), 1);
643 EXPECT_EQ(get_socket_response.socket().data().streams_succeeded(), 1);
644 EXPECT_EQ(get_socket_response.socket().data().streams_failed(), 0);
645 EXPECT_EQ(get_socket_response.socket().data().messages_sent(), kNumMessages);
646 EXPECT_EQ(get_socket_response.socket().data().messages_received(),
647 kNumMessages);
648 }
649
TEST_F(ChannelzServerTest,GetServerSocketsTest)650 TEST_F(ChannelzServerTest, GetServerSocketsTest) {
651 ResetStubs();
652 ConfigureProxy(1);
653 GetServersRequest get_server_request;
654 GetServersResponse get_server_response;
655 get_server_request.set_start_server_id(0);
656 ClientContext get_server_context;
657 Status s = channelz_stub_->GetServers(&get_server_context, get_server_request,
658 &get_server_response);
659 EXPECT_TRUE(s.ok()) << "s.error_message() = " << s.error_message();
660 EXPECT_EQ(get_server_response.server_size(), 1);
661 GetServerSocketsRequest get_server_sockets_request;
662 GetServerSocketsResponse get_server_sockets_response;
663 get_server_sockets_request.set_server_id(
664 get_server_response.server(0).ref().server_id());
665 get_server_sockets_request.set_start_socket_id(0);
666 ClientContext get_server_sockets_context;
667 s = channelz_stub_->GetServerSockets(&get_server_sockets_context,
668 get_server_sockets_request,
669 &get_server_sockets_response);
670 EXPECT_TRUE(s.ok()) << "s.error_message() = " << s.error_message();
671 EXPECT_EQ(get_server_sockets_response.socket_ref_size(), 1);
672 EXPECT_TRUE(get_server_sockets_response.socket_ref(0).name().find("http"));
673 }
674
TEST_F(ChannelzServerTest,GetServerSocketsPaginationTest)675 TEST_F(ChannelzServerTest, GetServerSocketsPaginationTest) {
676 ResetStubs();
677 ConfigureProxy(1);
678 std::vector<std::unique_ptr<grpc::testing::EchoTestService::Stub>> stubs;
679 const int kNumServerSocketsCreated = 20;
680 for (int i = 0; i < kNumServerSocketsCreated; ++i) {
681 stubs.push_back(NewEchoStub());
682 EchoRequest request;
683 EchoResponse response;
684 request.set_message("Hello channelz");
685 request.mutable_param()->set_backend_channel_idx(0);
686 ClientContext context;
687 Status s = stubs.back()->Echo(&context, request, &response);
688 EXPECT_EQ(response.message(), request.message());
689 EXPECT_TRUE(s.ok()) << "s.error_message() = " << s.error_message();
690 }
691 GetServersRequest get_server_request;
692 GetServersResponse get_server_response;
693 get_server_request.set_start_server_id(0);
694 ClientContext get_server_context;
695 Status s = channelz_stub_->GetServers(&get_server_context, get_server_request,
696 &get_server_response);
697 EXPECT_TRUE(s.ok()) << "s.error_message() = " << s.error_message();
698 EXPECT_EQ(get_server_response.server_size(), 1);
699 // Make a request that gets all of the serversockets
700 {
701 GetServerSocketsRequest get_server_sockets_request;
702 GetServerSocketsResponse get_server_sockets_response;
703 get_server_sockets_request.set_server_id(
704 get_server_response.server(0).ref().server_id());
705 get_server_sockets_request.set_start_socket_id(0);
706 ClientContext get_server_sockets_context;
707 s = channelz_stub_->GetServerSockets(&get_server_sockets_context,
708 get_server_sockets_request,
709 &get_server_sockets_response);
710 EXPECT_TRUE(s.ok()) << "s.error_message() = " << s.error_message();
711 // We add one to account the channelz stub that will end up creating
712 // a serversocket.
713 EXPECT_EQ(get_server_sockets_response.socket_ref_size(),
714 kNumServerSocketsCreated + 1);
715 EXPECT_TRUE(get_server_sockets_response.end());
716 }
717 // Now we make a request that exercises pagination.
718 {
719 GetServerSocketsRequest get_server_sockets_request;
720 GetServerSocketsResponse get_server_sockets_response;
721 get_server_sockets_request.set_server_id(
722 get_server_response.server(0).ref().server_id());
723 get_server_sockets_request.set_start_socket_id(0);
724 const int kMaxResults = 10;
725 get_server_sockets_request.set_max_results(kMaxResults);
726 ClientContext get_server_sockets_context;
727 s = channelz_stub_->GetServerSockets(&get_server_sockets_context,
728 get_server_sockets_request,
729 &get_server_sockets_response);
730 EXPECT_TRUE(s.ok()) << "s.error_message() = " << s.error_message();
731 EXPECT_EQ(get_server_sockets_response.socket_ref_size(), kMaxResults);
732 EXPECT_FALSE(get_server_sockets_response.end());
733 }
734 }
735
TEST_F(ChannelzServerTest,GetServerListenSocketsTest)736 TEST_F(ChannelzServerTest, GetServerListenSocketsTest) {
737 ResetStubs();
738 ConfigureProxy(1);
739 GetServersRequest get_server_request;
740 GetServersResponse get_server_response;
741 get_server_request.set_start_server_id(0);
742 ClientContext get_server_context;
743 Status s = channelz_stub_->GetServers(&get_server_context, get_server_request,
744 &get_server_response);
745 EXPECT_TRUE(s.ok()) << "s.error_message() = " << s.error_message();
746 EXPECT_EQ(get_server_response.server_size(), 1);
747 EXPECT_EQ(get_server_response.server(0).listen_socket_size(), 1);
748 GetSocketRequest get_socket_request;
749 GetSocketResponse get_socket_response;
750 get_socket_request.set_socket_id(
751 get_server_response.server(0).listen_socket(0).socket_id());
752 EXPECT_TRUE(
753 get_server_response.server(0).listen_socket(0).name().find("http"));
754 ClientContext get_socket_context;
755 s = channelz_stub_->GetSocket(&get_socket_context, get_socket_request,
756 &get_socket_response);
757 EXPECT_TRUE(s.ok()) << "s.error_message() = " << s.error_message();
758 }
759
760 } // namespace testing
761 } // namespace grpc
762
main(int argc,char ** argv)763 int main(int argc, char** argv) {
764 grpc::testing::TestEnvironment env(argc, argv);
765 ::testing::InitGoogleTest(&argc, argv);
766 return RUN_ALL_TESTS();
767 }
768