mirror of https://github.com/grpc/grpc.git
The C based gRPC (C++, Python, Ruby, Objective-C, PHP, C#)
https://grpc.io/
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
568 lines
20 KiB
568 lines
20 KiB
/* |
|
* |
|
* Copyright 2017 gRPC authors. |
|
* |
|
* Licensed under the Apache License, Version 2.0 (the "License"); |
|
* you may not use this file except in compliance with the License. |
|
* You may obtain a copy of the License at |
|
* |
|
* http://www.apache.org/licenses/LICENSE-2.0 |
|
* |
|
* Unless required by applicable law or agreed to in writing, software |
|
* distributed under the License is distributed on an "AS IS" BASIS, |
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|
* See the License for the specific language governing permissions and |
|
* limitations under the License. |
|
* |
|
*/ |
|
|
|
#include <stdlib.h> |
|
#include <string.h> |
|
|
|
#include <gtest/gtest.h> |
|
|
|
#include <grpc/support/alloc.h> |
|
#include <grpc/support/log.h> |
|
|
|
#include "src/core/lib/channel/channel_trace.h" |
|
#include "src/core/lib/channel/channelz.h" |
|
#include "src/core/lib/channel/channelz_registry.h" |
|
#include "src/core/lib/gpr/useful.h" |
|
#include "src/core/lib/iomgr/exec_ctx.h" |
|
#include "src/core/lib/json/json.h" |
|
#include "src/core/lib/surface/channel.h" |
|
#include "src/core/lib/surface/server.h" |
|
|
|
#include "test/core/util/test_config.h" |
|
#include "test/cpp/util/channel_trace_proto_helper.h" |
|
|
|
#include <grpc/support/string_util.h> |
|
#include <stdlib.h> |
|
#include <string.h> |
|
|
|
namespace grpc_core { |
|
namespace channelz { |
|
namespace testing { |
|
|
|
// testing peer to access channel internals |
|
class CallCountingHelperPeer { |
|
public: |
|
explicit CallCountingHelperPeer(CallCountingHelper* node) : node_(node) {} |
|
|
|
gpr_timespec last_call_started_time() const { |
|
CallCountingHelper::CounterData data; |
|
node_->CollectData(&data); |
|
return gpr_cycle_counter_to_time(data.last_call_started_cycle); |
|
} |
|
|
|
private: |
|
CallCountingHelper* node_; |
|
}; |
|
|
|
namespace { |
|
|
|
std::vector<intptr_t> GetUuidListFromArray(const Json::Array& arr) { |
|
std::vector<intptr_t> uuids; |
|
for (const Json& value : arr) { |
|
EXPECT_EQ(value.type(), Json::Type::OBJECT); |
|
if (value.type() != Json::Type::OBJECT) continue; |
|
const Json::Object& object = value.object_value(); |
|
auto it = object.find("ref"); |
|
EXPECT_NE(it, object.end()); |
|
if (it == object.end()) continue; |
|
EXPECT_EQ(it->second.type(), Json::Type::OBJECT); |
|
if (it->second.type() != Json::Type::OBJECT) continue; |
|
const Json::Object& ref_object = it->second.object_value(); |
|
it = ref_object.find("channelId"); |
|
EXPECT_NE(it, ref_object.end()); |
|
if (it != ref_object.end()) { |
|
uuids.push_back(atoi(it->second.string_value().c_str())); |
|
} |
|
} |
|
return uuids; |
|
} |
|
|
|
void ValidateJsonArraySize(const Json& array, size_t expected) { |
|
if (expected == 0) { |
|
ASSERT_EQ(array.type(), Json::Type::JSON_NULL); |
|
} else { |
|
ASSERT_EQ(array.type(), Json::Type::ARRAY); |
|
EXPECT_EQ(array.array_value().size(), expected); |
|
} |
|
} |
|
|
|
void ValidateJsonEnd(const Json& json, bool end) { |
|
auto it = json.object_value().find("end"); |
|
if (end) { |
|
ASSERT_NE(it, json.object_value().end()); |
|
EXPECT_EQ(it->second.type(), Json::Type::JSON_TRUE); |
|
} else { |
|
ASSERT_EQ(it, json.object_value().end()); |
|
} |
|
} |
|
|
|
void ValidateGetTopChannels(size_t expected_channels) { |
|
std::string json_str = ChannelzRegistry::GetTopChannels(0); |
|
grpc::testing::ValidateGetTopChannelsResponseProtoJsonTranslation( |
|
json_str.c_str()); |
|
grpc_error* error = GRPC_ERROR_NONE; |
|
Json parsed_json = Json::Parse(json_str, &error); |
|
ASSERT_EQ(error, GRPC_ERROR_NONE) << grpc_error_string(error); |
|
ASSERT_EQ(parsed_json.type(), Json::Type::OBJECT); |
|
// This check will naturally have to change when we support pagination. |
|
// tracked: https://github.com/grpc/grpc/issues/16019. |
|
ValidateJsonArraySize((*parsed_json.mutable_object())["channel"], |
|
expected_channels); |
|
ValidateJsonEnd(parsed_json, true); |
|
// Also check that the core API formats this correctly. |
|
char* core_api_json_str = grpc_channelz_get_top_channels(0); |
|
grpc::testing::ValidateGetTopChannelsResponseProtoJsonTranslation( |
|
core_api_json_str); |
|
gpr_free(core_api_json_str); |
|
} |
|
|
|
void ValidateGetServers(size_t expected_servers) { |
|
std::string json_str = ChannelzRegistry::GetServers(0); |
|
grpc::testing::ValidateGetServersResponseProtoJsonTranslation( |
|
json_str.c_str()); |
|
grpc_error* error = GRPC_ERROR_NONE; |
|
Json parsed_json = Json::Parse(json_str, &error); |
|
ASSERT_EQ(error, GRPC_ERROR_NONE) << grpc_error_string(error); |
|
ASSERT_EQ(parsed_json.type(), Json::Type::OBJECT); |
|
// This check will naturally have to change when we support pagination. |
|
// tracked: https://github.com/grpc/grpc/issues/16019. |
|
ValidateJsonArraySize((*parsed_json.mutable_object())["server"], |
|
expected_servers); |
|
ValidateJsonEnd(parsed_json, true); |
|
// Also check that the core API formats this correctly. |
|
char* core_api_json_str = grpc_channelz_get_servers(0); |
|
grpc::testing::ValidateGetServersResponseProtoJsonTranslation( |
|
core_api_json_str); |
|
gpr_free(core_api_json_str); |
|
} |
|
|
|
class ChannelFixture { |
|
public: |
|
ChannelFixture(int max_tracer_event_memory = 0) { |
|
grpc_arg client_a[] = { |
|
grpc_channel_arg_integer_create( |
|
const_cast<char*>(GRPC_ARG_MAX_CHANNEL_TRACE_EVENT_MEMORY_PER_NODE), |
|
max_tracer_event_memory), |
|
grpc_channel_arg_integer_create( |
|
const_cast<char*>(GRPC_ARG_ENABLE_CHANNELZ), true)}; |
|
grpc_channel_args client_args = {GPR_ARRAY_SIZE(client_a), client_a}; |
|
channel_ = |
|
grpc_insecure_channel_create("fake_target", &client_args, nullptr); |
|
} |
|
|
|
~ChannelFixture() { grpc_channel_destroy(channel_); } |
|
|
|
grpc_channel* channel() { return channel_; } |
|
|
|
private: |
|
grpc_channel* channel_; |
|
}; |
|
|
|
class ServerFixture { |
|
public: |
|
explicit ServerFixture(int max_tracer_event_memory = 0) { |
|
grpc_arg server_a[] = { |
|
grpc_channel_arg_integer_create( |
|
const_cast<char*>(GRPC_ARG_MAX_CHANNEL_TRACE_EVENT_MEMORY_PER_NODE), |
|
max_tracer_event_memory), |
|
grpc_channel_arg_integer_create( |
|
const_cast<char*>(GRPC_ARG_ENABLE_CHANNELZ), true), |
|
}; |
|
grpc_channel_args server_args = {GPR_ARRAY_SIZE(server_a), server_a}; |
|
server_ = grpc_server_create(&server_args, nullptr); |
|
} |
|
|
|
~ServerFixture() { grpc_server_destroy(server_); } |
|
|
|
grpc_server* server() const { return server_; } |
|
|
|
private: |
|
grpc_server* server_; |
|
}; |
|
|
|
struct ValidateChannelDataArgs { |
|
int64_t calls_started; |
|
int64_t calls_failed; |
|
int64_t calls_succeeded; |
|
}; |
|
|
|
void ValidateChildInteger(const Json::Object& object, const std::string& key, |
|
int64_t expected) { |
|
auto it = object.find(key); |
|
if (expected == 0) { |
|
ASSERT_EQ(it, object.end()); |
|
return; |
|
} |
|
ASSERT_NE(it, object.end()); |
|
ASSERT_EQ(it->second.type(), Json::Type::STRING); |
|
int64_t gotten_number = |
|
(int64_t)strtol(it->second.string_value().c_str(), nullptr, 0); |
|
EXPECT_EQ(gotten_number, expected); |
|
} |
|
|
|
void ValidateCounters(const std::string& json_str, |
|
const ValidateChannelDataArgs& args) { |
|
grpc_error* error = GRPC_ERROR_NONE; |
|
Json json = Json::Parse(json_str, &error); |
|
ASSERT_EQ(error, GRPC_ERROR_NONE) << grpc_error_string(error); |
|
ASSERT_EQ(json.type(), Json::Type::OBJECT); |
|
Json::Object* object = json.mutable_object(); |
|
Json& data = (*object)["data"]; |
|
ASSERT_EQ(data.type(), Json::Type::OBJECT); |
|
ValidateChildInteger(data.object_value(), "callsStarted", args.calls_started); |
|
ValidateChildInteger(data.object_value(), "callsFailed", args.calls_failed); |
|
ValidateChildInteger(data.object_value(), "callsSucceeded", |
|
args.calls_succeeded); |
|
} |
|
|
|
void ValidateChannel(ChannelNode* channel, |
|
const ValidateChannelDataArgs& args) { |
|
std::string json_str = channel->RenderJsonString(); |
|
grpc::testing::ValidateChannelProtoJsonTranslation(json_str.c_str()); |
|
ValidateCounters(json_str, args); |
|
// also check that the core API formats this the correct way |
|
char* core_api_json_str = grpc_channelz_get_channel(channel->uuid()); |
|
grpc::testing::ValidateGetChannelResponseProtoJsonTranslation( |
|
core_api_json_str); |
|
gpr_free(core_api_json_str); |
|
} |
|
|
|
void ValidateServer(ServerNode* server, const ValidateChannelDataArgs& args) { |
|
std::string json_str = server->RenderJsonString(); |
|
grpc::testing::ValidateServerProtoJsonTranslation(json_str.c_str()); |
|
ValidateCounters(json_str, args); |
|
// also check that the core API formats this the correct way |
|
char* core_api_json_str = grpc_channelz_get_server(server->uuid()); |
|
grpc::testing::ValidateGetServerResponseProtoJsonTranslation( |
|
core_api_json_str); |
|
gpr_free(core_api_json_str); |
|
} |
|
|
|
gpr_timespec GetLastCallStartedTime(CallCountingHelper* channel) { |
|
CallCountingHelperPeer peer(channel); |
|
return peer.last_call_started_time(); |
|
} |
|
|
|
void ChannelzSleep(int64_t sleep_us) { |
|
gpr_sleep_until(gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), |
|
gpr_time_from_micros(sleep_us, GPR_TIMESPAN))); |
|
grpc_core::ExecCtx::Get()->InvalidateNow(); |
|
} |
|
|
|
} // anonymous namespace |
|
|
|
class ChannelzChannelTest : public ::testing::TestWithParam<size_t> {}; |
|
|
|
TEST_P(ChannelzChannelTest, BasicChannel) { |
|
grpc_core::ExecCtx exec_ctx; |
|
ChannelFixture channel(GetParam()); |
|
ChannelNode* channelz_channel = |
|
grpc_channel_get_channelz_node(channel.channel()); |
|
ValidateChannel(channelz_channel, {0, 0, 0}); |
|
} |
|
|
|
TEST(ChannelzChannelTest, ChannelzDisabled) { |
|
grpc_core::ExecCtx exec_ctx; |
|
// explicitly disable channelz |
|
grpc_arg arg[] = { |
|
grpc_channel_arg_integer_create( |
|
const_cast<char*>(GRPC_ARG_MAX_CHANNEL_TRACE_EVENT_MEMORY_PER_NODE), |
|
0), |
|
grpc_channel_arg_integer_create( |
|
const_cast<char*>(GRPC_ARG_ENABLE_CHANNELZ), false)}; |
|
grpc_channel_args args = {GPR_ARRAY_SIZE(arg), arg}; |
|
grpc_channel* channel = |
|
grpc_insecure_channel_create("fake_target", &args, nullptr); |
|
ChannelNode* channelz_channel = grpc_channel_get_channelz_node(channel); |
|
ASSERT_EQ(channelz_channel, nullptr); |
|
grpc_channel_destroy(channel); |
|
} |
|
|
|
TEST_P(ChannelzChannelTest, BasicChannelAPIFunctionality) { |
|
grpc_core::ExecCtx exec_ctx; |
|
ChannelFixture channel(GetParam()); |
|
ChannelNode* channelz_channel = |
|
grpc_channel_get_channelz_node(channel.channel()); |
|
channelz_channel->RecordCallStarted(); |
|
channelz_channel->RecordCallFailed(); |
|
channelz_channel->RecordCallSucceeded(); |
|
ValidateChannel(channelz_channel, {1, 1, 1}); |
|
channelz_channel->RecordCallStarted(); |
|
channelz_channel->RecordCallFailed(); |
|
channelz_channel->RecordCallSucceeded(); |
|
channelz_channel->RecordCallStarted(); |
|
channelz_channel->RecordCallFailed(); |
|
channelz_channel->RecordCallSucceeded(); |
|
ValidateChannel(channelz_channel, {3, 3, 3}); |
|
} |
|
|
|
TEST_P(ChannelzChannelTest, LastCallStartedTime) { |
|
grpc_core::ExecCtx exec_ctx; |
|
CallCountingHelper counter; |
|
// start a call to set the last call started timestamp |
|
counter.RecordCallStarted(); |
|
gpr_timespec time1 = GetLastCallStartedTime(&counter); |
|
// time gone by should not affect the timestamp |
|
ChannelzSleep(100); |
|
gpr_timespec time2 = GetLastCallStartedTime(&counter); |
|
EXPECT_EQ(gpr_time_cmp(time1, time2), 0); |
|
// calls succeeded or failed should not affect the timestamp |
|
ChannelzSleep(100); |
|
counter.RecordCallFailed(); |
|
counter.RecordCallSucceeded(); |
|
gpr_timespec time3 = GetLastCallStartedTime(&counter); |
|
EXPECT_EQ(gpr_time_cmp(time1, time3), 0); |
|
// another call started should affect the timestamp |
|
// sleep for extra long to avoid flakes (since we cache Now()) |
|
ChannelzSleep(5000); |
|
counter.RecordCallStarted(); |
|
gpr_timespec time4 = GetLastCallStartedTime(&counter); |
|
EXPECT_NE(gpr_time_cmp(time1, time4), 0); |
|
} |
|
|
|
class ChannelzRegistryBasedTest : public ::testing::TestWithParam<size_t> { |
|
protected: |
|
// ensure we always have a fresh registry for tests. |
|
void SetUp() override { |
|
ChannelzRegistry::Shutdown(); |
|
ChannelzRegistry::Init(); |
|
} |
|
|
|
void TearDown() override { |
|
ChannelzRegistry::Shutdown(); |
|
ChannelzRegistry::Init(); |
|
} |
|
}; |
|
|
|
TEST_F(ChannelzRegistryBasedTest, BasicGetTopChannelsTest) { |
|
grpc_core::ExecCtx exec_ctx; |
|
ChannelFixture channel; |
|
ValidateGetTopChannels(1); |
|
} |
|
|
|
TEST_F(ChannelzRegistryBasedTest, NoChannelsTest) { |
|
grpc_core::ExecCtx exec_ctx; |
|
ValidateGetTopChannels(0); |
|
} |
|
|
|
TEST_F(ChannelzRegistryBasedTest, ManyChannelsTest) { |
|
grpc_core::ExecCtx exec_ctx; |
|
ChannelFixture channels[10]; |
|
(void)channels; // suppress unused variable error |
|
ValidateGetTopChannels(10); |
|
} |
|
|
|
TEST_F(ChannelzRegistryBasedTest, GetTopChannelsPagination) { |
|
grpc_core::ExecCtx exec_ctx; |
|
// This is over the pagination limit. |
|
ChannelFixture channels[150]; |
|
(void)channels; // suppress unused variable error |
|
std::string json_str = ChannelzRegistry::GetTopChannels(0); |
|
grpc::testing::ValidateGetTopChannelsResponseProtoJsonTranslation( |
|
json_str.c_str()); |
|
grpc_error* error = GRPC_ERROR_NONE; |
|
Json parsed_json = Json::Parse(json_str, &error); |
|
ASSERT_EQ(error, GRPC_ERROR_NONE) << grpc_error_string(error); |
|
ASSERT_EQ(parsed_json.type(), Json::Type::OBJECT); |
|
// 100 is the pagination limit. |
|
ValidateJsonArraySize((*parsed_json.mutable_object())["channel"], 100); |
|
ValidateJsonEnd(parsed_json, false); |
|
// Now we get the rest. |
|
json_str = ChannelzRegistry::GetTopChannels(101); |
|
grpc::testing::ValidateGetTopChannelsResponseProtoJsonTranslation( |
|
json_str.c_str()); |
|
error = GRPC_ERROR_NONE; |
|
parsed_json = Json::Parse(json_str, &error); |
|
ASSERT_EQ(error, GRPC_ERROR_NONE) << grpc_error_string(error); |
|
ASSERT_EQ(parsed_json.type(), Json::Type::OBJECT); |
|
ValidateJsonArraySize((*parsed_json.mutable_object())["channel"], 50); |
|
ValidateJsonEnd(parsed_json, true); |
|
} |
|
|
|
TEST_F(ChannelzRegistryBasedTest, GetTopChannelsUuidCheck) { |
|
const intptr_t kNumChannels = 50; |
|
grpc_core::ExecCtx exec_ctx; |
|
ChannelFixture channels[kNumChannels]; |
|
(void)channels; // suppress unused variable error |
|
std::string json_str = ChannelzRegistry::GetTopChannels(0); |
|
grpc_error* error = GRPC_ERROR_NONE; |
|
Json parsed_json = Json::Parse(json_str, &error); |
|
ASSERT_EQ(error, GRPC_ERROR_NONE) << grpc_error_string(error); |
|
ASSERT_EQ(parsed_json.type(), Json::Type::OBJECT); |
|
Json& array = (*parsed_json.mutable_object())["channel"]; |
|
ValidateJsonArraySize(array, kNumChannels); |
|
std::vector<intptr_t> uuids = GetUuidListFromArray(array.array_value()); |
|
for (int i = 0; i < kNumChannels; ++i) { |
|
EXPECT_EQ(i + 1, uuids[i]); |
|
} |
|
} |
|
|
|
TEST_F(ChannelzRegistryBasedTest, GetTopChannelsMiddleUuidCheck) { |
|
const intptr_t kNumChannels = 50; |
|
const intptr_t kMidQuery = 40; |
|
grpc_core::ExecCtx exec_ctx; |
|
ChannelFixture channels[kNumChannels]; |
|
(void)channels; // suppress unused variable error |
|
// Only query for the end of the channels. |
|
std::string json_str = ChannelzRegistry::GetTopChannels(kMidQuery); |
|
grpc_error* error = GRPC_ERROR_NONE; |
|
Json parsed_json = Json::Parse(json_str, &error); |
|
ASSERT_EQ(error, GRPC_ERROR_NONE) << grpc_error_string(error); |
|
ASSERT_EQ(parsed_json.type(), Json::Type::OBJECT); |
|
Json& array = (*parsed_json.mutable_object())["channel"]; |
|
ValidateJsonArraySize(array, kNumChannels - kMidQuery + 1); |
|
std::vector<intptr_t> uuids = GetUuidListFromArray(array.array_value()); |
|
for (int i = 0; i < uuids.size(); ++i) { |
|
EXPECT_EQ(static_cast<intptr_t>(kMidQuery + i), uuids[i]); |
|
} |
|
} |
|
|
|
TEST_F(ChannelzRegistryBasedTest, GetTopChannelsNoHitUuid) { |
|
grpc_core::ExecCtx exec_ctx; |
|
ChannelFixture pre_channels[40]; // will take uuid[1, 40] |
|
(void)pre_channels; // suppress unused variable error |
|
ServerFixture servers[10]; // will take uuid[41, 50] |
|
(void)servers; // suppress unused variable error |
|
ChannelFixture channels[10]; // will take uuid[51, 60] |
|
(void)channels; // suppress unused variable error |
|
// Query in the middle of the server channels. |
|
std::string json_str = ChannelzRegistry::GetTopChannels(45); |
|
grpc_error* error = GRPC_ERROR_NONE; |
|
Json parsed_json = Json::Parse(json_str, &error); |
|
ASSERT_EQ(error, GRPC_ERROR_NONE) << grpc_error_string(error); |
|
ASSERT_EQ(parsed_json.type(), Json::Type::OBJECT); |
|
Json& array = (*parsed_json.mutable_object())["channel"]; |
|
ValidateJsonArraySize(array, 10); |
|
std::vector<intptr_t> uuids = GetUuidListFromArray(array.array_value()); |
|
for (int i = 0; i < uuids.size(); ++i) { |
|
EXPECT_EQ(static_cast<intptr_t>(51 + i), uuids[i]); |
|
} |
|
} |
|
|
|
TEST_F(ChannelzRegistryBasedTest, GetTopChannelsMoreGaps) { |
|
grpc_core::ExecCtx exec_ctx; |
|
ChannelFixture channel_with_uuid1; |
|
{ ServerFixture channel_with_uuid2; } |
|
ChannelFixture channel_with_uuid3; |
|
{ ServerFixture server_with_uuid4; } |
|
ChannelFixture channel_with_uuid5; |
|
// Current state of list: [1, NULL, 3, NULL, 5] |
|
std::string json_str = ChannelzRegistry::GetTopChannels(2); |
|
grpc_error* error = GRPC_ERROR_NONE; |
|
Json parsed_json = Json::Parse(json_str, &error); |
|
ASSERT_EQ(error, GRPC_ERROR_NONE) << grpc_error_string(error); |
|
ASSERT_EQ(parsed_json.type(), Json::Type::OBJECT); |
|
Json array = (*parsed_json.mutable_object())["channel"]; |
|
ValidateJsonArraySize(array, 2); |
|
std::vector<intptr_t> uuids = GetUuidListFromArray(array.array_value()); |
|
EXPECT_EQ(static_cast<intptr_t>(3), uuids[0]); |
|
EXPECT_EQ(static_cast<intptr_t>(5), uuids[1]); |
|
json_str = ChannelzRegistry::GetTopChannels(4); |
|
error = GRPC_ERROR_NONE; |
|
parsed_json = Json::Parse(json_str, &error); |
|
ASSERT_EQ(error, GRPC_ERROR_NONE) << grpc_error_string(error); |
|
ASSERT_EQ(parsed_json.type(), Json::Type::OBJECT); |
|
array = (*parsed_json.mutable_object())["channel"]; |
|
ValidateJsonArraySize(array, 1); |
|
uuids = GetUuidListFromArray(array.array_value()); |
|
EXPECT_EQ(static_cast<intptr_t>(5), uuids[0]); |
|
} |
|
|
|
TEST_F(ChannelzRegistryBasedTest, GetTopChannelsUuidAfterCompaction) { |
|
const intptr_t kLoopIterations = 50; |
|
grpc_core::ExecCtx exec_ctx; |
|
std::vector<std::unique_ptr<ChannelFixture>> even_channels; |
|
{ |
|
// these will delete and unregister themselves after this block. |
|
std::vector<std::unique_ptr<ChannelFixture>> odd_channels; |
|
for (int i = 0; i < kLoopIterations; i++) { |
|
odd_channels.push_back(absl::make_unique<ChannelFixture>()); |
|
even_channels.push_back(absl::make_unique<ChannelFixture>()); |
|
} |
|
} |
|
std::string json_str = ChannelzRegistry::GetTopChannels(0); |
|
grpc_error* error = GRPC_ERROR_NONE; |
|
Json parsed_json = Json::Parse(json_str, &error); |
|
ASSERT_EQ(error, GRPC_ERROR_NONE) << grpc_error_string(error); |
|
ASSERT_EQ(parsed_json.type(), Json::Type::OBJECT); |
|
Json& array = (*parsed_json.mutable_object())["channel"]; |
|
ValidateJsonArraySize(array, kLoopIterations); |
|
std::vector<intptr_t> uuids = GetUuidListFromArray(array.array_value()); |
|
for (int i = 0; i < kLoopIterations; ++i) { |
|
// only the even uuids will still be present. |
|
EXPECT_EQ((i + 1) * 2, uuids[i]); |
|
} |
|
} |
|
|
|
TEST_F(ChannelzRegistryBasedTest, InternalChannelTest) { |
|
grpc_core::ExecCtx exec_ctx; |
|
ChannelFixture channels[10]; |
|
(void)channels; // suppress unused variable error |
|
// create an internal channel |
|
grpc_arg client_a[2]; |
|
client_a[0] = grpc_core::channelz::MakeParentUuidArg(1); |
|
client_a[1] = grpc_channel_arg_integer_create( |
|
const_cast<char*>(GRPC_ARG_ENABLE_CHANNELZ), true); |
|
grpc_channel_args client_args = {GPR_ARRAY_SIZE(client_a), client_a}; |
|
grpc_channel* internal_channel = |
|
grpc_insecure_channel_create("fake_target", &client_args, nullptr); |
|
// The internal channel should not be returned from the request |
|
ValidateGetTopChannels(10); |
|
grpc_channel_destroy(internal_channel); |
|
} |
|
|
|
TEST(ChannelzServerTest, BasicServerAPIFunctionality) { |
|
grpc_core::ExecCtx exec_ctx; |
|
ServerFixture server(10); |
|
ServerNode* channelz_server = grpc_server_get_channelz_node(server.server()); |
|
channelz_server->RecordCallStarted(); |
|
channelz_server->RecordCallFailed(); |
|
channelz_server->RecordCallSucceeded(); |
|
ValidateServer(channelz_server, {1, 1, 1}); |
|
channelz_server->RecordCallStarted(); |
|
channelz_server->RecordCallFailed(); |
|
channelz_server->RecordCallSucceeded(); |
|
channelz_server->RecordCallStarted(); |
|
channelz_server->RecordCallFailed(); |
|
channelz_server->RecordCallSucceeded(); |
|
ValidateServer(channelz_server, {3, 3, 3}); |
|
} |
|
|
|
TEST_F(ChannelzRegistryBasedTest, BasicGetServersTest) { |
|
grpc_core::ExecCtx exec_ctx; |
|
ServerFixture server; |
|
ValidateGetServers(1); |
|
} |
|
|
|
TEST_F(ChannelzRegistryBasedTest, NoServersTest) { |
|
grpc_core::ExecCtx exec_ctx; |
|
ValidateGetServers(0); |
|
} |
|
|
|
TEST_F(ChannelzRegistryBasedTest, ManyServersTest) { |
|
grpc_core::ExecCtx exec_ctx; |
|
ServerFixture servers[10]; |
|
(void)servers; // suppress unused variable error |
|
ValidateGetServers(10); |
|
} |
|
|
|
INSTANTIATE_TEST_SUITE_P(ChannelzChannelTestSweep, ChannelzChannelTest, |
|
::testing::Values(0, 8, 64, 1024, 1024 * 1024)); |
|
|
|
} // namespace testing |
|
} // namespace channelz |
|
} // namespace grpc_core |
|
|
|
int main(int argc, char** argv) { |
|
grpc::testing::TestEnvironment env(argc, argv); |
|
grpc_init(); |
|
::testing::InitGoogleTest(&argc, argv); |
|
int ret = RUN_ALL_TESTS(); |
|
grpc_shutdown(); |
|
return ret; |
|
}
|
|
|