31841f9f967d843fc1f218e39bc943e958e6fc38
[platform/upstream/grpc.git] / test / core / channel / channelz_registry_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 <grpc/grpc.h>
23 #include <gtest/gtest.h>
24
25 #include <grpc/support/alloc.h>
26 #include <grpc/support/log.h>
27
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"
36
37 #include "test/core/util/test_config.h"
38
39 #include <stdlib.h>
40 #include <string.h>
41
42 namespace grpc_core {
43 namespace channelz {
44 namespace testing {
45
46 class ChannelzRegistryPeer {
47  public:
48   const InlinedVector<BaseNode*, 20>* entities() {
49     return &ChannelzRegistry::Default()->entities_;
50   }
51   int num_empty_slots() {
52     return ChannelzRegistry::Default()->num_empty_slots_;
53   }
54 };
55
56 class ChannelzRegistryTest : public ::testing::Test {
57  protected:
58   // ensure we always have a fresh registry for tests.
59   void SetUp() override { ChannelzRegistry::Init(); }
60
61   void TearDown() override { ChannelzRegistry::Shutdown(); }
62 };
63
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/"
71                         "A14-channelz.md";
72 }
73
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));
80   }
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";
84   }
85 }
86
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);
92 }
93
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);
101   }
102 }
103
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);
112 }
113
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);
119   {
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));
128     }
129   }
130   // without compaction, there would be exactly kLoopIterations empty slots at
131   // this point. However, one of the unregisters should have triggered
132   // compaction.
133   ChannelzRegistryPeer peer;
134   EXPECT_LT(peer.num_empty_slots(), kLoopIterations);
135 }
136
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);
144   {
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());
154     }
155   }
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);
161   }
162 }
163
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);
171   {
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());
181     }
182   }
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);
190   }
191 }
192
193 }  // namespace testing
194 }  // namespace channelz
195 }  // namespace grpc_core
196
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();
201   return ret;
202 }