Loading...
Searching...
No Matches
checkpoint_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 <glog/logging.h>
23#include <gmock/gmock.h>
24#include <gtest/gtest.h>
25
26#include <future>
27
33#include "platform/proto/checkpoint_info.pb.h"
35
36namespace resdb {
37namespace {
38
39using ::resdb::testing::EqualsProto;
40using ::testing::_;
41using ::testing::Invoke;
42using ::testing::Return;
43using ::testing::Test;
44
45class MyCheckPointManager : public CheckPointManager {
46 public:
47 MyCheckPointManager(const ResDBConfig& config,
48 ReplicaCommunicator* replica_communicator,
49 SignatureVerifier* verifier,
50 std::function<void(int64_t)> call_back = nullptr)
51 : CheckPointManager(config, replica_communicator, verifier),
52 call_back_(call_back) {}
53
54 void UpdateStableCheckPointCallback(int64_t stable_checkpoint) {
55 if (call_back_) {
56 call_back_(stable_checkpoint);
57 }
58 }
59 std::function<void(int64_t)> call_back_;
60};
61
62ResConfigData GetConfigData() {
63 Stats::GetGlobalStats(/*int sleep_seconds = */ 1);
64 std::string json =
65 "{ "
66 " \"region\":{ "
67 " \"replica_info\": { "
68 " \"id\": 1, "
69 " \"ip\": \"127.0.0.1\", "
70 " \"port\": 1234 "
71 " },"
72 " \"replica_info\": { "
73 " \"id\": 2, "
74 " \"ip\": \"127.0.0.1\", "
75 " \"port\": 1235 "
76 " },"
77 " \"replica_info\": { "
78 " \"id\": 3, "
79 " \"ip\": \"127.0.0.1\", "
80 " \"port\": 1236 "
81 " },"
82 " \"replica_info\": { "
83 " \"id\": 4, "
84 " \"ip\": \"127.0.0.1\", "
85 " \"port\": 1237 "
86 " },"
87 " },"
88 "\"view_change_timeout_ms\": 500"
89 "}";
91}
92
93class CheckPointManagerTest : public Test {
94 public:
95 CheckPointManagerTest()
96 : // just set the monitor time to 1 second to return early.
97 config_(GetConfigData(), GenerateReplicaInfo(1, "127.0.0.1", 1234),
98 KeyInfo(), CertificateInfo()) {
99 config_.EnableCheckPoint(true);
100 }
101
102 protected:
103 ResDBConfig config_;
104 MockReplicaCommunicator replica_communicator_;
105};
106
107TEST_F(CheckPointManagerTest, SendCheckPoint) {
108 config_.SetViewchangeCommitTimeout(100);
109 CheckPointManager manager(config_, &replica_communicator_, nullptr);
110
111 for (int i = 1; i <= 5; ++i) {
112 std::unique_ptr<Request> request = std::make_unique<Request>();
113 request->set_seq(i);
114 manager.AddCommitData(std::move(request));
115 }
116
117 std::promise<bool> propose_done;
118 std::future<bool> propose_done_future = propose_done.get_future();
119 EXPECT_CALL(replica_communicator_, BroadCast).WillOnce(Invoke([&]() {
120 LOG(ERROR) << "bcbcbc";
121 propose_done.set_value(true);
122 }));
123 propose_done_future.get();
124 LOG(ERROR) << "done";
125}
126
127TEST_F(CheckPointManagerTest, SendCheckPointOnce) {
128 std::promise<bool> propose_done;
129 std::future<bool> propose_done_future = propose_done.get_future();
130 EXPECT_CALL(replica_communicator_, BroadCast).WillOnce(Invoke([&]() {
131 LOG(ERROR) << "bc:";
132 propose_done.set_value(true);
133 }));
134
135 CheckPointManager manager(config_, &replica_communicator_, nullptr);
136 for (int i = 1; i <= 5; ++i) {
137 std::unique_ptr<Request> request = std::make_unique<Request>();
138 request->set_seq(i);
139 manager.AddCommitData(std::move(request));
140 }
141 sleep(1);
142 {
143 std::unique_ptr<Request> request = std::make_unique<Request>();
144 request->set_seq(6);
145 manager.AddCommitData(std::move(request));
146 }
147
148 propose_done_future.get();
149}
150
151TEST_F(CheckPointManagerTest, SendCheckPointTwo) {
152 config_.SetViewchangeCommitTimeout(100);
153 std::promise<bool> propose_done;
154 std::future<bool> propose_done_future = propose_done.get_future();
155 int count = 0;
156 EXPECT_CALL(replica_communicator_, BroadCast).WillRepeatedly(Invoke([&]() {
157 if (++count == 2) {
158 propose_done.set_value(true);
159 }
160 }));
161
162 CheckPointManager manager(config_, &replica_communicator_, nullptr);
163 std::unique_ptr<Request> request = std::make_unique<Request>();
164 for (int i = 1; i <= 5; ++i) {
165 std::unique_ptr<Request> request = std::make_unique<Request>();
166 request->set_seq(i);
167 manager.AddCommitData(std::move(request));
168 }
169 sleep(1);
170 for (int i = 6; i <= 11; ++i) {
171 std::unique_ptr<Request> request = std::make_unique<Request>();
172 request->set_seq(i);
173 manager.AddCommitData(std::move(request));
174 }
175
176 propose_done_future.get();
177}
178
179TEST_F(CheckPointManagerTest, StableCkpt) {
180 config_.SetViewchangeCommitTimeout(100);
181 std::promise<bool> ckp_done;
182 std::future<bool> ckp_done_future = ckp_done.get_future();
183 bool already_set = 0;
184 MyCheckPointManager manager(config_, &replica_communicator_, nullptr,
185 [&](int64_t seq) {
186 if (seq > 0 && !already_set) {
187 already_set = true;
188 ckp_done.set_value(true);
189 }
190 });
191 for (int i = 1; i <= 4; ++i) {
192 CheckPointData checkpoint_data;
193 std::unique_ptr<Request> checkpoint_request =
194 NewRequest(Request::TYPE_CHECKPOINT, Request(), i);
195 checkpoint_data.set_seq(5);
196 checkpoint_data.set_hash("1234");
197 checkpoint_data.SerializeToString(checkpoint_request->mutable_data());
198 EXPECT_EQ(manager.ProcessCheckPoint(std::make_unique<Context>(),
199 std::move(checkpoint_request)),
200 0);
201 }
202 ckp_done_future.get();
203 EXPECT_EQ(manager.GetStableCheckpoint(), 5);
204}
205
206TEST_F(CheckPointManagerTest, StableCkptNotEnough) {
207 config_.SetViewchangeCommitTimeout(1000);
208 std::promise<bool> ckp_done;
209 std::future<bool> ckp_done_future = ckp_done.get_future();
210 bool set_done = false;
211 MyCheckPointManager manager(config_, &replica_communicator_, nullptr,
212 [&](int64_t seq) {
213 if (seq > 0 && !set_done) {
214 set_done = true;
215 ckp_done.set_value(true);
216 }
217 });
218 for (int i = 1; i <= 4; ++i) {
219 CheckPointData checkpoint_data;
220 std::unique_ptr<Request> checkpoint_request =
221 NewRequest(Request::TYPE_CHECKPOINT, Request(), i);
222 checkpoint_data.set_seq(5);
223 checkpoint_data.set_hash("1234");
224 checkpoint_data.SerializeToString(checkpoint_request->mutable_data());
225 EXPECT_EQ(manager.ProcessCheckPoint(std::make_unique<Context>(),
226 std::move(checkpoint_request)),
227 0);
228 }
229 for (int i = 1; i <= 4; ++i) {
230 CheckPointData checkpoint_data;
231 std::unique_ptr<Request> checkpoint_request =
232 NewRequest(Request::TYPE_CHECKPOINT, Request(), i);
233 checkpoint_data.set_seq(10);
234 if (i <= 2) {
235 checkpoint_data.set_hash("1234");
236 } else {
237 checkpoint_data.set_hash("2345");
238 }
239 checkpoint_data.SerializeToString(checkpoint_request->mutable_data());
240 EXPECT_EQ(manager.ProcessCheckPoint(std::make_unique<Context>(),
241 std::move(checkpoint_request)),
242 0);
243 }
244
245 ckp_done_future.get();
246 EXPECT_EQ(manager.GetStableCheckpoint(), 5);
247}
248
249TEST_F(CheckPointManagerTest, Votes) {
250 config_.SetViewchangeCommitTimeout(100);
251 MockSignatureVerifier mock_verifier;
252 EXPECT_CALL(mock_verifier, SignMessage).WillOnce(Return(SignatureInfo()));
253 EXPECT_CALL(mock_verifier, VerifyMessage(_, EqualsProto(SignatureInfo())))
254 .WillRepeatedly(Return(true));
255
256 std::promise<bool> propose_done;
257 std::future<bool> propose_done_future = propose_done.get_future();
258 CheckPointManager manager(config_, &replica_communicator_, &mock_verifier);
259 EXPECT_CALL(replica_communicator_, BroadCast)
260 .WillRepeatedly(Invoke([&](const google::protobuf::Message& message) {
261 for (int i = 1; i <= 3; ++i) {
262 std::unique_ptr<Request> checkpoint_request =
263 std::make_unique<Request>();
264 checkpoint_request->CopyFrom(message);
265 checkpoint_request->set_sender_id(i);
266 EXPECT_EQ(manager.ProcessCheckPoint(std::make_unique<Context>(),
267 std::move(checkpoint_request)),
268 0);
269 }
270 propose_done.set_value(true);
271 }));
272
273 std::unique_ptr<Request> request = std::make_unique<Request>();
274 for (int i = 1; i <= 5; ++i) {
275 std::unique_ptr<Request> request = std::make_unique<Request>();
276 request->set_seq(i);
277 manager.AddCommitData(std::move(request));
278 }
279 propose_done_future.get();
280 sleep(1);
281 StableCheckPoint ckpt = manager.GetStableCheckpointWithVotes();
282 EXPECT_EQ(ckpt.seq(), 5);
283 EXPECT_EQ(ckpt.signatures_size(), 3);
284}
285
286/*
287TEST_F(CheckPointManagerTest, SetTimeoutHandler) {
288 CheckPointManager manager(config_, &replica_communicator_, nullptr);
289
290 std::promise<bool> propose_done;
291 std::future<bool> propose_done_future = propose_done.get_future();
292 int ct = 0;
293 manager.SetTimeoutHandler([&]() {
294 if (ct++ == 0) {
295 propose_done.set_value(true);
296 }
297 });
298 std::unique_ptr<Request> request = std::make_unique<Request>();
299 request->set_seq(1);
300 manager.AddCommitData(std::move(request));
301 propose_done_future.get();
302}
303*/
304
305} // namespace
306
307} // namespace resdb
MockReplicaCommunicator replica_communicator_
std::function< void(int64_t)> call_back_
static Stats * GetGlobalStats(int sleep_seconds=5)
Definition stats.cpp:29
T ParseFromText(const std::string &json_str)
Definition test_macros.h:41
std::unique_ptr< Request > NewRequest(Request::Type type, const Request &request, int sender_id)
ReplicaInfo GenerateReplicaInfo(int id, const std::string &ip, int port)
TEST_F(ResDBTest, TestPBFTService)
std::unique_ptr< ResDBConfig > config_