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