• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  *
3  * Copyright 2017 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 <stdlib.h>
20 #include <string.h>
21 
22 #include <gtest/gtest.h>
23 
24 #include <grpc/support/alloc.h>
25 #include <grpc/support/log.h>
26 
27 #include "src/core/lib/channel/channel_trace.h"
28 #include "src/core/lib/channel/channelz.h"
29 #include "src/core/lib/channel/channelz_registry.h"
30 #include "src/core/lib/gpr/useful.h"
31 #include "src/core/lib/iomgr/exec_ctx.h"
32 #include "src/core/lib/json/json.h"
33 #include "src/core/lib/surface/channel.h"
34 #include "src/core/lib/surface/server.h"
35 
36 #include "test/core/util/test_config.h"
37 #include "test/cpp/util/channel_trace_proto_helper.h"
38 
39 #include <grpc/support/string_util.h>
40 #include <stdlib.h>
41 #include <string.h>
42 
43 namespace grpc_core {
44 namespace channelz {
45 namespace testing {
46 
47 // testing peer to access channel internals
48 class CallCountingHelperPeer {
49  public:
CallCountingHelperPeer(CallCountingHelper * node)50   explicit CallCountingHelperPeer(CallCountingHelper* node) : node_(node) {}
51 
last_call_started_time() const52   gpr_timespec last_call_started_time() const {
53     CallCountingHelper::CounterData data;
54     node_->CollectData(&data);
55     return gpr_cycle_counter_to_time(data.last_call_started_cycle);
56   }
57 
58  private:
59   CallCountingHelper* node_;
60 };
61 
62 namespace {
63 
GetUuidListFromArray(const Json::Array & arr)64 std::vector<intptr_t> GetUuidListFromArray(const Json::Array& arr) {
65   std::vector<intptr_t> uuids;
66   for (const Json& value : arr) {
67     EXPECT_EQ(value.type(), Json::Type::OBJECT);
68     if (value.type() != Json::Type::OBJECT) continue;
69     const Json::Object& object = value.object_value();
70     auto it = object.find("ref");
71     EXPECT_NE(it, object.end());
72     if (it == object.end()) continue;
73     EXPECT_EQ(it->second.type(), Json::Type::OBJECT);
74     if (it->second.type() != Json::Type::OBJECT) continue;
75     const Json::Object& ref_object = it->second.object_value();
76     it = ref_object.find("channelId");
77     EXPECT_NE(it, ref_object.end());
78     if (it != ref_object.end()) {
79       uuids.push_back(atoi(it->second.string_value().c_str()));
80     }
81   }
82   return uuids;
83 }
84 
ValidateJsonArraySize(const Json & array,size_t expected)85 void ValidateJsonArraySize(const Json& array, size_t expected) {
86   if (expected == 0) {
87     ASSERT_EQ(array.type(), Json::Type::JSON_NULL);
88   } else {
89     ASSERT_EQ(array.type(), Json::Type::ARRAY);
90     EXPECT_EQ(array.array_value().size(), expected);
91   }
92 }
93 
ValidateJsonEnd(const Json & json,bool end)94 void ValidateJsonEnd(const Json& json, bool end) {
95   auto it = json.object_value().find("end");
96   if (end) {
97     ASSERT_NE(it, json.object_value().end());
98     EXPECT_EQ(it->second.type(), Json::Type::JSON_TRUE);
99   } else {
100     ASSERT_EQ(it, json.object_value().end());
101   }
102 }
103 
ValidateGetTopChannels(size_t expected_channels)104 void ValidateGetTopChannels(size_t expected_channels) {
105   std::string json_str = ChannelzRegistry::GetTopChannels(0);
106   grpc::testing::ValidateGetTopChannelsResponseProtoJsonTranslation(
107       json_str.c_str());
108   grpc_error* error = GRPC_ERROR_NONE;
109   Json parsed_json = Json::Parse(json_str, &error);
110   ASSERT_EQ(error, GRPC_ERROR_NONE) << grpc_error_string(error);
111   ASSERT_EQ(parsed_json.type(), Json::Type::OBJECT);
112   // This check will naturally have to change when we support pagination.
113   // tracked: https://github.com/grpc/grpc/issues/16019.
114   ValidateJsonArraySize((*parsed_json.mutable_object())["channel"],
115                         expected_channels);
116   ValidateJsonEnd(parsed_json, true);
117   // Also check that the core API formats this correctly.
118   char* core_api_json_str = grpc_channelz_get_top_channels(0);
119   grpc::testing::ValidateGetTopChannelsResponseProtoJsonTranslation(
120       core_api_json_str);
121   gpr_free(core_api_json_str);
122 }
123 
ValidateGetServers(size_t expected_servers)124 void ValidateGetServers(size_t expected_servers) {
125   std::string json_str = ChannelzRegistry::GetServers(0);
126   grpc::testing::ValidateGetServersResponseProtoJsonTranslation(
127       json_str.c_str());
128   grpc_error* error = GRPC_ERROR_NONE;
129   Json parsed_json = Json::Parse(json_str, &error);
130   ASSERT_EQ(error, GRPC_ERROR_NONE) << grpc_error_string(error);
131   ASSERT_EQ(parsed_json.type(), Json::Type::OBJECT);
132   // This check will naturally have to change when we support pagination.
133   // tracked: https://github.com/grpc/grpc/issues/16019.
134   ValidateJsonArraySize((*parsed_json.mutable_object())["server"],
135                         expected_servers);
136   ValidateJsonEnd(parsed_json, true);
137   // Also check that the core API formats this correctly.
138   char* core_api_json_str = grpc_channelz_get_servers(0);
139   grpc::testing::ValidateGetServersResponseProtoJsonTranslation(
140       core_api_json_str);
141   gpr_free(core_api_json_str);
142 }
143 
144 class ChannelFixture {
145  public:
ChannelFixture(int max_tracer_event_memory=0)146   ChannelFixture(int max_tracer_event_memory = 0) {
147     grpc_arg client_a[] = {
148         grpc_channel_arg_integer_create(
149             const_cast<char*>(GRPC_ARG_MAX_CHANNEL_TRACE_EVENT_MEMORY_PER_NODE),
150             max_tracer_event_memory),
151         grpc_channel_arg_integer_create(
152             const_cast<char*>(GRPC_ARG_ENABLE_CHANNELZ), true)};
153     grpc_channel_args client_args = {GPR_ARRAY_SIZE(client_a), client_a};
154     channel_ =
155         grpc_insecure_channel_create("fake_target", &client_args, nullptr);
156   }
157 
~ChannelFixture()158   ~ChannelFixture() { grpc_channel_destroy(channel_); }
159 
channel()160   grpc_channel* channel() { return channel_; }
161 
162  private:
163   grpc_channel* channel_;
164 };
165 
166 class ServerFixture {
167  public:
ServerFixture(int max_tracer_event_memory=0)168   explicit ServerFixture(int max_tracer_event_memory = 0) {
169     grpc_arg server_a[] = {
170         grpc_channel_arg_integer_create(
171             const_cast<char*>(GRPC_ARG_MAX_CHANNEL_TRACE_EVENT_MEMORY_PER_NODE),
172             max_tracer_event_memory),
173         grpc_channel_arg_integer_create(
174             const_cast<char*>(GRPC_ARG_ENABLE_CHANNELZ), true),
175     };
176     grpc_channel_args server_args = {GPR_ARRAY_SIZE(server_a), server_a};
177     server_ = grpc_server_create(&server_args, nullptr);
178   }
179 
~ServerFixture()180   ~ServerFixture() { grpc_server_destroy(server_); }
181 
server() const182   grpc_server* server() const { return server_; }
183 
184  private:
185   grpc_server* server_;
186 };
187 
188 struct ValidateChannelDataArgs {
189   int64_t calls_started;
190   int64_t calls_failed;
191   int64_t calls_succeeded;
192 };
193 
ValidateChildInteger(const Json::Object & object,const std::string & key,int64_t expected)194 void ValidateChildInteger(const Json::Object& object, const std::string& key,
195                           int64_t expected) {
196   auto it = object.find(key);
197   if (expected == 0) {
198     ASSERT_EQ(it, object.end());
199     return;
200   }
201   ASSERT_NE(it, object.end());
202   ASSERT_EQ(it->second.type(), Json::Type::STRING);
203   int64_t gotten_number =
204       (int64_t)strtol(it->second.string_value().c_str(), nullptr, 0);
205   EXPECT_EQ(gotten_number, expected);
206 }
207 
ValidateCounters(const std::string & json_str,const ValidateChannelDataArgs & args)208 void ValidateCounters(const std::string& json_str,
209                       const ValidateChannelDataArgs& args) {
210   grpc_error* error = GRPC_ERROR_NONE;
211   Json json = Json::Parse(json_str, &error);
212   ASSERT_EQ(error, GRPC_ERROR_NONE) << grpc_error_string(error);
213   ASSERT_EQ(json.type(), Json::Type::OBJECT);
214   Json::Object* object = json.mutable_object();
215   Json& data = (*object)["data"];
216   ASSERT_EQ(data.type(), Json::Type::OBJECT);
217   ValidateChildInteger(data.object_value(), "callsStarted", args.calls_started);
218   ValidateChildInteger(data.object_value(), "callsFailed", args.calls_failed);
219   ValidateChildInteger(data.object_value(), "callsSucceeded",
220                        args.calls_succeeded);
221 }
222 
ValidateChannel(ChannelNode * channel,const ValidateChannelDataArgs & args)223 void ValidateChannel(ChannelNode* channel,
224                      const ValidateChannelDataArgs& args) {
225   std::string json_str = channel->RenderJsonString();
226   grpc::testing::ValidateChannelProtoJsonTranslation(json_str.c_str());
227   ValidateCounters(json_str, args);
228   // also check that the core API formats this the correct way
229   char* core_api_json_str = grpc_channelz_get_channel(channel->uuid());
230   grpc::testing::ValidateGetChannelResponseProtoJsonTranslation(
231       core_api_json_str);
232   gpr_free(core_api_json_str);
233 }
234 
ValidateServer(ServerNode * server,const ValidateChannelDataArgs & args)235 void ValidateServer(ServerNode* server, const ValidateChannelDataArgs& args) {
236   std::string json_str = server->RenderJsonString();
237   grpc::testing::ValidateServerProtoJsonTranslation(json_str.c_str());
238   ValidateCounters(json_str, args);
239   // also check that the core API formats this the correct way
240   char* core_api_json_str = grpc_channelz_get_server(server->uuid());
241   grpc::testing::ValidateGetServerResponseProtoJsonTranslation(
242       core_api_json_str);
243   gpr_free(core_api_json_str);
244 }
245 
GetLastCallStartedTime(CallCountingHelper * channel)246 gpr_timespec GetLastCallStartedTime(CallCountingHelper* channel) {
247   CallCountingHelperPeer peer(channel);
248   return peer.last_call_started_time();
249 }
250 
ChannelzSleep(int64_t sleep_us)251 void ChannelzSleep(int64_t sleep_us) {
252   gpr_sleep_until(gpr_time_add(gpr_now(GPR_CLOCK_REALTIME),
253                                gpr_time_from_micros(sleep_us, GPR_TIMESPAN)));
254   grpc_core::ExecCtx::Get()->InvalidateNow();
255 }
256 
257 }  // anonymous namespace
258 
259 class ChannelzChannelTest : public ::testing::TestWithParam<size_t> {};
260 
TEST_P(ChannelzChannelTest,BasicChannel)261 TEST_P(ChannelzChannelTest, BasicChannel) {
262   grpc_core::ExecCtx exec_ctx;
263   ChannelFixture channel(GetParam());
264   ChannelNode* channelz_channel =
265       grpc_channel_get_channelz_node(channel.channel());
266   ValidateChannel(channelz_channel, {0, 0, 0});
267 }
268 
TEST(ChannelzChannelTest,ChannelzDisabled)269 TEST(ChannelzChannelTest, ChannelzDisabled) {
270   grpc_core::ExecCtx exec_ctx;
271   // explicitly disable channelz
272   grpc_arg arg[] = {
273       grpc_channel_arg_integer_create(
274           const_cast<char*>(GRPC_ARG_MAX_CHANNEL_TRACE_EVENT_MEMORY_PER_NODE),
275           0),
276       grpc_channel_arg_integer_create(
277           const_cast<char*>(GRPC_ARG_ENABLE_CHANNELZ), false)};
278   grpc_channel_args args = {GPR_ARRAY_SIZE(arg), arg};
279   grpc_channel* channel =
280       grpc_insecure_channel_create("fake_target", &args, nullptr);
281   ChannelNode* channelz_channel = grpc_channel_get_channelz_node(channel);
282   ASSERT_EQ(channelz_channel, nullptr);
283   grpc_channel_destroy(channel);
284 }
285 
TEST_P(ChannelzChannelTest,BasicChannelAPIFunctionality)286 TEST_P(ChannelzChannelTest, BasicChannelAPIFunctionality) {
287   grpc_core::ExecCtx exec_ctx;
288   ChannelFixture channel(GetParam());
289   ChannelNode* channelz_channel =
290       grpc_channel_get_channelz_node(channel.channel());
291   channelz_channel->RecordCallStarted();
292   channelz_channel->RecordCallFailed();
293   channelz_channel->RecordCallSucceeded();
294   ValidateChannel(channelz_channel, {1, 1, 1});
295   channelz_channel->RecordCallStarted();
296   channelz_channel->RecordCallFailed();
297   channelz_channel->RecordCallSucceeded();
298   channelz_channel->RecordCallStarted();
299   channelz_channel->RecordCallFailed();
300   channelz_channel->RecordCallSucceeded();
301   ValidateChannel(channelz_channel, {3, 3, 3});
302 }
303 
TEST_P(ChannelzChannelTest,LastCallStartedTime)304 TEST_P(ChannelzChannelTest, LastCallStartedTime) {
305   grpc_core::ExecCtx exec_ctx;
306   CallCountingHelper counter;
307   // start a call to set the last call started timestamp
308   counter.RecordCallStarted();
309   gpr_timespec time1 = GetLastCallStartedTime(&counter);
310   // time gone by should not affect the timestamp
311   ChannelzSleep(100);
312   gpr_timespec time2 = GetLastCallStartedTime(&counter);
313   EXPECT_EQ(gpr_time_cmp(time1, time2), 0);
314   // calls succeeded or failed should not affect the timestamp
315   ChannelzSleep(100);
316   counter.RecordCallFailed();
317   counter.RecordCallSucceeded();
318   gpr_timespec time3 = GetLastCallStartedTime(&counter);
319   EXPECT_EQ(gpr_time_cmp(time1, time3), 0);
320   // another call started should affect the timestamp
321   // sleep for extra long to avoid flakes (since we cache Now())
322   ChannelzSleep(5000);
323   counter.RecordCallStarted();
324   gpr_timespec time4 = GetLastCallStartedTime(&counter);
325   EXPECT_NE(gpr_time_cmp(time1, time4), 0);
326 }
327 
328 class ChannelzRegistryBasedTest : public ::testing::TestWithParam<size_t> {
329  protected:
330   // ensure we always have a fresh registry for tests.
SetUp()331   void SetUp() override {
332     ChannelzRegistry::Shutdown();
333     ChannelzRegistry::Init();
334   }
335 
TearDown()336   void TearDown() override {
337     ChannelzRegistry::Shutdown();
338     ChannelzRegistry::Init();
339   }
340 };
341 
TEST_F(ChannelzRegistryBasedTest,BasicGetTopChannelsTest)342 TEST_F(ChannelzRegistryBasedTest, BasicGetTopChannelsTest) {
343   grpc_core::ExecCtx exec_ctx;
344   ChannelFixture channel;
345   ValidateGetTopChannels(1);
346 }
347 
TEST_F(ChannelzRegistryBasedTest,NoChannelsTest)348 TEST_F(ChannelzRegistryBasedTest, NoChannelsTest) {
349   grpc_core::ExecCtx exec_ctx;
350   ValidateGetTopChannels(0);
351 }
352 
TEST_F(ChannelzRegistryBasedTest,ManyChannelsTest)353 TEST_F(ChannelzRegistryBasedTest, ManyChannelsTest) {
354   grpc_core::ExecCtx exec_ctx;
355   ChannelFixture channels[10];
356   (void)channels;  // suppress unused variable error
357   ValidateGetTopChannels(10);
358 }
359 
TEST_F(ChannelzRegistryBasedTest,GetTopChannelsPagination)360 TEST_F(ChannelzRegistryBasedTest, GetTopChannelsPagination) {
361   grpc_core::ExecCtx exec_ctx;
362   // This is over the pagination limit.
363   ChannelFixture channels[150];
364   (void)channels;  // suppress unused variable error
365   std::string json_str = ChannelzRegistry::GetTopChannels(0);
366   grpc::testing::ValidateGetTopChannelsResponseProtoJsonTranslation(
367       json_str.c_str());
368   grpc_error* error = GRPC_ERROR_NONE;
369   Json parsed_json = Json::Parse(json_str, &error);
370   ASSERT_EQ(error, GRPC_ERROR_NONE) << grpc_error_string(error);
371   ASSERT_EQ(parsed_json.type(), Json::Type::OBJECT);
372   // 100 is the pagination limit.
373   ValidateJsonArraySize((*parsed_json.mutable_object())["channel"], 100);
374   ValidateJsonEnd(parsed_json, false);
375   // Now we get the rest.
376   json_str = ChannelzRegistry::GetTopChannels(101);
377   grpc::testing::ValidateGetTopChannelsResponseProtoJsonTranslation(
378       json_str.c_str());
379   error = GRPC_ERROR_NONE;
380   parsed_json = Json::Parse(json_str, &error);
381   ASSERT_EQ(error, GRPC_ERROR_NONE) << grpc_error_string(error);
382   ASSERT_EQ(parsed_json.type(), Json::Type::OBJECT);
383   ValidateJsonArraySize((*parsed_json.mutable_object())["channel"], 50);
384   ValidateJsonEnd(parsed_json, true);
385 }
386 
TEST_F(ChannelzRegistryBasedTest,GetTopChannelsUuidCheck)387 TEST_F(ChannelzRegistryBasedTest, GetTopChannelsUuidCheck) {
388   const intptr_t kNumChannels = 50;
389   grpc_core::ExecCtx exec_ctx;
390   ChannelFixture channels[kNumChannels];
391   (void)channels;  // suppress unused variable error
392   std::string json_str = ChannelzRegistry::GetTopChannels(0);
393   grpc_error* error = GRPC_ERROR_NONE;
394   Json parsed_json = Json::Parse(json_str, &error);
395   ASSERT_EQ(error, GRPC_ERROR_NONE) << grpc_error_string(error);
396   ASSERT_EQ(parsed_json.type(), Json::Type::OBJECT);
397   Json& array = (*parsed_json.mutable_object())["channel"];
398   ValidateJsonArraySize(array, kNumChannels);
399   std::vector<intptr_t> uuids = GetUuidListFromArray(array.array_value());
400   for (int i = 0; i < kNumChannels; ++i) {
401     EXPECT_EQ(i + 1, uuids[i]);
402   }
403 }
404 
TEST_F(ChannelzRegistryBasedTest,GetTopChannelsMiddleUuidCheck)405 TEST_F(ChannelzRegistryBasedTest, GetTopChannelsMiddleUuidCheck) {
406   const intptr_t kNumChannels = 50;
407   const intptr_t kMidQuery = 40;
408   grpc_core::ExecCtx exec_ctx;
409   ChannelFixture channels[kNumChannels];
410   (void)channels;  // suppress unused variable error
411   // Only query for the end of the channels.
412   std::string json_str = ChannelzRegistry::GetTopChannels(kMidQuery);
413   grpc_error* error = GRPC_ERROR_NONE;
414   Json parsed_json = Json::Parse(json_str, &error);
415   ASSERT_EQ(error, GRPC_ERROR_NONE) << grpc_error_string(error);
416   ASSERT_EQ(parsed_json.type(), Json::Type::OBJECT);
417   Json& array = (*parsed_json.mutable_object())["channel"];
418   ValidateJsonArraySize(array, kNumChannels - kMidQuery + 1);
419   std::vector<intptr_t> uuids = GetUuidListFromArray(array.array_value());
420   for (int i = 0; i < uuids.size(); ++i) {
421     EXPECT_EQ(static_cast<intptr_t>(kMidQuery + i), uuids[i]);
422   }
423 }
424 
TEST_F(ChannelzRegistryBasedTest,GetTopChannelsNoHitUuid)425 TEST_F(ChannelzRegistryBasedTest, GetTopChannelsNoHitUuid) {
426   grpc_core::ExecCtx exec_ctx;
427   ChannelFixture pre_channels[40];  // will take uuid[1, 40]
428   (void)pre_channels;               // suppress unused variable error
429   ServerFixture servers[10];        // will take uuid[41, 50]
430   (void)servers;                    // suppress unused variable error
431   ChannelFixture channels[10];      // will take uuid[51, 60]
432   (void)channels;                   // suppress unused variable error
433   // Query in the middle of the server channels.
434   std::string json_str = ChannelzRegistry::GetTopChannels(45);
435   grpc_error* error = GRPC_ERROR_NONE;
436   Json parsed_json = Json::Parse(json_str, &error);
437   ASSERT_EQ(error, GRPC_ERROR_NONE) << grpc_error_string(error);
438   ASSERT_EQ(parsed_json.type(), Json::Type::OBJECT);
439   Json& array = (*parsed_json.mutable_object())["channel"];
440   ValidateJsonArraySize(array, 10);
441   std::vector<intptr_t> uuids = GetUuidListFromArray(array.array_value());
442   for (int i = 0; i < uuids.size(); ++i) {
443     EXPECT_EQ(static_cast<intptr_t>(51 + i), uuids[i]);
444   }
445 }
446 
TEST_F(ChannelzRegistryBasedTest,GetTopChannelsMoreGaps)447 TEST_F(ChannelzRegistryBasedTest, GetTopChannelsMoreGaps) {
448   grpc_core::ExecCtx exec_ctx;
449   ChannelFixture channel_with_uuid1;
450   { ServerFixture channel_with_uuid2; }
451   ChannelFixture channel_with_uuid3;
452   { ServerFixture server_with_uuid4; }
453   ChannelFixture channel_with_uuid5;
454   // Current state of list: [1, NULL, 3, NULL, 5]
455   std::string json_str = ChannelzRegistry::GetTopChannels(2);
456   grpc_error* error = GRPC_ERROR_NONE;
457   Json parsed_json = Json::Parse(json_str, &error);
458   ASSERT_EQ(error, GRPC_ERROR_NONE) << grpc_error_string(error);
459   ASSERT_EQ(parsed_json.type(), Json::Type::OBJECT);
460   Json array = (*parsed_json.mutable_object())["channel"];
461   ValidateJsonArraySize(array, 2);
462   std::vector<intptr_t> uuids = GetUuidListFromArray(array.array_value());
463   EXPECT_EQ(static_cast<intptr_t>(3), uuids[0]);
464   EXPECT_EQ(static_cast<intptr_t>(5), uuids[1]);
465   json_str = ChannelzRegistry::GetTopChannels(4);
466   error = GRPC_ERROR_NONE;
467   parsed_json = Json::Parse(json_str, &error);
468   ASSERT_EQ(error, GRPC_ERROR_NONE) << grpc_error_string(error);
469   ASSERT_EQ(parsed_json.type(), Json::Type::OBJECT);
470   array = (*parsed_json.mutable_object())["channel"];
471   ValidateJsonArraySize(array, 1);
472   uuids = GetUuidListFromArray(array.array_value());
473   EXPECT_EQ(static_cast<intptr_t>(5), uuids[0]);
474 }
475 
TEST_F(ChannelzRegistryBasedTest,GetTopChannelsUuidAfterCompaction)476 TEST_F(ChannelzRegistryBasedTest, GetTopChannelsUuidAfterCompaction) {
477   const intptr_t kLoopIterations = 50;
478   grpc_core::ExecCtx exec_ctx;
479   std::vector<std::unique_ptr<ChannelFixture>> even_channels;
480   {
481     // these will delete and unregister themselves after this block.
482     std::vector<std::unique_ptr<ChannelFixture>> odd_channels;
483     for (int i = 0; i < kLoopIterations; i++) {
484       odd_channels.push_back(absl::make_unique<ChannelFixture>());
485       even_channels.push_back(absl::make_unique<ChannelFixture>());
486     }
487   }
488   std::string json_str = ChannelzRegistry::GetTopChannels(0);
489   grpc_error* error = GRPC_ERROR_NONE;
490   Json parsed_json = Json::Parse(json_str, &error);
491   ASSERT_EQ(error, GRPC_ERROR_NONE) << grpc_error_string(error);
492   ASSERT_EQ(parsed_json.type(), Json::Type::OBJECT);
493   Json& array = (*parsed_json.mutable_object())["channel"];
494   ValidateJsonArraySize(array, kLoopIterations);
495   std::vector<intptr_t> uuids = GetUuidListFromArray(array.array_value());
496   for (int i = 0; i < kLoopIterations; ++i) {
497     // only the even uuids will still be present.
498     EXPECT_EQ((i + 1) * 2, uuids[i]);
499   }
500 }
501 
TEST_F(ChannelzRegistryBasedTest,InternalChannelTest)502 TEST_F(ChannelzRegistryBasedTest, InternalChannelTest) {
503   grpc_core::ExecCtx exec_ctx;
504   ChannelFixture channels[10];
505   (void)channels;  // suppress unused variable error
506   // create an internal channel
507   grpc_arg client_a[2];
508   client_a[0] = grpc_core::channelz::MakeParentUuidArg(1);
509   client_a[1] = grpc_channel_arg_integer_create(
510       const_cast<char*>(GRPC_ARG_ENABLE_CHANNELZ), true);
511   grpc_channel_args client_args = {GPR_ARRAY_SIZE(client_a), client_a};
512   grpc_channel* internal_channel =
513       grpc_insecure_channel_create("fake_target", &client_args, nullptr);
514   // The internal channel should not be returned from the request
515   ValidateGetTopChannels(10);
516   grpc_channel_destroy(internal_channel);
517 }
518 
TEST(ChannelzServerTest,BasicServerAPIFunctionality)519 TEST(ChannelzServerTest, BasicServerAPIFunctionality) {
520   grpc_core::ExecCtx exec_ctx;
521   ServerFixture server(10);
522   ServerNode* channelz_server = grpc_server_get_channelz_node(server.server());
523   channelz_server->RecordCallStarted();
524   channelz_server->RecordCallFailed();
525   channelz_server->RecordCallSucceeded();
526   ValidateServer(channelz_server, {1, 1, 1});
527   channelz_server->RecordCallStarted();
528   channelz_server->RecordCallFailed();
529   channelz_server->RecordCallSucceeded();
530   channelz_server->RecordCallStarted();
531   channelz_server->RecordCallFailed();
532   channelz_server->RecordCallSucceeded();
533   ValidateServer(channelz_server, {3, 3, 3});
534 }
535 
TEST_F(ChannelzRegistryBasedTest,BasicGetServersTest)536 TEST_F(ChannelzRegistryBasedTest, BasicGetServersTest) {
537   grpc_core::ExecCtx exec_ctx;
538   ServerFixture server;
539   ValidateGetServers(1);
540 }
541 
TEST_F(ChannelzRegistryBasedTest,NoServersTest)542 TEST_F(ChannelzRegistryBasedTest, NoServersTest) {
543   grpc_core::ExecCtx exec_ctx;
544   ValidateGetServers(0);
545 }
546 
TEST_F(ChannelzRegistryBasedTest,ManyServersTest)547 TEST_F(ChannelzRegistryBasedTest, ManyServersTest) {
548   grpc_core::ExecCtx exec_ctx;
549   ServerFixture servers[10];
550   (void)servers;  // suppress unused variable error
551   ValidateGetServers(10);
552 }
553 
554 INSTANTIATE_TEST_SUITE_P(ChannelzChannelTestSweep, ChannelzChannelTest,
555                          ::testing::Values(0, 8, 64, 1024, 1024 * 1024));
556 
557 }  // namespace testing
558 }  // namespace channelz
559 }  // namespace grpc_core
560 
main(int argc,char ** argv)561 int main(int argc, char** argv) {
562   grpc::testing::TestEnvironment env(argc, argv);
563   grpc_init();
564   ::testing::InitGoogleTest(&argc, argv);
565   int ret = RUN_ALL_TESTS();
566   grpc_shutdown();
567   return ret;
568 }
569