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