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