aboutsummaryrefslogtreecommitdiffhomepage
path: root/test/core/channel/channelz_test.cc
diff options
context:
space:
mode:
Diffstat (limited to 'test/core/channel/channelz_test.cc')
-rw-r--r--test/core/channel/channelz_test.cc324
1 files changed, 291 insertions, 33 deletions
diff --git a/test/core/channel/channelz_test.cc b/test/core/channel/channelz_test.cc
index ad5f86d934..4d4b077002 100644
--- a/test/core/channel/channelz_test.cc
+++ b/test/core/channel/channelz_test.cc
@@ -31,6 +31,7 @@
#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"
@@ -44,16 +45,17 @@ namespace channelz {
namespace testing {
// testing peer to access channel internals
-class ChannelNodePeer {
+class CallCountingHelperPeer {
public:
- ChannelNodePeer(ChannelNode* channel) : channel_(channel) {}
- grpc_millis last_call_started_millis() {
- return (grpc_millis)gpr_atm_no_barrier_load(
- &channel_->last_call_started_millis_);
+ explicit CallCountingHelperPeer(CallCountingHelper* node) : node_(node) {}
+ grpc_millis last_call_started_millis() const {
+ CallCountingHelper::CounterData data;
+ node_->CollectData(&data);
+ return (grpc_millis)gpr_atm_no_barrier_load(&data.last_call_started_millis);
}
private:
- ChannelNode* channel_;
+ CallCountingHelper* node_;
};
namespace {
@@ -83,6 +85,19 @@ void ValidateJsonArraySize(grpc_json* json, const char* key,
EXPECT_EQ(count, expected_size);
}
+std::vector<intptr_t> GetUuidListFromArray(grpc_json* arr) {
+ EXPECT_EQ(arr->type, GRPC_JSON_ARRAY);
+ std::vector<intptr_t> uuids;
+ for (grpc_json* child = arr->child; child != nullptr; child = child->next) {
+ grpc_json* it = GetJsonChild(child, "ref");
+ EXPECT_NE(it, nullptr);
+ it = GetJsonChild(it, "channelId");
+ EXPECT_NE(it, nullptr);
+ uuids.push_back(atoi(it->value));
+ }
+ return uuids;
+}
+
void ValidateGetTopChannels(size_t expected_channels) {
char* json_str = ChannelzRegistry::GetTopChannels(0);
grpc::testing::ValidateGetTopChannelsResponseProtoJsonTranslation(json_str);
@@ -102,15 +117,34 @@ void ValidateGetTopChannels(size_t expected_channels) {
gpr_free(core_api_json_str);
}
+void ValidateGetServers(size_t expected_servers) {
+ char* json_str = ChannelzRegistry::GetServers(0);
+ grpc::testing::ValidateGetServersResponseProtoJsonTranslation(json_str);
+ grpc_json* parsed_json = grpc_json_parse_string(json_str);
+ // This check will naturally have to change when we support pagination.
+ // tracked: https://github.com/grpc/grpc/issues/16019.
+ ValidateJsonArraySize(parsed_json, "server", expected_servers);
+ grpc_json* end = GetJsonChild(parsed_json, "end");
+ ASSERT_NE(end, nullptr);
+ EXPECT_EQ(end->type, GRPC_JSON_TRUE);
+ grpc_json_destroy(parsed_json);
+ gpr_free(json_str);
+ // 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_trace_nodes = 0) {
- grpc_arg client_a[2];
- client_a[0] = grpc_channel_arg_integer_create(
- const_cast<char*>(GRPC_ARG_MAX_CHANNEL_TRACE_EVENTS_PER_NODE),
- max_trace_nodes);
- client_a[1] = grpc_channel_arg_integer_create(
- const_cast<char*>(GRPC_ARG_ENABLE_CHANNELZ), true);
+ 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);
@@ -124,6 +158,28 @@ class ChannelFixture {
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 validate_channel_data_args {
int64_t calls_started;
int64_t calls_failed;
@@ -157,14 +213,26 @@ void ValidateChannel(ChannelNode* channel, validate_channel_data_args args) {
ValidateCounters(json_str, args);
gpr_free(json_str);
// also check that the core API formats this the correct way
- char* core_api_json_str = grpc_channelz_get_channel(channel->channel_uuid());
+ char* core_api_json_str = grpc_channelz_get_channel(channel->uuid());
grpc::testing::ValidateGetChannelResponseProtoJsonTranslation(
core_api_json_str);
gpr_free(core_api_json_str);
}
-grpc_millis GetLastCallStartedMillis(ChannelNode* channel) {
- ChannelNodePeer peer(channel);
+void ValidateServer(ServerNode* server, validate_channel_data_args args) {
+ char* json_str = server->RenderJsonString();
+ grpc::testing::ValidateServerProtoJsonTranslation(json_str);
+ ValidateCounters(json_str, args);
+ gpr_free(json_str);
+ // 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);
+}
+
+grpc_millis GetLastCallStartedMillis(CallCountingHelper* channel) {
+ CallCountingHelperPeer peer(channel);
return peer.last_call_started_millis();
}
@@ -188,8 +256,16 @@ TEST_P(ChannelzChannelTest, BasicChannel) {
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", nullptr, nullptr);
+ 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);
@@ -215,49 +291,196 @@ TEST_P(ChannelzChannelTest, BasicChannelAPIFunctionality) {
TEST_P(ChannelzChannelTest, LastCallStartedMillis) {
grpc_core::ExecCtx exec_ctx;
- ChannelFixture channel(GetParam());
- ChannelNode* channelz_channel =
- grpc_channel_get_channelz_node(channel.channel());
+ CallCountingHelper counter;
// start a call to set the last call started timestamp
- channelz_channel->RecordCallStarted();
- grpc_millis millis1 = GetLastCallStartedMillis(channelz_channel);
+ counter.RecordCallStarted();
+ grpc_millis millis1 = GetLastCallStartedMillis(&counter);
// time gone by should not affect the timestamp
ChannelzSleep(100);
- grpc_millis millis2 = GetLastCallStartedMillis(channelz_channel);
+ grpc_millis millis2 = GetLastCallStartedMillis(&counter);
EXPECT_EQ(millis1, millis2);
// calls succeeded or failed should not affect the timestamp
ChannelzSleep(100);
- channelz_channel->RecordCallFailed();
- channelz_channel->RecordCallSucceeded();
- grpc_millis millis3 = GetLastCallStartedMillis(channelz_channel);
+ counter.RecordCallFailed();
+ counter.RecordCallSucceeded();
+ grpc_millis millis3 = GetLastCallStartedMillis(&counter);
EXPECT_EQ(millis1, millis3);
// another call started should affect the timestamp
// sleep for extra long to avoid flakes (since we cache Now())
ChannelzSleep(5000);
- channelz_channel->RecordCallStarted();
- grpc_millis millis4 = GetLastCallStartedMillis(channelz_channel);
+ counter.RecordCallStarted();
+ grpc_millis millis4 = GetLastCallStartedMillis(&counter);
EXPECT_NE(millis1, millis4);
}
-TEST(ChannelzGetTopChannelsTest, BasicTest) {
+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(ChannelzGetTopChannelsTest, NoChannelsTest) {
+TEST_F(ChannelzRegistryBasedTest, NoChannelsTest) {
grpc_core::ExecCtx exec_ctx;
ValidateGetTopChannels(0);
}
-TEST(ChannelzGetTopChannelsTest, ManyChannelsTest) {
+TEST_F(ChannelzRegistryBasedTest, ManyChannelsTest) {
grpc_core::ExecCtx exec_ctx;
ChannelFixture channels[10];
(void)channels; // suppress unused variable error
ValidateGetTopChannels(10);
}
-TEST(ChannelzGetTopChannelsTest, InternalChannelTest) {
+TEST_F(ChannelzRegistryBasedTest, GetTopChannelsPagination) {
+ grpc_core::ExecCtx exec_ctx;
+ // this is over the pagination limit.
+ ChannelFixture channels[150];
+ (void)channels; // suppress unused variable error
+ char* json_str = ChannelzRegistry::GetTopChannels(0);
+ grpc::testing::ValidateGetTopChannelsResponseProtoJsonTranslation(json_str);
+ grpc_json* parsed_json = grpc_json_parse_string(json_str);
+ // 100 is the pagination limit.
+ ValidateJsonArraySize(parsed_json, "channel", 100);
+ grpc_json* end = GetJsonChild(parsed_json, "end");
+ EXPECT_EQ(end, nullptr);
+ grpc_json_destroy(parsed_json);
+ gpr_free(json_str);
+ // Now we get the rest
+ json_str = ChannelzRegistry::GetTopChannels(101);
+ grpc::testing::ValidateGetTopChannelsResponseProtoJsonTranslation(json_str);
+ parsed_json = grpc_json_parse_string(json_str);
+ ValidateJsonArraySize(parsed_json, "channel", 50);
+ end = GetJsonChild(parsed_json, "end");
+ ASSERT_NE(end, nullptr);
+ EXPECT_EQ(end->type, GRPC_JSON_TRUE);
+ grpc_json_destroy(parsed_json);
+ gpr_free(json_str);
+}
+
+TEST_F(ChannelzRegistryBasedTest, GetTopChannelsUuidCheck) {
+ const intptr_t kNumChannels = 50;
+ grpc_core::ExecCtx exec_ctx;
+ ChannelFixture channels[kNumChannels];
+ (void)channels; // suppress unused variable error
+ char* json_str = ChannelzRegistry::GetTopChannels(0);
+ grpc_json* parsed_json = grpc_json_parse_string(json_str);
+ ValidateJsonArraySize(parsed_json, "channel", kNumChannels);
+ grpc_json* json_channels = GetJsonChild(parsed_json, "channel");
+ std::vector<intptr_t> uuids = GetUuidListFromArray(json_channels);
+ for (int i = 0; i < kNumChannels; ++i) {
+ EXPECT_EQ(i + 1, uuids[i]);
+ }
+ grpc_json_destroy(parsed_json);
+ gpr_free(json_str);
+}
+
+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
+ char* json_str = ChannelzRegistry::GetTopChannels(kMidQuery);
+ grpc_json* parsed_json = grpc_json_parse_string(json_str);
+ ValidateJsonArraySize(parsed_json, "channel", kNumChannels - kMidQuery + 1);
+ grpc_json* json_channels = GetJsonChild(parsed_json, "channel");
+ std::vector<intptr_t> uuids = GetUuidListFromArray(json_channels);
+ for (size_t i = 0; i < uuids.size(); ++i) {
+ EXPECT_EQ(static_cast<intptr_t>(kMidQuery + i), uuids[i]);
+ }
+ grpc_json_destroy(parsed_json);
+ gpr_free(json_str);
+}
+
+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
+ char* json_str = ChannelzRegistry::GetTopChannels(45);
+ grpc_json* parsed_json = grpc_json_parse_string(json_str);
+ ValidateJsonArraySize(parsed_json, "channel", 10);
+ grpc_json* json_channels = GetJsonChild(parsed_json, "channel");
+ std::vector<intptr_t> uuids = GetUuidListFromArray(json_channels);
+ for (size_t i = 0; i < uuids.size(); ++i) {
+ EXPECT_EQ(static_cast<intptr_t>(51 + i), uuids[i]);
+ }
+ grpc_json_destroy(parsed_json);
+ gpr_free(json_str);
+}
+
+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]
+ char* json_str = ChannelzRegistry::GetTopChannels(2);
+ grpc_json* parsed_json = grpc_json_parse_string(json_str);
+ ValidateJsonArraySize(parsed_json, "channel", 2);
+ grpc_json* json_channels = GetJsonChild(parsed_json, "channel");
+ std::vector<intptr_t> uuids = GetUuidListFromArray(json_channels);
+ EXPECT_EQ(static_cast<intptr_t>(3), uuids[0]);
+ EXPECT_EQ(static_cast<intptr_t>(5), uuids[1]);
+ grpc_json_destroy(parsed_json);
+ gpr_free(json_str);
+ json_str = ChannelzRegistry::GetTopChannels(4);
+ parsed_json = grpc_json_parse_string(json_str);
+ ValidateJsonArraySize(parsed_json, "channel", 1);
+ json_channels = GetJsonChild(parsed_json, "channel");
+ uuids = GetUuidListFromArray(json_channels);
+ EXPECT_EQ(static_cast<intptr_t>(5), uuids[0]);
+ grpc_json_destroy(parsed_json);
+ gpr_free(json_str);
+}
+
+TEST_F(ChannelzRegistryBasedTest, GetTopChannelsUuidAfterCompaction) {
+ const intptr_t kLoopIterations = 50;
+ grpc_core::ExecCtx exec_ctx;
+ std::vector<UniquePtr<ChannelFixture>> even_channels;
+ {
+ // these will delete and unregister themselves after this block.
+ std::vector<UniquePtr<ChannelFixture>> odd_channels;
+ for (int i = 0; i < kLoopIterations; i++) {
+ odd_channels.push_back(MakeUnique<ChannelFixture>());
+ even_channels.push_back(MakeUnique<ChannelFixture>());
+ }
+ }
+ char* json_str = ChannelzRegistry::GetTopChannels(0);
+ grpc_json* parsed_json = grpc_json_parse_string(json_str);
+ ValidateJsonArraySize(parsed_json, "channel", kLoopIterations);
+ grpc_json* json_channels = GetJsonChild(parsed_json, "channel");
+ std::vector<intptr_t> uuids = GetUuidListFromArray(json_channels);
+ for (int i = 0; i < kLoopIterations; ++i) {
+ // only the even uuids will still be present.
+ EXPECT_EQ((i + 1) * 2, uuids[i]);
+ }
+ grpc_json_destroy(parsed_json);
+ gpr_free(json_str);
+}
+
+TEST_F(ChannelzRegistryBasedTest, InternalChannelTest) {
grpc_core::ExecCtx exec_ctx;
ChannelFixture channels[10];
(void)channels; // suppress unused variable error
@@ -275,8 +498,43 @@ TEST(ChannelzGetTopChannelsTest, InternalChannelTest) {
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_CASE_P(ChannelzChannelTestSweep, ChannelzChannelTest,
- ::testing::Values(0, 1, 2, 6, 10, 15));
+ ::testing::Values(0, 8, 64, 1024, 1024 * 1024));
} // namespace testing
} // namespace channelz