22#include <glog/logging.h>
23#include <gmock/gmock.h>
24#include <gtest/gtest.h>
37using ::resdb::testing::EqualsProto;
38using ::testing::Invoke;
39using ::testing::Return;
42const std::string log_path =
"./log/test_log";
44ResConfigData GetConfigData(
int buf_size = 10) {
46 data.set_recovery_enabled(
true);
47 data.set_recovery_path(log_path);
48 data.set_recovery_buffer_size(buf_size);
49 data.set_recovery_ckpt_time_s(1);
54std::vector<std::string> Listlogs(
const std::string &path) {
55 std::vector<std::string> ret;
56 std::string dir = std::filesystem::path(path).parent_path();
57 for (
const auto &entry : std::filesystem::directory_iterator(dir)) {
58 LOG(ERROR) <<
"path:" << entry.path();
59 ret.push_back(entry.path());
64class RecoveryTest :
public Test {
67 :
config_(GetConfigData(), ReplicaInfo(), KeyInfo(), CertificateInfo()),
69 std::string dir = std::filesystem::path(log_path).parent_path();
70 std::filesystem::remove_all(dir);
79TEST_F(RecoveryTest, ReadLog) {
80 std::vector<int> types = {Request::TYPE_PRE_PREPARE, Request::TYPE_PREPARE,
81 Request::TYPE_COMMIT, Request::TYPE_CHECKPOINT,
82 Request::TYPE_NEWVIEW, Request::TYPE_NEW_TXNS};
84 std::vector<int> expected_types = {
85 Request::TYPE_PRE_PREPARE, Request::TYPE_PREPARE, Request::TYPE_COMMIT,
86 Request::TYPE_CHECKPOINT, Request::TYPE_NEWVIEW,
93 std::unique_ptr<Request> request =
94 NewRequest(
static_cast<resdb::Request_Type
>(t), Request(), 0);
96 recovery.AddRequest(
nullptr, request.get());
100 std::vector<Request> list;
103 [&](
const SystemInfoData &
data) {},
104 [&](std::unique_ptr<Context> context,
105 std::unique_ptr<Request> request) { list.push_back(*request); });
107 EXPECT_EQ(list.size(), expected_types.size());
109 for (
size_t i = 0; i < expected_types.size(); ++i) {
110 EXPECT_EQ(list[i].type(), expected_types[i]);
115TEST_F(RecoveryTest, ReadLog_FlushOnce) {
116 ResDBConfig config(GetConfigData(1024), ReplicaInfo(), KeyInfo(),
119 std::vector<int> types = {Request::TYPE_PRE_PREPARE, Request::TYPE_PREPARE,
120 Request::TYPE_COMMIT, Request::TYPE_CHECKPOINT,
121 Request::TYPE_NEWVIEW, Request::TYPE_NEW_TXNS};
123 std::vector<int> expected_types = {
124 Request::TYPE_PRE_PREPARE, Request::TYPE_PREPARE, Request::TYPE_COMMIT,
125 Request::TYPE_CHECKPOINT, Request::TYPE_NEWVIEW,
131 for (
int t : types) {
132 std::unique_ptr<Request> request =
133 NewRequest(
static_cast<resdb::Request_Type
>(t), Request(), 0);
135 recovery.AddRequest(
nullptr, request.get());
139 std::vector<Request> list;
141 recovery.ReadLogs([&](
const SystemInfoData &
data) {},
142 [&](std::unique_ptr<Context> context,
143 std::unique_ptr<Request> request) {
144 LOG(ERROR) <<
"call back:" << request->seq();
145 list.push_back(*request);
148 EXPECT_EQ(list.size(), expected_types.size());
150 for (
size_t i = 0; i < expected_types.size(); ++i) {
151 EXPECT_EQ(list[i].type(), expected_types[i]);
156TEST_F(RecoveryTest, CheckPoint) {
157 ResDBConfig config(GetConfigData(1024), ReplicaInfo(), KeyInfo(),
160 std::vector<int> types = {Request::TYPE_PRE_PREPARE, Request::TYPE_PREPARE,
161 Request::TYPE_COMMIT};
163 std::vector<int> expected_types = {
164 Request::TYPE_PRE_PREPARE, Request::TYPE_PREPARE, Request::TYPE_COMMIT};
166 std::promise<bool> insert_done, ckpt;
167 std::future<bool> insert_done_future = insert_done.get_future(),
168 ckpt_future = ckpt.get_future();
170 EXPECT_CALL(
checkpoint_, GetStableCheckpoint()).WillRepeatedly(Invoke([&]() {
172 insert_done_future.get();
173 }
else if (time == 2) {
174 ckpt.set_value(
true);
183 for (
int i = 1; i < 10; ++i) {
184 for (
int t : types) {
185 std::unique_ptr<Request> request =
186 NewRequest(
static_cast<resdb::Request_Type
>(t), Request(), i);
188 recovery.AddRequest(
nullptr, request.get());
191 insert_done.set_value(
true);
193 for (
int i = 10; i < 20; ++i) {
194 for (
int t : types) {
195 std::unique_ptr<Request> request =
196 NewRequest(
static_cast<resdb::Request_Type
>(t), Request(), i);
198 recovery.AddRequest(
nullptr, request.get());
202 std::vector<std::string> log_list = Listlogs(log_path);
203 EXPECT_EQ(log_list.size(), 2);
205 std::vector<Request> list;
207 recovery.ReadLogs([&](
const SystemInfoData &
data) {},
208 [&](std::unique_ptr<Context> context,
209 std::unique_ptr<Request> request) {
210 list.push_back(*request);
214 EXPECT_EQ(list.size(), types.size() * 14);
216 for (
size_t i = 0; i < expected_types.size(); ++i) {
217 EXPECT_EQ(list[i].type(), expected_types[i]);
222TEST_F(RecoveryTest, CheckPoint2) {
223 ResDBConfig config(GetConfigData(1024), ReplicaInfo(), KeyInfo(),
226 EXPECT_CALL(storage, Flush).Times(2).WillRepeatedly(Return(
true));
228 std::vector<int> types = {Request::TYPE_PRE_PREPARE, Request::TYPE_PREPARE,
229 Request::TYPE_COMMIT};
231 std::vector<int> expected_types = {
232 Request::TYPE_PRE_PREPARE, Request::TYPE_PREPARE, Request::TYPE_COMMIT};
234 std::promise<bool> insert_done, ckpt, insert_done2, ckpt2;
235 std::future<bool> insert_done_future = insert_done.get_future(),
236 ckpt_future = ckpt.get_future();
237 std::future<bool> insert_done2_future = insert_done2.get_future();
238 std::future<bool> ckpt_future2 = ckpt2.get_future();
240 EXPECT_CALL(
checkpoint_, GetStableCheckpoint()).WillRepeatedly(Invoke([&]() {
242 insert_done_future.get();
243 }
else if (time == 2) {
244 ckpt.set_value(
true);
245 }
else if (time == 3) {
246 insert_done2_future.get();
247 }
else if (time == 4) {
248 ckpt2.set_value(
true);
260 for (
int i = 1; i < 10; ++i) {
261 for (
int t : types) {
262 std::unique_ptr<Request> request =
263 NewRequest(
static_cast<resdb::Request_Type
>(t), Request(), i);
265 recovery.AddRequest(
nullptr, request.get());
268 insert_done.set_value(
true);
270 for (
int i = 10; i < 20; ++i) {
271 for (
int t : types) {
272 std::unique_ptr<Request> request =
273 NewRequest(
static_cast<resdb::Request_Type
>(t), Request(), i);
275 recovery.AddRequest(
nullptr, request.get());
279 std::vector<std::string> log_list = Listlogs(log_path);
280 EXPECT_EQ(log_list.size(), 2);
282 std::vector<Request> list;
284 recovery.ReadLogs([&](
const SystemInfoData &
data) {},
285 [&](std::unique_ptr<Context> context,
286 std::unique_ptr<Request> request) {
287 list.push_back(*request);
291 EXPECT_EQ(list.size(), types.size() * 14);
293 for (
size_t i = 0; i < expected_types.size(); ++i) {
294 EXPECT_EQ(list[i].type(), expected_types[i]);
297 for (
int i = 20; i < 30; ++i) {
298 for (
int t : types) {
299 std::unique_ptr<Request> request =
300 NewRequest(
static_cast<resdb::Request_Type
>(t), Request(), i);
302 recovery.AddRequest(
nullptr, request.get());
305 insert_done2.set_value(
true);
308 for (
int i = 30; i < 35; ++i) {
309 for (
int t : types) {
310 std::unique_ptr<Request> request =
311 NewRequest(
static_cast<resdb::Request_Type
>(t), Request(), i);
313 recovery.AddRequest(
nullptr, request.get());
319 std::vector<Request> list;
321 recovery.ReadLogs([&](
const SystemInfoData &
data) {},
322 [&](std::unique_ptr<Context> context,
323 std::unique_ptr<Request> request) {
324 list.push_back(*request);
328 EXPECT_EQ(list.size(), types.size() * 9);
330 for (
size_t i = 0; i < expected_types.size(); ++i) {
331 EXPECT_EQ(list[i].type(), expected_types[i]);
333 EXPECT_EQ(recovery.GetMinSeq(), 30);
334 EXPECT_EQ(recovery.GetMaxSeq(), 34);
338TEST_F(RecoveryTest, SystemInfo) {
339 ResDBConfig config(GetConfigData(1024), ReplicaInfo(), KeyInfo(),
342 EXPECT_CALL(storage, Flush).Times(2).WillRepeatedly(Return(
true));
344 std::vector<int> types = {Request::TYPE_PRE_PREPARE, Request::TYPE_PREPARE,
345 Request::TYPE_COMMIT};
347 std::vector<int> expected_types = {
348 Request::TYPE_PRE_PREPARE, Request::TYPE_PREPARE, Request::TYPE_COMMIT};
350 std::promise<bool> insert_done, ckpt, insert_done2, ckpt2;
351 std::future<bool> insert_done_future = insert_done.get_future(),
352 ckpt_future = ckpt.get_future();
353 std::future<bool> insert_done2_future = insert_done2.get_future();
354 std::future<bool> ckpt_future2 = ckpt2.get_future();
356 EXPECT_CALL(
checkpoint_, GetStableCheckpoint()).WillRepeatedly(Invoke([&]() {
358 insert_done_future.get();
359 }
else if (time == 2) {
360 ckpt.set_value(
true);
361 }
else if (time == 3) {
362 insert_done2_future.get();
363 }
else if (time == 4) {
364 ckpt2.set_value(
true);
378 for (
int i = 1; i < 10; ++i) {
379 for (
int t : types) {
380 std::unique_ptr<Request> request =
381 NewRequest(
static_cast<resdb::Request_Type
>(t), Request(), i);
383 recovery.AddRequest(
nullptr, request.get());
386 insert_done.set_value(
true);
388 for (
int i = 10; i < 20; ++i) {
389 for (
int t : types) {
390 std::unique_ptr<Request> request =
391 NewRequest(
static_cast<resdb::Request_Type
>(t), Request(), i);
393 recovery.AddRequest(
nullptr, request.get());
397 std::vector<std::string> log_list = Listlogs(log_path);
398 EXPECT_EQ(log_list.size(), 2);
400 std::vector<Request> list;
403 recovery.ReadLogs([&](
const SystemInfoData &r_data) {
data = r_data; },
404 [&](std::unique_ptr<Context> context,
405 std::unique_ptr<Request> request) {
406 list.push_back(*request);
410 EXPECT_EQ(list.size(), types.size() * 14);
412 for (
size_t i = 0; i < expected_types.size(); ++i) {
413 EXPECT_EQ(list[i].type(), expected_types[i]);
416 for (
int i = 20; i < 30; ++i) {
417 for (
int t : types) {
418 std::unique_ptr<Request> request =
419 NewRequest(
static_cast<resdb::Request_Type
>(t), Request(), i);
421 recovery.AddRequest(
nullptr, request.get());
424 insert_done2.set_value(
true);
427 for (
int i = 30; i < 35; ++i) {
428 for (
int t : types) {
429 std::unique_ptr<Request> request =
430 NewRequest(
static_cast<resdb::Request_Type
>(t), Request(), i);
432 recovery.AddRequest(
nullptr, request.get());
438 std::vector<Request> list;
441 recovery.ReadLogs([&](
const SystemInfoData &r_data) {
data = r_data; },
442 [&](std::unique_ptr<Context> context,
443 std::unique_ptr<Request> request) {
444 list.push_back(*request);
448 EXPECT_EQ(
data.view(), 2);
449 EXPECT_EQ(
data.primary_id(), 2);
450 EXPECT_EQ(list.size(), types.size() * 9);
452 for (
size_t i = 0; i < expected_types.size(); ++i) {
453 EXPECT_EQ(list[i].type(), expected_types[i]);
455 EXPECT_EQ(recovery.GetMinSeq(), 30);
456 EXPECT_EQ(recovery.GetMaxSeq(), 34);
void SetCurrentView(uint64_t)
void SetPrimary(uint32_t id)
std::unique_ptr< Storage > storage
std::unique_ptr< Request > NewRequest(Request::Type type, const Request &request, int sender_id)
TEST_F(ResDBTest, TestPBFTService)
MockCheckPoint checkpoint_
std::unique_ptr< ResDBConfig > config_