3 * Copyright 2017 gRPC authors.
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
9 * http://www.apache.org/licenses/LICENSE-2.0
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.
22 #include <grpc/grpc.h>
23 #include <gtest/gtest.h>
25 #include <grpc/support/alloc.h>
26 #include <grpc/support/log.h>
28 #include "src/core/lib/channel/channel_trace.h"
29 #include "src/core/lib/channel/channelz.h"
30 #include "src/core/lib/channel/channelz_registry.h"
31 #include "src/core/lib/gpr/useful.h"
32 #include "src/core/lib/gprpp/memory.h"
33 #include "src/core/lib/iomgr/exec_ctx.h"
34 #include "src/core/lib/json/json.h"
35 #include "src/core/lib/surface/channel.h"
37 #include "test/core/util/test_config.h"
46 class ChannelzRegistryPeer {
48 const InlinedVector<BaseNode*, 20>* entities() {
49 return &ChannelzRegistry::Default()->entities_;
51 int num_empty_slots() {
52 return ChannelzRegistry::Default()->num_empty_slots_;
56 class ChannelzRegistryTest : public ::testing::Test {
58 // ensure we always have a fresh registry for tests.
59 void SetUp() override { ChannelzRegistry::Init(); }
61 void TearDown() override { ChannelzRegistry::Shutdown(); }
64 TEST_F(ChannelzRegistryTest, UuidStartsAboveZeroTest) {
65 UniquePtr<BaseNode> channelz_channel =
66 MakeUnique<BaseNode>(BaseNode::EntityType::kTopLevelChannel);
67 intptr_t uuid = channelz_channel->uuid();
68 EXPECT_GT(uuid, 0) << "First uuid chose must be greater than zero. Zero if "
69 "reserved according to "
70 "https://github.com/grpc/proposal/blob/master/"
74 TEST_F(ChannelzRegistryTest, UuidsAreIncreasing) {
75 std::vector<UniquePtr<BaseNode>> channelz_channels;
76 channelz_channels.reserve(10);
77 for (int i = 0; i < 10; ++i) {
78 channelz_channels.push_back(
79 MakeUnique<BaseNode>(BaseNode::EntityType::kTopLevelChannel));
81 for (size_t i = 1; i < channelz_channels.size(); ++i) {
82 EXPECT_LT(channelz_channels[i - 1]->uuid(), channelz_channels[i]->uuid())
83 << "Uuids must always be increasing";
87 TEST_F(ChannelzRegistryTest, RegisterGetTest) {
88 UniquePtr<BaseNode> channelz_channel =
89 MakeUnique<BaseNode>(BaseNode::EntityType::kTopLevelChannel);
90 BaseNode* retrieved = ChannelzRegistry::Get(channelz_channel->uuid());
91 EXPECT_EQ(channelz_channel.get(), retrieved);
94 TEST_F(ChannelzRegistryTest, RegisterManyItems) {
95 std::vector<UniquePtr<BaseNode>> channelz_channels;
96 for (int i = 0; i < 100; i++) {
97 channelz_channels.push_back(
98 MakeUnique<BaseNode>(BaseNode::EntityType::kTopLevelChannel));
99 BaseNode* retrieved = ChannelzRegistry::Get(channelz_channels[i]->uuid());
100 EXPECT_EQ(channelz_channels[i].get(), retrieved);
104 TEST_F(ChannelzRegistryTest, NullIfNotPresentTest) {
105 UniquePtr<BaseNode> channelz_channel =
106 MakeUnique<BaseNode>(BaseNode::EntityType::kTopLevelChannel);
107 // try to pull out a uuid that does not exist.
108 BaseNode* nonexistant = ChannelzRegistry::Get(channelz_channel->uuid() + 1);
109 EXPECT_EQ(nonexistant, nullptr);
110 BaseNode* retrieved = ChannelzRegistry::Get(channelz_channel->uuid());
111 EXPECT_EQ(channelz_channel.get(), retrieved);
114 TEST_F(ChannelzRegistryTest, TestCompaction) {
115 const int kLoopIterations = 300;
116 // These channels that will stay in the registry for the duration of the test.
117 std::vector<UniquePtr<BaseNode>> even_channels;
118 even_channels.reserve(kLoopIterations);
120 // The channels will unregister themselves at the end of the for block.
121 std::vector<UniquePtr<BaseNode>> odd_channels;
122 odd_channels.reserve(kLoopIterations);
123 for (int i = 0; i < kLoopIterations; i++) {
124 even_channels.push_back(
125 MakeUnique<BaseNode>(BaseNode::EntityType::kTopLevelChannel));
126 odd_channels.push_back(
127 MakeUnique<BaseNode>(BaseNode::EntityType::kTopLevelChannel));
130 // without compaction, there would be exactly kLoopIterations empty slots at
131 // this point. However, one of the unregisters should have triggered
133 ChannelzRegistryPeer peer;
134 EXPECT_LT(peer.num_empty_slots(), kLoopIterations);
137 TEST_F(ChannelzRegistryTest, TestGetAfterCompaction) {
138 const int kLoopIterations = 100;
139 // These channels that will stay in the registry for the duration of the test.
140 std::vector<UniquePtr<BaseNode>> even_channels;
141 even_channels.reserve(kLoopIterations);
142 std::vector<intptr_t> odd_uuids;
143 odd_uuids.reserve(kLoopIterations);
145 // The channels will unregister themselves at the end of the for block.
146 std::vector<UniquePtr<BaseNode>> odd_channels;
147 odd_channels.reserve(kLoopIterations);
148 for (int i = 0; i < kLoopIterations; i++) {
149 even_channels.push_back(
150 MakeUnique<BaseNode>(BaseNode::EntityType::kTopLevelChannel));
151 odd_channels.push_back(
152 MakeUnique<BaseNode>(BaseNode::EntityType::kTopLevelChannel));
153 odd_uuids.push_back(odd_channels[i]->uuid());
156 for (int i = 0; i < kLoopIterations; i++) {
157 BaseNode* retrieved = ChannelzRegistry::Get(even_channels[i]->uuid());
158 EXPECT_EQ(even_channels[i].get(), retrieved);
159 retrieved = ChannelzRegistry::Get(odd_uuids[i]);
160 EXPECT_EQ(retrieved, nullptr);
164 TEST_F(ChannelzRegistryTest, TestAddAfterCompaction) {
165 const int kLoopIterations = 100;
166 // These channels that will stay in the registry for the duration of the test.
167 std::vector<UniquePtr<BaseNode>> even_channels;
168 even_channels.reserve(kLoopIterations);
169 std::vector<intptr_t> odd_uuids;
170 odd_uuids.reserve(kLoopIterations);
172 // The channels will unregister themselves at the end of the for block.
173 std::vector<UniquePtr<BaseNode>> odd_channels;
174 odd_channels.reserve(kLoopIterations);
175 for (int i = 0; i < kLoopIterations; i++) {
176 even_channels.push_back(
177 MakeUnique<BaseNode>(BaseNode::EntityType::kTopLevelChannel));
178 odd_channels.push_back(
179 MakeUnique<BaseNode>(BaseNode::EntityType::kTopLevelChannel));
180 odd_uuids.push_back(odd_channels[i]->uuid());
183 std::vector<UniquePtr<BaseNode>> more_channels;
184 more_channels.reserve(kLoopIterations);
185 for (int i = 0; i < kLoopIterations; i++) {
186 more_channels.push_back(
187 MakeUnique<BaseNode>(BaseNode::EntityType::kTopLevelChannel));
188 BaseNode* retrieved = ChannelzRegistry::Get(more_channels[i]->uuid());
189 EXPECT_EQ(more_channels[i].get(), retrieved);
193 } // namespace testing
194 } // namespace channelz
195 } // namespace grpc_core
197 int main(int argc, char** argv) {
198 grpc::testing::TestEnvironment env(argc, argv);
199 ::testing::InitGoogleTest(&argc, argv);
200 int ret = RUN_ALL_TESTS();