Loading...
Searching...
No Matches
consensus_manager_test.cpp
Go to the documentation of this file.
1/*
2 * Licensed to the Apache Software Foundation (ASF) under one
3 * or more contributor license agreements. See the NOTICE file
4 * distributed with this work for additional information
5 * regarding copyright ownership. The ASF licenses this file
6 * to you under the Apache License, Version 2.0 (the
7 * "License"); you may not use this file except in compliance
8 * with the License. You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing,
13 * software distributed under the License is distributed on an
14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 * KIND, either express or implied. See the License for the
16 * specific language governing permissions and limitations
17 * under the License.
18 */
19
21
22#include <gtest/gtest.h>
23
24#include <future>
25
28
29namespace resdb {
30namespace {
31
32using ::resdb::testing::EqualsProto;
33using ::testing::_;
34using ::testing::AtLeast;
35using ::testing::Invoke;
36using ::testing::Pointee;
37using ::testing::Return;
38using ::testing::Test;
39
40ReplicaInfo GenerateReplicaInfo(const std::string& ip, int port) {
41 ReplicaInfo info;
42 info.set_ip(ip);
43 info.set_port(port);
44 return info;
45}
46
47class MockConsensusManager : public ConsensusManager {
48 public:
49 MockConsensusManager(const ResDBConfig& config) : ConsensusManager(config) {}
50
51 MOCK_METHOD(std::unique_ptr<ReplicaCommunicator>, GetReplicaClient,
52 (const std::vector<ReplicaInfo>&, bool), (override));
53 MOCK_METHOD(int, ConsensusCommit,
54 (std::unique_ptr<Context>, std::unique_ptr<Request>), (override));
55 MOCK_METHOD(std::vector<ReplicaInfo>, GetReplicas, (), (override));
56 MOCK_METHOD(std::vector<ReplicaInfo>, GetClientReplicas, (), (override));
57
58 public:
59 void BroadCast(const Request& request) {
60 return ConsensusManager::BroadCast(request);
61 }
62 void UpdateBroadCastClient() {
64 }
65
66 ReplicaCommunicator* GetBroadCastClient() {
68 }
69
70 public:
71 int Dispatch(std::unique_ptr<Context> context,
72 std::unique_ptr<Request> request) {
73 return ConsensusManager::Dispatch(std::move(context), std::move(request));
74 }
75};
76
77class ConsensusManagerTest : public Test {
78 public:
79 ConsensusManagerTest()
80 : replicas_({GenerateReplicaInfo("127.0.0.1", 1234),
81 GenerateReplicaInfo("127.0.0.1", 1235)}),
82 self_info_(GenerateReplicaInfo("127.0.0.1", 10000)),
83 config_(replicas_, self_info_, KeyInfo(), CertificateInfo()) {
84 ResConfigData data;
85 auto region = data.add_region();
86 region->set_region_id(1);
87 for (ReplicaInfo info : config_.GetReplicaInfos()) {
88 *region->add_replica_info() = info;
89 }
90 config_.SetConfigData(data);
91
93
94 impl_ = std::make_unique<MockConsensusManager>(config_);
95
96 ON_CALL(*impl_, GetReplicas).WillByDefault(Return(replicas_));
97 }
98
99 ~ConsensusManagerTest() { impl_->Stop(); }
100
101 protected:
102 std::vector<ReplicaInfo> replicas_;
103 ReplicaInfo self_info_;
104 ResDBConfig config_;
105 std::unique_ptr<MockConsensusManager> impl_;
106};
107
108TEST_F(ConsensusManagerTest, SendHB) {
109 std::promise<bool> hb;
110 std::future<bool> hb_done = hb.get_future();
111 EXPECT_CALL(*impl_, GetReplicaClient)
112 .Times(AtLeast(1))
113 .WillRepeatedly(
114 Invoke([&](const std::vector<ReplicaInfo>& replicas, bool) {
115 auto client = std::make_unique<MockReplicaCommunicator>(replicas);
116 EXPECT_CALL(*client, SendHeartBeat)
117 .WillRepeatedly(Invoke([&](const Request& hb_info) {
118 hb.set_value(true);
119 return 0;
120 }));
121 return client;
122 }));
123 impl_->Start();
124 hb_done.get();
125}
126
127TEST_F(ConsensusManagerTest, SendHBToClient) {
128 std::promise<bool> hb;
129 std::future<bool> hb_done = hb.get_future();
130
131 EXPECT_CALL(*impl_, GetClientReplicas)
132 .Times(AtLeast(1))
133 .WillRepeatedly(Invoke([&]() {
134 ReplicaInfo client_info;
135 client_info.set_ip("127.0.0.1");
136 client_info.set_port(54321);
137 return std::vector<ReplicaInfo>({client_info});
138 }));
139
140 EXPECT_CALL(*impl_, GetReplicaClient)
141 .Times(AtLeast(1))
142 .WillRepeatedly(
143 Invoke([&](const std::vector<ReplicaInfo>& replicas, bool) {
144 EXPECT_EQ(replicas.size(), 3);
145 bool find = false;
146 for (auto& info : replicas) {
147 if (info.ip() == "127.0.0.1" && info.port() == 54321) {
148 find = true;
149 }
150 }
151 EXPECT_TRUE(find);
152 auto client = std::make_unique<MockReplicaCommunicator>(replicas);
153 EXPECT_CALL(*client, SendHeartBeat)
154 .WillRepeatedly(Invoke([&](const Request& hb_info) {
155 hb.set_value(true);
156 return 0;
157 }));
158 return client;
159 }));
160 impl_->Start();
161 hb_done.get();
162}
163
164TEST_F(ConsensusManagerTest, SendHBToClientWithTworegion) {
165 ResConfigData data;
166 auto region = data.add_region();
167 region->set_region_id(1);
168 *region->add_replica_info() = GenerateReplicaInfo("127.0.0.1", 1234);
169 *region->add_replica_info() = GenerateReplicaInfo("127.0.0.1", 1235);
170
171 region = data.add_region();
172 region->set_region_id(2);
173 *region->add_replica_info() = GenerateReplicaInfo("127.0.0.1", 1234);
174 *region->add_replica_info() = GenerateReplicaInfo("127.0.0.1", 1235);
175 config_.SetConfigData(data);
176 impl_ = std::make_unique<MockConsensusManager>(config_);
177
178 std::promise<bool> hb;
179 std::future<bool> hb_done = hb.get_future();
180
181 EXPECT_CALL(*impl_, GetClientReplicas)
182 .Times(AtLeast(1))
183 .WillRepeatedly(Invoke([&]() {
184 ReplicaInfo client_info;
185 client_info.set_ip("127.0.0.1");
186 client_info.set_port(54321);
187 return std::vector<ReplicaInfo>({client_info});
188 }));
189
190 EXPECT_CALL(*impl_, GetReplicaClient)
191 .Times(AtLeast(1))
192 .WillRepeatedly(
193 Invoke([&](const std::vector<ReplicaInfo>& replicas, bool) {
194 EXPECT_EQ(replicas.size(), 5);
195 bool find = false;
196 for (auto& info : replicas) {
197 if (info.ip() == "127.0.0.1" && info.port() == 54321) {
198 find = true;
199 }
200 }
201 EXPECT_TRUE(find);
202 auto client = std::make_unique<MockReplicaCommunicator>(replicas);
203 EXPECT_CALL(*client, SendHeartBeat)
204 .WillRepeatedly(Invoke([&](const Request& hb_info) {
205 hb.set_value(true);
206 return 0;
207 }));
208 return client;
209 }));
210 impl_->Start();
211 hb_done.get();
212}
213
214TEST_F(ConsensusManagerTest, BroadCast) {
215 std::promise<bool> bc;
216 std::future<bool> bc_done = bc.get_future();
217 EXPECT_CALL(*impl_, GetReplicaClient)
218 .WillRepeatedly(
219 Invoke([&](const std::vector<ReplicaInfo>& replicas, bool long_conn) {
220 EXPECT_EQ(replicas.size(), replicas_.size());
221 auto client = std::make_unique<MockReplicaCommunicator>(replicas);
222 EXPECT_CALL(*client, SendMessage(_))
223 .WillRepeatedly(
224 Invoke([&](const google::protobuf::Message& request) {
225 try {
226 bc.set_value(true);
227 } catch (...) {
228 }
229 return 0;
230 }));
231 return client;
232 }));
233
234 impl_->Start();
235 impl_->UpdateBroadCastClient();
236 impl_->BroadCast(Request());
237 bc_done.get();
238}
239
240TEST_F(ConsensusManagerTest, DiscoverNewClient) {
241 config_.SetSignatureVerifierEnabled(false);
242 impl_ = std::make_unique<MockConsensusManager>(config_);
243 impl_->Start();
244
245 EXPECT_CALL(*impl_, GetReplicaClient)
246 .WillRepeatedly(
247 Invoke([&](const std::vector<ReplicaInfo>& replicas, bool long_conn) {
248 EXPECT_EQ(replicas.size(), replicas_.size());
249 auto client = std::make_unique<MockReplicaCommunicator>(replicas);
250 return client;
251 }));
252
253 HeartBeatInfo hb;
254 auto* public_key = hb.add_public_keys();
255
256 public_key->mutable_public_key_info()->set_ip("127.0.0.1");
257 public_key->mutable_public_key_info()->set_port(12345);
258 public_key->mutable_public_key_info()->set_node_id(5);
259 public_key->mutable_public_key_info()->set_type(CertificateKeyInfo::CLIENT);
260
261 auto request = std::make_unique<Request>();
262 request->set_type(Request::TYPE_HEART_BEAT);
263 hb.SerializeToString(request->mutable_data());
264
265 EXPECT_EQ(impl_->Dispatch(std::make_unique<Context>(), std::move(request)),
266 0);
267
268 ReplicaCommunicator* bc_client = impl_->GetBroadCastClient();
269 EXPECT_NE(bc_client, nullptr);
270
271 std::vector<ReplicaInfo> client_infos = bc_client->GetClientReplicas();
272 EXPECT_EQ(client_infos.size(), 1);
273}
274
275TEST_F(ConsensusManagerTest, DispatchOK) {
276 Request expected_request;
277 expected_request.set_type(Request::TYPE_CLIENT_REQUEST);
278 EXPECT_CALL(*impl_,
279 ConsensusCommit(_, Pointee(EqualsProto(expected_request))))
280 .Times(1);
281
282 impl_->Start();
283 {
284 auto request = std::make_unique<Request>();
285 request->set_type(Request::TYPE_HEART_BEAT);
286 auto replica_info = GenerateReplicaInfo("127.0.0.1", 1234);
287 replica_info.SerializeToString(request->mutable_data());
288
289 EXPECT_EQ(impl_->Dispatch(std::make_unique<Context>(), std::move(request)),
290 0);
291 }
292
293 {
294 auto request = std::make_unique<Request>();
295 request->set_type(Request::TYPE_CLIENT_REQUEST);
296 EXPECT_EQ(impl_->Dispatch(std::make_unique<Context>(), std::move(request)),
297 0);
298 }
299}
300
301} // namespace
302
303} // namespace resdb
std::string data
virtual void BroadCast(const Request &request)
ReplicaCommunicator * GetBroadCastClient()
virtual int Dispatch(std::unique_ptr< Context > context, std::unique_ptr< Request > request)
static Stats * GetGlobalStats(int sleep_seconds=5)
Definition stats.cpp:29
ReplicaInfo GenerateReplicaInfo(int id, const std::string &ip, int port)
TEST_F(ResDBTest, TestPBFTService)
ReplicaInfo self_info_
std::vector< ReplicaInfo > replicas_
std::unique_ptr< ResDBConfig > config_