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