1 /*
2 * Copyright (c) 2021 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #define LOG_TAG "RdbDoubleWriteTest"
17 #include <gtest/gtest.h>
18 #include <sys/stat.h>
19 #include <sqlite3sym.h>
20 #include <unistd.h>
21
22 #include <fstream>
23 #include <string>
24
25 #include "common.h"
26 #include "file_ex.h"
27 #include "grd_api_manager.h"
28 #include "logger.h"
29 #include "rdb_common.h"
30 #include "rdb_errno.h"
31 #include "rdb_helper.h"
32 #include "rdb_open_callback.h"
33 #include "rdb_security_manager.h"
34 #ifndef CROSS_PLATFORM
35 #include "relational/relational_store_sqlite_ext.h"
36 #endif
37 #include "sqlite_connection.h"
38 #include "sqlite_utils.h"
39 #include "sys/types.h"
40
41 using namespace testing::ext;
42 using namespace OHOS::NativeRdb;
43 using namespace OHOS::Rdb;
44
45 class RdbDoubleWriteTest : public testing::Test {
46 public:
47 static void SetUpTestCase(void);
48 static void TearDownTestCase(void);
49 void SetUp();
50 void TearDown();
51 void CheckResultSet(std::shared_ptr<RdbStore> &store);
52 void CheckAge(std::shared_ptr<ResultSet> &resultSet);
53 void CheckSalary(std::shared_ptr<ResultSet> &resultSet);
54 void CheckBlob(std::shared_ptr<ResultSet> &resultSet);
55 void CheckNumber(
56 std::shared_ptr<RdbStore> &store, int num, int errCode = E_OK, const std::string &tableName = "test");
57 void Insert(int64_t start, int count, bool isSlave = false, int dataSize = 0);
58 void WaitForBackupFinish(int32_t expectStatus, int maxTimes = 400);
59 void WaitForAsyncRepairFinish(int maxTimes = 400);
60 void TryInterruptBackup();
61 void InitDb(HAMode mode = HAMode::MAIN_REPLICA, bool isOpenSlave = true);
62
63 static const std::string DATABASE_NAME;
64 static const std::string SLAVE_DATABASE_NAME;
65 static std::shared_ptr<RdbStore> store;
66 static std::shared_ptr<RdbStore> slaveStore;
67 static std::shared_ptr<RdbStore> store3;
68 static const struct sqlite3_api_routines_extra *originalExtraApi;
69 static struct sqlite3_api_routines_extra mockExtraApi;
70 #ifndef CROSS_PLATFORM
71 static const struct sqlite3_api_routines_relational *originalKvApi;
72 static struct sqlite3_api_routines_relational mockKvApi;
73 #endif
74
75 enum SlaveStatus : uint32_t {
76 UNDEFINED,
77 BACKING_UP,
78 BACKUP_INTERRUPT,
79 BACKUP_FINISHED,
80 DB_CLOSING,
81 };
82 };
83
84 const std::string RdbDoubleWriteTest::DATABASE_NAME = RDB_TEST_PATH + "dual_write_test.db";
85 const std::string RdbDoubleWriteTest::SLAVE_DATABASE_NAME = RDB_TEST_PATH + "dual_write_test_slave.db";
86 std::shared_ptr<RdbStore> RdbDoubleWriteTest::store = nullptr;
87 std::shared_ptr<RdbStore> RdbDoubleWriteTest::slaveStore = nullptr;
88 std::shared_ptr<RdbStore> RdbDoubleWriteTest::store3 = nullptr;
89 const struct sqlite3_api_routines_extra *RdbDoubleWriteTest::originalExtraApi = sqlite3_export_extra_symbols;
90 struct sqlite3_api_routines_extra RdbDoubleWriteTest::mockExtraApi = *sqlite3_export_extra_symbols;
91 #ifndef CROSS_PLATFORM
92 const struct sqlite3_api_routines_relational *RdbDoubleWriteTest::originalKvApi = sqlite3_export_relational_symbols;
93 struct sqlite3_api_routines_relational RdbDoubleWriteTest::mockKvApi = *sqlite3_export_relational_symbols;
94 #endif
95 const int BLOB_SIZE = 3;
96 const uint8_t EXPECTED_BLOB_DATA[]{ 1, 2, 3 };
97 const int CHECKAGE = 18;
98 const double CHECKCOLUMN = 100.5;
99 const int HUGE_DATA_SIZE = 6 * 1024 * 1024; // 1MB
100
101 class DoubleWriteTestOpenCallback : public RdbOpenCallback {
102 public:
103 int OnCreate(RdbStore &store) override;
104 int OnUpgrade(RdbStore &store, int oldVersion, int newVersion) override;
105 int OnOpen(RdbStore &rdbStore) override;
106 static const std::string CREATE_TABLE_TEST;
107 };
108
109 const std::string DoubleWriteTestOpenCallback::CREATE_TABLE_TEST =
110 std::string("CREATE TABLE IF NOT EXISTS test ") + std::string("(id INTEGER PRIMARY KEY AUTOINCREMENT, "
111 "name TEXT NOT NULL, age INTEGER, salary "
112 "REAL, blobType BLOB)");
113
OnCreate(RdbStore & store)114 int DoubleWriteTestOpenCallback::OnCreate(RdbStore &store)
115 {
116 return store.ExecuteSql(CREATE_TABLE_TEST);
117 }
118
OnUpgrade(RdbStore & store,int oldVersion,int newVersion)119 int DoubleWriteTestOpenCallback::OnUpgrade(RdbStore &store, int oldVersion, int newVersion)
120 {
121 return E_OK;
122 }
123
OnOpen(RdbStore & rdbStore)124 int DoubleWriteTestOpenCallback::OnOpen(RdbStore &rdbStore)
125 {
126 int version = 0;
127 rdbStore.GetVersion(version);
128 EXPECT_TRUE(version > -1);
129 return E_OK;
130 }
131
MockNotSupportBinlog(const char * notUsed)132 static int MockNotSupportBinlog(const char *notUsed)
133 {
134 return SQLITE_ERROR;
135 }
136
MockSupportBinlog(const char * notUsed)137 static int MockSupportBinlog(const char *notUsed)
138 {
139 return SQLITE_OK;
140 }
141
142 #ifndef CROSS_PLATFORM
MockNotSupportBinlogWithParam(const char * name)143 static int MockNotSupportBinlogWithParam(const char *name)
144 {
145 return SQLITE_ERROR;
146 }
147
MockSupportBinlogWithParam(const char * name)148 static int MockSupportBinlogWithParam(const char *name)
149 {
150 return SQLITE_OK;
151 }
152 #endif
MockReplayBinlog(sqlite3 * srcDb,sqlite3 * destDb)153 static int MockReplayBinlog(sqlite3 *srcDb, sqlite3 *destDb)
154 {
155 return SQLITE_OK;
156 }
157
MockCleanBinlog(sqlite3 * db,BinlogFileCleanModeE mode)158 static int MockCleanBinlog(sqlite3 *db, BinlogFileCleanModeE mode)
159 {
160 return SQLITE_OK;
161 }
162
SetUpTestCase(void)163 void RdbDoubleWriteTest::SetUpTestCase(void)
164 {
165 }
166
TearDownTestCase(void)167 void RdbDoubleWriteTest::TearDownTestCase(void)
168 {
169 }
170
SetUp(void)171 void RdbDoubleWriteTest::SetUp(void)
172 {
173 mockExtraApi.is_support_binlog = MockNotSupportBinlog;
174 mockExtraApi.replay_binlog = MockReplayBinlog;
175 mockExtraApi.clean_binlog = MockCleanBinlog;
176 sqlite3_export_extra_symbols = &mockExtraApi;
177 #ifndef CROSS_PLATFORM
178 mockKvApi.is_support_binlog = MockNotSupportBinlogWithParam;
179 sqlite3_export_relational_symbols = &mockKvApi;
180 #endif
181 store = nullptr;
182 slaveStore = nullptr;
183 RdbHelper::DeleteRdbStore(RdbDoubleWriteTest::DATABASE_NAME);
184 }
185
TearDown(void)186 void RdbDoubleWriteTest::TearDown(void)
187 {
188 RdbDoubleWriteTest::WaitForAsyncRepairFinish();
189 store = nullptr;
190 slaveStore = nullptr;
191 RdbHelper::DeleteRdbStore(RdbDoubleWriteTest::DATABASE_NAME);
192 sqlite3_export_extra_symbols = originalExtraApi;
193 #ifndef CROSS_PLATFORM
194 sqlite3_export_relational_symbols = originalKvApi;
195 #endif
196 }
197
InitDb(HAMode mode,bool isOpenSlave)198 void RdbDoubleWriteTest::InitDb(HAMode mode, bool isOpenSlave)
199 {
200 int errCode = E_OK;
201 RdbStoreConfig config(RdbDoubleWriteTest::DATABASE_NAME);
202 config.SetHaMode(mode);
203 DoubleWriteTestOpenCallback helper;
204 RdbDoubleWriteTest::store = RdbHelper::GetRdbStore(config, 1, helper, errCode);
205 ASSERT_NE(RdbDoubleWriteTest::store, nullptr);
206 store->ExecuteSql("DELETE FROM test");
207
208 if (isOpenSlave) {
209 RdbStoreConfig slaveConfig(RdbDoubleWriteTest::SLAVE_DATABASE_NAME);
210 DoubleWriteTestOpenCallback slaveHelper;
211 RdbDoubleWriteTest::slaveStore = RdbHelper::GetRdbStore(slaveConfig, 1, slaveHelper, errCode);
212 ASSERT_NE(RdbDoubleWriteTest::slaveStore, nullptr);
213 slaveStore->ExecuteSql("DELETE FROM test");
214 }
215 }
216
217 /**
218 * @tc.name: RdbStore_DoubleWrite_001
219 * @tc.desc: test RdbStore doubleWrite
220 * @tc.type: FUNC
221 */
222 HWTEST_F(RdbDoubleWriteTest, RdbStore_DoubleWrite_001, TestSize.Level1)
223 {
224 InitDb();
225 int64_t id;
226 ValuesBucket values;
227
228 values.PutInt("id", 1);
229 values.PutString("name", std::string("zhangsan"));
230 values.PutInt("age", 18);
231 values.PutDouble("salary", 100.5);
232 values.PutBlob("blobType", std::vector<uint8_t>{ 1, 2, 3 });
233 int ret = store->Insert(id, "test", values);
234 EXPECT_EQ(ret, E_OK);
235 EXPECT_EQ(1, id);
236
237 values.Clear();
238 values.PutInt("id", 2);
239 values.PutString("name", std::string("lisi"));
240 values.PutInt("age", 18);
241 values.PutDouble("salary", 100.5);
242 values.PutBlob("blobType", std::vector<uint8_t>{ 1, 2, 3 });
243 ret = store->Insert(id, "test", values);
244 EXPECT_EQ(ret, E_OK);
245 EXPECT_EQ(2, id);
246
247 values.Clear();
248 values.PutInt("id", 3);
249 values.PutString("name", std::string("lisi"));
250 values.PutInt("age", 20L);
251 values.PutDouble("salary", 100.5f);
252 values.PutBlob("blobType", std::vector<uint8_t>{ 1, 2, 3 });
253 ret = store->Insert(id, "test", values);
254 EXPECT_EQ(ret, E_OK);
255 EXPECT_EQ(3, id);
256
257 RdbDoubleWriteTest::CheckResultSet(slaveStore);
258 }
259
Insert(int64_t start,int count,bool isSlave,int dataSize)260 void RdbDoubleWriteTest::Insert(int64_t start, int count, bool isSlave, int dataSize)
261 {
262 ValuesBucket values;
263 int64_t id = start;
264 int ret = E_OK;
265 for (int i = 0; i < count; i++) {
266 values.Clear();
267 values.PutInt("id", id);
268 if (dataSize > 0) {
269 values.PutString("name", std::string(dataSize, 'a'));
270 } else {
271 values.PutString("name", std::string("zhangsan"));
272 }
273 values.PutInt("age", CHECKAGE);
274 values.PutDouble("salary", CHECKCOLUMN);
275 values.PutBlob("blobType", std::vector<uint8_t>{ 1, 2, 3 });
276 if (isSlave) {
277 ret = slaveStore->Insert(id, "test", values);
278 } else {
279 ret = store->Insert(id, "test", values);
280 }
281 EXPECT_EQ(ret, E_OK);
282 id++;
283 }
284 }
285
WaitForBackupFinish(int32_t expectStatus,int maxTimes)286 void RdbDoubleWriteTest::WaitForBackupFinish(int32_t expectStatus, int maxTimes)
287 {
288 int32_t curStatus = store->GetBackupStatus();
289 int tryTimes = 0;
290 while (curStatus != expectStatus && (++tryTimes <= maxTimes)) {
291 usleep(50000); // 50000 delay
292 curStatus = store->GetBackupStatus();
293 }
294 LOG_INFO("----------cur backup Status:%{public}d---------", curStatus);
295 ASSERT_EQ(curStatus, expectStatus);
296 }
297
WaitForAsyncRepairFinish(int maxTimes)298 void RdbDoubleWriteTest::WaitForAsyncRepairFinish(int maxTimes)
299 {
300 LOG_INFO("---- start wait for async finish----");
301 sleep(1);
302 int tryTimes = 0;
303 auto keyFiles = RdbSecurityManager::KeyFiles(DATABASE_NAME + "-async.restore");
304 while (keyFiles.Lock(false) != E_OK && (++tryTimes <= maxTimes)) {
305 sleep(1);
306 }
307 LOG_INFO("---- end wait for async finish ----, %{public}d", tryTimes);
308 }
309
TryInterruptBackup()310 void RdbDoubleWriteTest::TryInterruptBackup()
311 {
312 int err = store->InterruptBackup();
313 int tryTimes = 0;
314 while (err != E_OK && (++tryTimes <= 1000)) { // 1000 is try time
315 usleep(10000); // 10000 delay
316 err = store->InterruptBackup();
317 }
318 EXPECT_EQ(err, E_OK);
319 LOG_INFO("----------interrupt backup---------");
320 }
321
CheckResultSet(std::shared_ptr<RdbStore> & store)322 void RdbDoubleWriteTest::CheckResultSet(std::shared_ptr<RdbStore> &store)
323 {
324 std::shared_ptr<ResultSet> resultSet =
325 store->QuerySql("SELECT * FROM test WHERE name = ?", std::vector<std::string>{ "zhangsan" });
326 EXPECT_NE(resultSet, nullptr);
327
328 int columnIndex;
329 int intVal;
330 std::string strVal;
331 ColumnType columnType;
332 int position;
333 int ret = resultSet->GetRowIndex(position);
334 EXPECT_EQ(ret, E_OK);
335 EXPECT_EQ(position, -1);
336
337 ret = resultSet->GetColumnType(0, columnType);
338 EXPECT_EQ(ret, E_ROW_OUT_RANGE);
339
340 ret = resultSet->GoToFirstRow();
341 EXPECT_EQ(ret, E_OK);
342
343 ret = resultSet->GetColumnIndex("id", columnIndex);
344 EXPECT_EQ(ret, E_OK);
345 EXPECT_EQ(columnIndex, 0);
346 ret = resultSet->GetColumnType(columnIndex, columnType);
347 EXPECT_EQ(ret, E_OK);
348 EXPECT_EQ(columnType, ColumnType::TYPE_INTEGER);
349 ret = resultSet->GetInt(columnIndex, intVal);
350 EXPECT_EQ(ret, E_OK);
351 EXPECT_EQ(1, intVal);
352
353 ret = resultSet->GetColumnIndex("name", columnIndex);
354 EXPECT_EQ(ret, E_OK);
355 ret = resultSet->GetColumnType(columnIndex, columnType);
356 EXPECT_EQ(ret, E_OK);
357 EXPECT_EQ(columnType, ColumnType::TYPE_STRING);
358 ret = resultSet->GetString(columnIndex, strVal);
359 EXPECT_EQ(ret, E_OK);
360 EXPECT_EQ("zhangsan", strVal);
361
362 RdbDoubleWriteTest::CheckAge(resultSet);
363 RdbDoubleWriteTest::CheckSalary(resultSet);
364 RdbDoubleWriteTest::CheckBlob(resultSet);
365
366 ret = resultSet->GoToNextRow();
367 EXPECT_EQ(ret, E_ROW_OUT_RANGE);
368
369 ret = resultSet->GetColumnType(columnIndex, columnType);
370 EXPECT_EQ(ret, E_ROW_OUT_RANGE);
371
372 ret = resultSet->Close();
373 EXPECT_EQ(ret, E_OK);
374 }
375
CheckAge(std::shared_ptr<ResultSet> & resultSet)376 void RdbDoubleWriteTest::CheckAge(std::shared_ptr<ResultSet> &resultSet)
377 {
378 int columnIndex;
379 int intVal;
380 ColumnType columnType;
381 int ret = resultSet->GetColumnIndex("age", columnIndex);
382 EXPECT_EQ(ret, E_OK);
383 ret = resultSet->GetColumnType(columnIndex, columnType);
384 EXPECT_EQ(ret, E_OK);
385 EXPECT_EQ(columnType, ColumnType::TYPE_INTEGER);
386 ret = resultSet->GetInt(columnIndex, intVal);
387 EXPECT_EQ(ret, E_OK);
388 EXPECT_EQ(CHECKAGE, intVal);
389 }
390
CheckSalary(std::shared_ptr<ResultSet> & resultSet)391 void RdbDoubleWriteTest::CheckSalary(std::shared_ptr<ResultSet> &resultSet)
392 {
393 int columnIndex;
394 double dVal;
395 ColumnType columnType;
396 int ret = resultSet->GetColumnIndex("salary", columnIndex);
397 EXPECT_EQ(ret, E_OK);
398 ret = resultSet->GetColumnType(columnIndex, columnType);
399 EXPECT_EQ(ret, E_OK);
400 EXPECT_EQ(columnType, ColumnType::TYPE_FLOAT);
401 ret = resultSet->GetDouble(columnIndex, dVal);
402 EXPECT_EQ(ret, E_OK);
403 EXPECT_EQ(CHECKCOLUMN, dVal);
404 }
405
CheckBlob(std::shared_ptr<ResultSet> & resultSet)406 void RdbDoubleWriteTest::CheckBlob(std::shared_ptr<ResultSet> &resultSet)
407 {
408 int columnIndex;
409 std::vector<uint8_t> blob;
410 ColumnType columnType;
411 int ret = resultSet->GetColumnIndex("blobType", columnIndex);
412 EXPECT_EQ(ret, E_OK);
413 ret = resultSet->GetColumnType(columnIndex, columnType);
414 EXPECT_EQ(ret, E_OK);
415 EXPECT_EQ(columnType, ColumnType::TYPE_BLOB);
416 ret = resultSet->GetBlob(columnIndex, blob);
417 EXPECT_EQ(ret, E_OK);
418 EXPECT_EQ(BLOB_SIZE, static_cast<int>(blob.size()));
419 for (int i = 0; i < BLOB_SIZE; i++) {
420 EXPECT_EQ(EXPECTED_BLOB_DATA[i], blob[i]);
421 }
422 }
423
CheckNumber(std::shared_ptr<RdbStore> & store,int num,int errCode,const std::string & tableName)424 void RdbDoubleWriteTest::CheckNumber(
425 std::shared_ptr<RdbStore> &store, int num, int errCode, const std::string &tableName)
426 {
427 std::shared_ptr<ResultSet> resultSet = store->QuerySql("SELECT * FROM " + tableName);
428 ASSERT_NE(resultSet, nullptr);
429 int countNum;
430 int ret = resultSet->GetRowCount(countNum);
431 EXPECT_EQ(ret, errCode);
432 EXPECT_EQ(num, countNum);
433 }
434
435 /**
436 * @tc.name: RdbStore_DoubleWrite_003
437 * @tc.desc: test RdbStore execute
438 * @tc.type: FUNC
439 */
440 HWTEST_F(RdbDoubleWriteTest, RdbStore_DoubleWrite_003, TestSize.Level1)
441 {
442 InitDb();
443
444 int64_t id;
445 ValuesBucket values;
446 values.PutInt("id", 1);
447 values.PutString("name", std::string("zhangsan"));
448 values.PutInt("age", 25);
449 values.PutDouble("salary", CHECKCOLUMN);
450 values.PutBlob("blobType", std::vector<uint8_t>{ 1, 2, 3 });
451 int ret = store->Insert(id, "test", values);
452 EXPECT_EQ(ret, E_OK);
453 auto [ret2, outValue2] = store->Execute("UPDATE test SET age= 18 WHERE id = 1");
454 EXPECT_EQ(E_OK, ret2);
455
456 RdbDoubleWriteTest::CheckResultSet(slaveStore);
457 }
458
459 /**
460 * @tc.name: RdbStore_DoubleWrite_004
461 * @tc.desc: test RdbStore updata
462 * @tc.type: FUNC
463 */
464 HWTEST_F(RdbDoubleWriteTest, RdbStore_DoubleWrite_004, TestSize.Level1)
465 {
466 InitDb();
467
468 int64_t id;
469
470 ValuesBucket values;
471 values.PutInt("id", 1);
472 values.PutString("name", std::string("zhangsan"));
473 values.PutInt("age", 25);
474 values.PutDouble("salary", 100.5);
475 values.PutBlob("blobType", std::vector<uint8_t>{ 1, 2, 3 });
476 int ret = store->Insert(id, "test", values);
477
478 int changedRows;
479 values.Clear();
480 values.PutInt("age", 18);
481 ret = store->Update(changedRows, "test", values);
482 EXPECT_EQ(ret, E_OK);
483 EXPECT_EQ(1, changedRows);
484
485 RdbDoubleWriteTest::CheckResultSet(slaveStore);
486 }
487
488 /**
489 * @tc.name: RdbStore_DoubleWrite_005
490 * @tc.desc: test RdbStore delete
491 * @tc.type: FUNC
492 */
493 HWTEST_F(RdbDoubleWriteTest, RdbStore_DoubleWrite_005, TestSize.Level1)
494 {
495 InitDb();
496
497 ValuesBucket values;
498 int64_t id;
499 values.PutInt("id", 1);
500 values.PutString("name", std::string("zhangsan"));
501 values.PutInt("age", 18);
502 values.PutDouble("salary", 100.5);
503 values.PutBlob("blobType", std::vector<uint8_t>{ 1, 2, 3 });
504 int ret = store->Insert(id, "test", values);
505 EXPECT_EQ(ret, E_OK);
506 EXPECT_EQ(1, id);
507
508 values.Clear();
509 values.PutInt("id", 2);
510 values.PutString("name", std::string("lisi"));
511 values.PutInt("age", 18);
512 values.PutDouble("salary", 100.5);
513 values.PutBlob("blobType", std::vector<uint8_t>{ 1, 2, 3 });
514 ret = store->Insert(id, "test", values);
515 EXPECT_EQ(ret, E_OK);
516 EXPECT_EQ(2, id);
517
518 values.Clear();
519 values.PutInt("id", 3);
520 values.PutString("name", std::string("lisi"));
521 values.PutInt("age", 20L);
522 values.PutDouble("salary", 100.5f);
523 values.PutBlob("blobType", std::vector<uint8_t>{ 1, 2, 3 });
524 ret = store->Insert(id, "test", values);
525 EXPECT_EQ(ret, E_OK);
526 EXPECT_EQ(3, id);
527
528 int deletedRows;
529 ret = store->Delete(deletedRows, "test", "id = 2");
530 ret = store->Delete(deletedRows, "test", "id = 3");
531 EXPECT_EQ(ret, E_OK);
532 EXPECT_EQ(1, deletedRows);
533
534 RdbDoubleWriteTest::CheckNumber(slaveStore, 1);
535 }
536
537 /**
538 * @tc.name: RdbStore_DoubleWrite_007
539 * @tc.desc: open SINGLE db, write, close, open MAIN_REPLICA db, check slave
540 * @tc.type: FUNC
541 */
542 HWTEST_F(RdbDoubleWriteTest, RdbStore_DoubleWrite_007, TestSize.Level1)
543 {
544 int errCode = E_OK;
545 RdbStoreConfig config(RdbDoubleWriteTest::DATABASE_NAME);
546 config.SetHaMode(HAMode::SINGLE);
547 DoubleWriteTestOpenCallback helper;
548 store = RdbHelper::GetRdbStore(config, 1, helper, errCode);
549 EXPECT_NE(store, nullptr);
550
551 int64_t id = 10;
552 int count = 100;
553 Insert(id, count);
554
555 store = nullptr;
556 config.SetHaMode(HAMode::MAIN_REPLICA);
557 RdbDoubleWriteTest::store = RdbHelper::GetRdbStore(config, 1, helper, errCode);
558 EXPECT_NE(RdbDoubleWriteTest::store, nullptr);
559
560 WaitForBackupFinish(BACKUP_FINISHED);
561
562 RdbStoreConfig slaveConfig(RdbDoubleWriteTest::SLAVE_DATABASE_NAME);
563 DoubleWriteTestOpenCallback slaveHelper;
564 RdbDoubleWriteTest::slaveStore = RdbHelper::GetRdbStore(slaveConfig, 1, slaveHelper, errCode);
565 EXPECT_NE(RdbDoubleWriteTest::slaveStore, nullptr);
566
567 RdbDoubleWriteTest::CheckNumber(RdbDoubleWriteTest::slaveStore, count);
568 }
569
570 /**
571 * @tc.name: RdbStore_DoubleWrite_008
572 * @tc.desc: open MAIN_REPLICA db, write, close, corrupt, reopen db allow rebuild, db returns to normal
573 * @tc.type: FUNC
574 */
575 HWTEST_F(RdbDoubleWriteTest, RdbStore_DoubleWrite_008, TestSize.Level1)
576 {
577 InitDb();
578 int64_t id = 10;
579 int count = 100;
580 Insert(id, count);
581 LOG_INFO("RdbStore_DoubleWrite_008 insert finish");
582
583 store = nullptr;
584
585 std::fstream file(DATABASE_NAME, std::ios::in | std::ios::out | std::ios::binary);
586 ASSERT_TRUE(file.is_open() == true);
587 file.seekp(30, std::ios::beg);
588 ASSERT_TRUE(file.good() == true);
589 char bytes[2] = { 0x6, 0x6 };
590 file.write(bytes, 2);
591 ASSERT_TRUE(file.good() == true);
592 file.close();
593 LOG_INFO("RdbStore_DoubleWrite_008 corrupt db finish");
594
595 SqliteUtils::DeleteFile(RdbDoubleWriteTest::DATABASE_NAME + "-dwr");
596 SqliteUtils::DeleteFile(RdbDoubleWriteTest::SLAVE_DATABASE_NAME + "-dwr");
597 int errCode = E_OK;
598 RdbStoreConfig config(RdbDoubleWriteTest::DATABASE_NAME);
599 config.SetHaMode(HAMode::MAIN_REPLICA);
600 config.SetAllowRebuild(true);
601 DoubleWriteTestOpenCallback helper;
602 store = RdbHelper::GetRdbStore(config, 1, helper, errCode);
603 EXPECT_EQ(errCode, E_OK);
604 ASSERT_NE(store, nullptr);
605 RebuiltType rebuiltType;
606 store->GetRebuilt(rebuiltType);
607 EXPECT_EQ(rebuiltType, RebuiltType::REPAIRED);
608 LOG_INFO("RdbStore_DoubleWrite_008 reopen db finish");
609
610 RdbDoubleWriteTest::CheckNumber(store, count);
611 }
612
613 /**
614 * @tc.name: RdbStore_DoubleWrite_009
615 * @tc.desc: open MAIN_REPLICA db, write, slave db has 100 more data than main db, restore, check count
616 * @tc.type: FUNC
617 */
618 HWTEST_F(RdbDoubleWriteTest, RdbStore_DoubleWrite_009, TestSize.Level1)
619 {
620 InitDb();
621 int64_t id = 10;
622 Insert(id, 100);
623 id = 200;
624 Insert(id, 100, true);
625 RdbDoubleWriteTest::CheckNumber(store, 100);
626 RdbDoubleWriteTest::CheckNumber(slaveStore, 200);
627 EXPECT_EQ(store->Restore(std::string(""), {}), E_OK);
628 RdbDoubleWriteTest::CheckNumber(store, 200);
629 }
630
631 /**
632 * @tc.name: RdbStore_DoubleWrite_010
633 * @tc.desc: open MAIN_REPLICA db, write, close all, corrupt slave, open MAIN_REPLICA db, slave returns to normal
634 * @tc.type: FUNC
635 */
636 HWTEST_F(RdbDoubleWriteTest, RdbStore_DoubleWrite_010, TestSize.Level1)
637 {
638 InitDb();
639 int64_t id = 10;
640 int count = 100;
641 Insert(id, count);
642 LOG_INFO("RdbStore_DoubleWrite_010 insert finish");
643
644 slaveStore = nullptr;
645 store = nullptr;
646
647 std::fstream file(SLAVE_DATABASE_NAME, std::ios::in | std::ios::out | std::ios::binary);
648 ASSERT_TRUE(file.is_open() == true);
649 file.seekp(30, std::ios::beg);
650 ASSERT_TRUE(file.good() == true);
651 char bytes[2] = { 0x6, 0x6 };
652 file.write(bytes, 2);
653 ASSERT_TRUE(file.good() == true);
654 file.close();
655 LOG_INFO("RdbStore_DoubleWrite_010 corrupt db finish");
656 SqliteUtils::DeleteFile(RdbDoubleWriteTest::DATABASE_NAME + "-dwr");
657 SqliteUtils::DeleteFile(RdbDoubleWriteTest::SLAVE_DATABASE_NAME + "-dwr");
658
659 int errCode = E_OK;
660 RdbStoreConfig config(RdbDoubleWriteTest::DATABASE_NAME);
661 config.SetHaMode(HAMode::MAIN_REPLICA);
662 DoubleWriteTestOpenCallback helper;
663 store = RdbHelper::GetRdbStore(config, 1, helper, errCode);
664 EXPECT_EQ(errCode, E_OK);
665 ASSERT_NE(store, nullptr);
666 LOG_INFO("RdbStore_DoubleWrite_010 reopen main db finish");
667
668 RdbStoreConfig slaveConfig(RdbDoubleWriteTest::SLAVE_DATABASE_NAME);
669 DoubleWriteTestOpenCallback slaveHelper;
670 RdbDoubleWriteTest::slaveStore = RdbHelper::GetRdbStore(slaveConfig, 1, slaveHelper, errCode);
671 EXPECT_NE(RdbDoubleWriteTest::slaveStore, nullptr);
672 LOG_INFO("RdbStore_DoubleWrite_010 reopen slave db finish");
673 WaitForBackupFinish(BACKUP_FINISHED);
674 RdbDoubleWriteTest::CheckNumber(slaveStore, count);
675 }
676
677 /**
678 * @tc.name: RdbStore_DoubleWrite_011
679 * @tc.desc: open MAIN_REPLICA db, write, close slave, corrupt slave, backup, check slave
680 * @tc.type: FUNC
681 */
682 HWTEST_F(RdbDoubleWriteTest, RdbStore_DoubleWrite_011, TestSize.Level1)
683 {
684 InitDb();
685 int64_t id = 10;
686 int count = 100;
687 Insert(id, count);
688 LOG_INFO("RdbStore_DoubleWrite_011 insert finish");
689
690 slaveStore = nullptr;
691
692 std::fstream file(SLAVE_DATABASE_NAME, std::ios::in | std::ios::out | std::ios::binary);
693 ASSERT_TRUE(file.is_open() == true);
694 file.seekp(30, std::ios::beg);
695 ASSERT_TRUE(file.good() == true);
696 char bytes[2] = { 0x6, 0x6 };
697 file.write(bytes, 2);
698 ASSERT_TRUE(file.good() == true);
699 file.close();
700 LOG_INFO("RdbStore_DoubleWrite_011 corrupt db finish");
701
702 EXPECT_NE(store->Backup(std::string(""), {}), E_OK);
703 LOG_INFO("RdbStore_DoubleWrite_011 backup db finish");
704 EXPECT_EQ(store->Backup(std::string(""), {}), E_OK);
705
706 RdbStoreConfig slaveConfig(RdbDoubleWriteTest::SLAVE_DATABASE_NAME);
707 DoubleWriteTestOpenCallback slaveHelper;
708 int errCode;
709 RdbDoubleWriteTest::slaveStore = RdbHelper::GetRdbStore(slaveConfig, 1, slaveHelper, errCode);
710 EXPECT_NE(RdbDoubleWriteTest::slaveStore, nullptr);
711 LOG_INFO("RdbStore_DoubleWrite_011 reopen slave db finish");
712
713 RdbDoubleWriteTest::CheckNumber(slaveStore, count);
714 }
715
716 /**
717 * @tc.name: RdbStore_DoubleWrite_012
718 * @tc.desc: test RdbStore transaction
719 * @tc.type: FUNC
720 */
721 HWTEST_F(RdbDoubleWriteTest, RdbStore_DoubleWrite_012, TestSize.Level1)
722 {
723 InitDb();
724
725 int err = store->BeginTransaction();
726 EXPECT_EQ(err, E_OK);
727 int64_t id;
728 ValuesBucket values;
729 values.PutInt("id", 1);
730 values.PutString("name", std::string("zhangsan"));
731 values.PutInt("age", 25);
732 values.PutDouble("salary", CHECKCOLUMN);
733 values.PutBlob("blobType", std::vector<uint8_t>{ 1, 2, 3 });
734 int ret = store->Insert(id, "test", values);
735 EXPECT_EQ(ret, E_OK);
736 auto [ret2, outValue2] = store->Execute("UPDATE test SET age= 18 WHERE id = 1");
737 EXPECT_EQ(E_OK, ret2);
738 err = store->Commit();
739 EXPECT_EQ(err, E_OK);
740
741 RdbDoubleWriteTest::CheckResultSet(slaveStore);
742 }
743
744 /**
745 * @tc.name: RdbStore_DoubleWrite_013
746 * @tc.desc: open MANUAL_TRIGGER db, open slave, write, slave is empty, backup, check slave, write, check slave
747 * @tc.type: FUNC
748 */
749 HWTEST_F(RdbDoubleWriteTest, RdbStore_DoubleWrite_013, TestSize.Level1)
750 {
751 int errCode = E_OK;
752 RdbStoreConfig config(RdbDoubleWriteTest::DATABASE_NAME);
753 config.SetHaMode(HAMode::MANUAL_TRIGGER);
754 DoubleWriteTestOpenCallback helper;
755 store = RdbHelper::GetRdbStore(config, 1, helper, errCode);
756 EXPECT_EQ(errCode, E_OK);
757 ASSERT_NE(store, nullptr);
758 LOG_INFO("RdbStore_DoubleWrite_013 reopen main db finish");
759
760 RdbStoreConfig slaveConfig(RdbDoubleWriteTest::SLAVE_DATABASE_NAME);
761 DoubleWriteTestOpenCallback slaveHelper;
762 RdbDoubleWriteTest::slaveStore = RdbHelper::GetRdbStore(slaveConfig, 1, slaveHelper, errCode);
763 EXPECT_NE(RdbDoubleWriteTest::slaveStore, nullptr);
764 LOG_INFO("RdbStore_DoubleWrite_013 reopen slave db finish");
765
766 int64_t id = 10;
767 int count = 100;
768 Insert(id, count);
769 LOG_INFO("RdbStore_DoubleWrite_013 insert finish");
770
771 RdbDoubleWriteTest::CheckNumber(slaveStore, 0);
772
773 errCode = store->Backup(std::string(""), {});
774 EXPECT_EQ(errCode, E_OK);
775 LOG_INFO("RdbStore_DoubleWrite_013 backup finish");
776
777 RdbDoubleWriteTest::CheckNumber(slaveStore, count);
778
779 id = 1000;
780 Insert(id, count);
781 LOG_INFO("RdbStore_DoubleWrite_013 insert finish");
782 RdbDoubleWriteTest::CheckNumber(slaveStore, 200); // 200 is all count
783 }
784
785 /**
786 * @tc.name: RdbStore_DoubleWrite_014
787 * @tc.desc: open MANUAL_TRIGGER db, write, backup, open slave, check slave, write, check slave
788 * @tc.type: FUNC
789 */
790 HWTEST_F(RdbDoubleWriteTest, RdbStore_DoubleWrite_014, TestSize.Level1)
791 {
792 int errCode = E_OK;
793 RdbStoreConfig config(RdbDoubleWriteTest::DATABASE_NAME);
794 config.SetHaMode(HAMode::MANUAL_TRIGGER);
795 DoubleWriteTestOpenCallback helper;
796 store = RdbHelper::GetRdbStore(config, 1, helper, errCode);
797 EXPECT_EQ(errCode, E_OK);
798 ASSERT_NE(store, nullptr);
799 LOG_INFO("RdbStore_DoubleWrite_014 reopen main db finish");
800
801 int64_t id = 10;
802 int count = 100;
803 Insert(id, count);
804 LOG_INFO("RdbStore_DoubleWrite_014 insert finish");
805
806 errCode = store->Backup(std::string(""), {});
807 EXPECT_EQ(errCode, E_OK);
808 LOG_INFO("RdbStore_DoubleWrite_014 backup finish");
809
810 RdbStoreConfig slaveConfig(RdbDoubleWriteTest::SLAVE_DATABASE_NAME);
811 DoubleWriteTestOpenCallback slaveHelper;
812 RdbDoubleWriteTest::slaveStore = RdbHelper::GetRdbStore(slaveConfig, 1, slaveHelper, errCode);
813 EXPECT_NE(RdbDoubleWriteTest::slaveStore, nullptr);
814 LOG_INFO("RdbStore_DoubleWrite_014 reopen slave db finish");
815
816 RdbDoubleWriteTest::CheckNumber(slaveStore, count);
817
818 id = 1000;
819 Insert(id, count);
820 LOG_INFO("RdbStore_DoubleWrite_014 insert finish");
821 RdbDoubleWriteTest::CheckNumber(slaveStore, 200); // 200 is all count
822 }
823
824 /**
825 * @tc.name: RdbStore_DoubleWrite_015
826 * @tc.desc: open MAIN_REPLICA db, write, close, corrupt, slave create table, open MAIN_REPLICA db. check count
827 * @tc.type: FUNC
828 */
829 HWTEST_F(RdbDoubleWriteTest, RdbStore_DoubleWrite_015, TestSize.Level1)
830 {
831 InitDb();
832 int64_t id = 10;
833 int count = 100;
834 ValuesBucket values;
835 for (int i = 0; i < count; i++) {
836 id++;
837 values.Clear();
838 values.PutInt("id", id);
839 values.PutString("name", std::string("zhangsan"));
840 values.PutInt("age", 18);
841 values.PutDouble("salary", CHECKCOLUMN);
842 values.PutBlob("blobType", std::vector<uint8_t>{ 1, 2, 3 });
843 int ret = store->Insert(id, "test", values);
844 EXPECT_EQ(ret, E_OK);
845 }
846 LOG_INFO("RdbStore_DoubleWrite_015 insert finish");
847
848 store = nullptr;
849
850 std::fstream file(DATABASE_NAME, std::ios::in | std::ios::out | std::ios::binary);
851 ASSERT_TRUE(file.is_open() == true);
852 file.seekp(30, std::ios::beg);
853 ASSERT_TRUE(file.good() == true);
854 char bytes[2] = { 0x6, 0x6 };
855 file.write(bytes, 2);
856 ASSERT_TRUE(file.good() == true);
857 file.close();
858 LOG_INFO("RdbStore_DoubleWrite_015 corrupt db finish");
859 SqliteUtils::DeleteFile(RdbDoubleWriteTest::DATABASE_NAME + "-dwr");
860 SqliteUtils::DeleteFile(RdbDoubleWriteTest::SLAVE_DATABASE_NAME + "-dwr");
861
862 int errCode = slaveStore->ExecuteSql("CREATE TABLE IF NOT EXISTS xx (id INTEGER PRIMARY KEY AUTOINCREMENT,"
863 "name TEXT NOT NULL, age INTEGER, salary REAL, blobType BLOB)");
864 EXPECT_EQ(errCode, E_OK);
865 EXPECT_EQ(slaveStore->Insert(id, "xx", values), E_OK);
866
867 RdbStoreConfig config(RdbDoubleWriteTest::DATABASE_NAME);
868 config.SetHaMode(HAMode::MAIN_REPLICA);
869 config.SetAllowRebuild(true);
870 DoubleWriteTestOpenCallback helper;
871 store = RdbHelper::GetRdbStore(config, 1, helper, errCode);
872 EXPECT_EQ(errCode, E_OK);
873 ASSERT_NE(store, nullptr);
874 LOG_INFO("RdbStore_DoubleWrite_015 reopen db finish");
875
876 RdbDoubleWriteTest::CheckNumber(store, 1, E_OK, std::string("xx"));
877 RdbDoubleWriteTest::CheckNumber(store, count);
878 RdbDoubleWriteTest::CheckNumber(slaveStore, 1, E_OK, std::string("xx"));
879 RdbDoubleWriteTest::CheckNumber(slaveStore, count);
880 }
881
882 /**
883 * @tc.name: RdbStore_DoubleWrite_016
884 * @tc.desc: open MAIN_REPLICA db, write, close, delete db file, reopen, check count
885 * @tc.type: FUNC
886 */
887 HWTEST_F(RdbDoubleWriteTest, RdbStore_DoubleWrite_016, TestSize.Level1)
888 {
889 InitDb();
890 int64_t id = 10;
891 int count = 100;
892 Insert(id, count);
893 LOG_INFO("RdbStore_DoubleWrite_016 insert finish");
894
895 store = nullptr;
896 LOG_INFO("RdbStore_DoubleWrite_016 close finish");
897
898 SqliteUtils::DeleteFile(DATABASE_NAME);
899 SqliteUtils::DeleteFile(DATABASE_NAME + "-shm");
900 SqliteUtils::DeleteFile(DATABASE_NAME + "-wal");
901 LOG_INFO("RdbStore_DoubleWrite_016 delete db file finish");
902
903 RdbStoreConfig config(RdbDoubleWriteTest::DATABASE_NAME);
904 config.SetHaMode(HAMode::MAIN_REPLICA);
905 DoubleWriteTestOpenCallback helper;
906 int errCode;
907 store = RdbHelper::GetRdbStore(config, 1, helper, errCode);
908 EXPECT_EQ(errCode, E_OK);
909 ASSERT_NE(store, nullptr);
910 LOG_INFO("RdbStore_DoubleWrite_016 reopen db finish");
911
912 WaitForBackupFinish(BACKUP_FINISHED);
913
914 RdbDoubleWriteTest::CheckNumber(store, count);
915 RdbDoubleWriteTest::CheckNumber(slaveStore, count);
916 }
917
918 /**
919 * @tc.name: RdbStore_DoubleWrite_018
920 * @tc.desc: open MAIN_REPLICA db, update slave, insert, M succ && S failed,
921 * check failureFlag, backup, check failureFlag
922 * @tc.type: FUNC
923 */
924 HWTEST_F(RdbDoubleWriteTest, RdbStore_DoubleWrite_018, TestSize.Level1)
925 {
926 InitDb();
927
928 int64_t id;
929 ValuesBucket values;
930 values.PutInt("id", 1);
931 values.PutString("name", std::string("zhangsan"));
932 values.PutInt("age", 25);
933 values.PutDouble("salary", CHECKCOLUMN);
934 values.PutBlob("blobType", std::vector<uint8_t>{ 1, 2, 3 });
935 int ret = store->Insert(id, "test", values);
936 EXPECT_EQ(ret, E_OK);
937
938 auto [ret2, outValue2] = slaveStore->Execute("UPDATE test SET id = 3 WHERE id = 1");
939 EXPECT_EQ(E_OK, ret2);
940
941 int64_t id2;
942 ValuesBucket values2;
943 values2.PutInt("id", 3);
944 values2.PutString("name", std::string("zhangsan"));
945 values2.PutInt("age", 25);
946 values2.PutDouble("salary", CHECKCOLUMN);
947 values2.PutBlob("blobType", std::vector<uint8_t>{ 1, 2, 3 });
948 int ret3 = store->Insert(id2, "test", values2);
949 EXPECT_EQ(E_OK, ret3);
950 std::string failureFlagPath = RdbDoubleWriteTest::DATABASE_NAME + +"-slaveFailure";
951 bool isFlagFileExists = OHOS::FileExists(failureFlagPath);
952 ASSERT_TRUE(isFlagFileExists);
953 ASSERT_TRUE(store->IsSlaveDiffFromMaster());
954
955 int errCode;
956 errCode = store->Backup(std::string(""), {});
957 EXPECT_EQ(errCode, E_OK);
958 isFlagFileExists = OHOS::FileExists(failureFlagPath);
959 ASSERT_FALSE(isFlagFileExists);
960 }
961
962 /**
963 * @tc.name: RdbStore_DoubleWrite_019
964 * @tc.desc: open MAIN_REPLICA db, update slave, insert, M succ && S failed,
965 * check failureFlag, reopen, check failureFlag
966 * @tc.type: FUNC
967 */
968 HWTEST_F(RdbDoubleWriteTest, RdbStore_DoubleWrite_019, TestSize.Level1)
969 {
970 InitDb();
971
972 int64_t id;
973 ValuesBucket values;
974 values.PutInt("id", 1);
975 values.PutString("name", std::string("zhangsan"));
976 values.PutInt("age", 25);
977 values.PutDouble("salary", CHECKCOLUMN);
978 values.PutBlob("blobType", std::vector<uint8_t>{ 1, 2, 3 });
979 int ret = store->Insert(id, "test", values);
980 EXPECT_EQ(ret, E_OK);
981
982 auto [ret2, outValue2] = slaveStore->Execute("UPDATE test SET id = 3 WHERE id = 1");
983 EXPECT_EQ(E_OK, ret2);
984
985 int64_t id2;
986 ValuesBucket values2;
987 values2.PutInt("id", 3);
988 values2.PutString("name", std::string("zhangsan"));
989 values2.PutInt("age", 25);
990 values2.PutDouble("salary", CHECKCOLUMN);
991 values2.PutBlob("blobType", std::vector<uint8_t>{ 1, 2, 3 });
992 int ret3 = store->Insert(id2, "test", values2);
993 EXPECT_EQ(E_OK, ret3);
994 std::string failureFlagPath = RdbDoubleWriteTest::DATABASE_NAME + +"-slaveFailure";
995 bool isFlagFileExists = OHOS::FileExists(failureFlagPath);
996 ASSERT_TRUE(isFlagFileExists);
997 ASSERT_TRUE(store->IsSlaveDiffFromMaster());
998
999 store = nullptr;
1000 RdbStoreConfig config(RdbDoubleWriteTest::DATABASE_NAME);
1001 config.SetHaMode(HAMode::MAIN_REPLICA);
1002 config.SetAllowRebuild(true);
1003 DoubleWriteTestOpenCallback helper;
1004 int errCode;
1005 store = RdbHelper::GetRdbStore(config, 1, helper, errCode);
1006 WaitForBackupFinish(BACKUP_FINISHED);
1007 store = nullptr;
1008 isFlagFileExists = OHOS::FileExists(failureFlagPath);
1009 ASSERT_FALSE(isFlagFileExists);
1010 }
1011
1012 /**
1013 * @tc.name: RdbStore_DoubleWrite_026
1014 * @tc.desc: open MANUAL_TRIGGER db, write, restore, insert, check count
1015 * @tc.type: FUNC
1016 */
1017 HWTEST_F(RdbDoubleWriteTest, RdbStore_DoubleWrite_026, TestSize.Level1)
1018 {
1019 int errCode = E_OK;
1020 RdbStoreConfig config(RdbDoubleWriteTest::DATABASE_NAME);
1021 config.SetHaMode(HAMode::MANUAL_TRIGGER);
1022 DoubleWriteTestOpenCallback helper;
1023 store = RdbHelper::GetRdbStore(config, 1, helper, errCode);
1024 EXPECT_EQ(errCode, E_OK);
1025 ASSERT_NE(store, nullptr);
1026
1027 int64_t id = 10;
1028 int count = 100;
1029 Insert(id, count);
1030
1031 EXPECT_EQ(store->Restore(std::string(""), {}), E_INVALID_FILE_PATH);
1032
1033 id = 2000;
1034 Insert(id, count);
1035 RdbDoubleWriteTest::CheckNumber(store, count + count);
1036 }
1037
1038 /**
1039 * @tc.name: RdbStore_DoubleWrite_027
1040 * @tc.desc: open MANUAL_TRIGGER db, write, close, corrupt db, reopen, insert, check count
1041 * @tc.type: FUNC
1042 */
1043 HWTEST_F(RdbDoubleWriteTest, RdbStore_DoubleWrite_027, TestSize.Level1)
1044 {
1045 int errCode = E_OK;
1046 RdbStoreConfig config(RdbDoubleWriteTest::DATABASE_NAME);
1047 config.SetHaMode(HAMode::MANUAL_TRIGGER);
1048 config.SetAllowRebuild(true);
1049 DoubleWriteTestOpenCallback helper;
1050
1051 RdbStoreConfig slaveConfig(RdbDoubleWriteTest::SLAVE_DATABASE_NAME);
1052 DoubleWriteTestOpenCallback slaveHelper;
1053 RdbDoubleWriteTest::slaveStore = RdbHelper::GetRdbStore(slaveConfig, 1, slaveHelper, errCode);
1054 EXPECT_NE(RdbDoubleWriteTest::slaveStore, nullptr);
1055
1056 store = RdbHelper::GetRdbStore(config, 1, helper, errCode);
1057 EXPECT_EQ(errCode, E_OK);
1058 ASSERT_NE(store, nullptr);
1059
1060 int64_t id = 10;
1061 int count = 100;
1062 Insert(id, count);
1063 RdbDoubleWriteTest::CheckNumber(slaveStore, count);
1064
1065 store = nullptr;
1066
1067 std::fstream file(DATABASE_NAME, std::ios::in | std::ios::out | std::ios::binary);
1068 ASSERT_TRUE(file.is_open() == true);
1069 file.seekp(30, std::ios::beg);
1070 ASSERT_TRUE(file.good() == true);
1071 char bytes[2] = { 0x6, 0x6 };
1072 file.write(bytes, 2);
1073 ASSERT_TRUE(file.good() == true);
1074 file.close();
1075
1076 store = RdbHelper::GetRdbStore(config, 1, helper, errCode);
1077 EXPECT_EQ(errCode, E_OK);
1078 ASSERT_NE(store, nullptr);
1079
1080 id = 1000;
1081 Insert(id, count);
1082 RdbDoubleWriteTest::CheckNumber(store, count + count);
1083 }
1084
1085 /**
1086 * @tc.name: RdbStore_DoubleWrite_029
1087 * @tc.desc: open db, write, corrupt slave db, backup, backup, check count
1088 * @tc.type: FUNC
1089 */
1090 HWTEST_F(RdbDoubleWriteTest, RdbStore_DoubleWrite_029, TestSize.Level1)
1091 {
1092 InitDb();
1093 int64_t id = 10;
1094 int count = 100;
1095 Insert(id, count);
1096
1097 std::fstream slaveFile(SLAVE_DATABASE_NAME, std::ios::in | std::ios::out | std::ios::trunc);
1098 ASSERT_TRUE(slaveFile.is_open() == true);
1099 slaveFile << "0000";
1100 slaveFile.flush();
1101 slaveFile.close();
1102
1103 std::fstream slaveWalFile(SLAVE_DATABASE_NAME + "-wal", std::ios::in | std::ios::out | std::ios::trunc);
1104 ASSERT_TRUE(slaveWalFile.is_open() == true);
1105 slaveWalFile << "0000";
1106 slaveWalFile.flush();
1107 slaveWalFile.close();
1108
1109 EXPECT_NE(store->Backup(std::string(""), {}), E_OK);
1110 LOG_INFO("RdbStore_DoubleWrite_029 backup again");
1111 EXPECT_EQ(store->Backup(std::string(""), {}), E_OK);
1112
1113 RdbDoubleWriteTest::CheckNumber(store, count);
1114 RdbDoubleWriteTest::CheckNumber(slaveStore, -1, E_SQLITE_CORRUPT);
1115
1116 int errCode = E_OK;
1117 slaveStore = nullptr;
1118 RdbStoreConfig slaveConfig(RdbDoubleWriteTest::SLAVE_DATABASE_NAME);
1119 DoubleWriteTestOpenCallback slaveHelper;
1120 RdbDoubleWriteTest::slaveStore = RdbHelper::GetRdbStore(slaveConfig, 1, slaveHelper, errCode);
1121 EXPECT_NE(RdbDoubleWriteTest::slaveStore, nullptr);
1122
1123 RdbDoubleWriteTest::CheckNumber(slaveStore, count);
1124 }
1125
1126 /**
1127 * @tc.name: RdbStore_DoubleWrite_030
1128 * @tc.desc: open db, write, update slave, insert, check failure, restore, check count
1129 * @tc.type: FUNC
1130 */
1131 HWTEST_F(RdbDoubleWriteTest, RdbStore_DoubleWrite_030, TestSize.Level1)
1132 {
1133 InitDb();
1134 int64_t id = 10;
1135 int count = 100;
1136 Insert(id, count);
1137
1138 auto [ret2, outValue2] = slaveStore->Execute("UPDATE test SET id = 666 WHERE id = 22");
1139 EXPECT_EQ(E_OK, ret2);
1140
1141 id = 666;
1142 Insert(id, 1);
1143
1144 std::string failureFlagPath = RdbDoubleWriteTest::DATABASE_NAME + +"-slaveFailure";
1145 bool isFlagFileExists = OHOS::FileExists(failureFlagPath);
1146 ASSERT_TRUE(isFlagFileExists);
1147
1148 EXPECT_NE(store->Restore(std::string(""), {}), E_OK);
1149
1150 RdbDoubleWriteTest::CheckNumber(store, count + 1);
1151 RdbDoubleWriteTest::CheckNumber(slaveStore, count);
1152 }
1153
1154 /**
1155 * @tc.name: RdbStore_DoubleWrite_031
1156 * @tc.desc: open db, delete main.db, deleteRdbStore, check slave db
1157 * @tc.type: FUNC
1158 */
1159 HWTEST_F(RdbDoubleWriteTest, RdbStore_DoubleWrite_031, TestSize.Level1)
1160 {
1161 InitDb();
1162 remove(RdbDoubleWriteTest::DATABASE_NAME.c_str());
1163 RdbHelper::DeleteRdbStore(RdbDoubleWriteTest::DATABASE_NAME);
1164 EXPECT_NE(access(RdbDoubleWriteTest::SLAVE_DATABASE_NAME.c_str(), F_OK), 0);
1165 }
1166
1167 /**
1168 * @tc.name: RdbStore_DoubleWrite_032
1169 * @tc.desc: open db, delete main.db, deleteRdbStore, check slave db
1170 * @tc.type: FUNC
1171 */
1172 HWTEST_F(RdbDoubleWriteTest, RdbStore_DoubleWrite_032, TestSize.Level1)
1173 {
1174 InitDb();
1175 remove(RdbDoubleWriteTest::DATABASE_NAME.c_str());
1176 RdbStoreConfig config(RdbDoubleWriteTest::DATABASE_NAME);
1177 RdbHelper::DeleteRdbStore(config);
1178 EXPECT_NE(access(RdbDoubleWriteTest::SLAVE_DATABASE_NAME.c_str(), F_OK), 0);
1179 }
1180
1181 /**
1182 * @tc.name: RdbStore_DoubleWrite_033
1183 * @tc.desc: open db, write, close, corrupt, open SINGLE db, check
1184 * @tc.type: FUNC
1185 */
1186 HWTEST_F(RdbDoubleWriteTest, RdbStore_DoubleWrite_033, TestSize.Level1)
1187 {
1188 InitDb();
1189 int64_t id = 10;
1190 int count = 100;
1191 Insert(id, count);
1192
1193 store = nullptr;
1194 slaveStore = nullptr;
1195
1196 std::fstream file(DATABASE_NAME, std::ios::in | std::ios::out | std::ios::binary);
1197 ASSERT_TRUE(file.is_open() == true);
1198 file.seekp(30, std::ios::beg);
1199 ASSERT_TRUE(file.good() == true);
1200 char bytes[2] = { 0x6, 0x6 };
1201 file.write(bytes, 2);
1202 ASSERT_TRUE(file.good() == true);
1203 file.close();
1204
1205 SqliteUtils::DeleteFile(RdbDoubleWriteTest::DATABASE_NAME + "-dwr");
1206 SqliteUtils::DeleteFile(RdbDoubleWriteTest::SLAVE_DATABASE_NAME + "-dwr");
1207 int errCode = E_OK;
1208 RdbStoreConfig config(RdbDoubleWriteTest::DATABASE_NAME);
1209 config.SetHaMode(HAMode::SINGLE);
1210 DoubleWriteTestOpenCallback helper;
1211 store = RdbHelper::GetRdbStore(config, 1, helper, errCode);
1212 EXPECT_EQ(errCode, E_OK);
1213 ASSERT_NE(store, nullptr);
1214
1215 RebuiltType rebuiltType;
1216 store->GetRebuilt(rebuiltType);
1217 EXPECT_EQ(rebuiltType, RebuiltType::REPAIRED);
1218
1219 RdbDoubleWriteTest::CheckNumber(store, count);
1220 }
1221
1222 /**
1223 * @tc.name: RdbStore_DoubleWrite_034
1224 * @tc.desc: open db, close, open SINGLE db, create index, write, reopen, check slave db
1225 * @tc.type: FUNC
1226 */
1227 HWTEST_F(RdbDoubleWriteTest, RdbStore_DoubleWrite_034, TestSize.Level1)
1228 {
1229 InitDb();
1230 store = nullptr;
1231 slaveStore = nullptr;
1232 int errCode = E_OK;
1233 RdbStoreConfig config(RdbDoubleWriteTest::DATABASE_NAME);
1234 config.SetHaMode(HAMode::SINGLE);
1235 DoubleWriteTestOpenCallback helper;
1236 store = RdbHelper::GetRdbStore(config, 1, helper, errCode);
1237 EXPECT_EQ(errCode, E_OK);
1238 ASSERT_NE(store, nullptr);
1239 EXPECT_EQ(store->ExecuteSql("CREATE index age_index ON test(age);"), E_OK);
1240 int64_t id = 10;
1241 int count = 10;
1242 Insert(id, count);
1243 store = nullptr;
1244
1245 config.SetHaMode(HAMode::MAIN_REPLICA);
1246 store = RdbHelper::GetRdbStore(config, 1, helper, errCode);
1247 ASSERT_NE(store, nullptr);
1248 RdbStoreConfig slaveConfig(RdbDoubleWriteTest::SLAVE_DATABASE_NAME);
1249 DoubleWriteTestOpenCallback slaveHelper;
1250 slaveStore = RdbHelper::GetRdbStore(slaveConfig, 1, slaveHelper, errCode);
1251 ASSERT_NE(RdbDoubleWriteTest::slaveStore, nullptr);
1252 WaitForBackupFinish(BACKUP_FINISHED);
1253 RdbDoubleWriteTest::CheckNumber(slaveStore, count);
1254 store = nullptr;
1255 slaveStore = nullptr;
1256 }
1257
1258 /**
1259 * @tc.name: RdbStore_DoubleWrite_Manual_Trigger_Not_Verify_Db
1260 * @tc.desc: open MANUAL_TRIGGER db, write, corrupt db, check backup with verify and no verify
1261 * @tc.type: FUNC
1262 */
1263 HWTEST_F(RdbDoubleWriteTest, RdbStore_DoubleWrite_Manual_Trigger_Not_Verify_Db, TestSize.Level0)
1264 {
1265 int errCode = E_OK;
1266 RdbStoreConfig config(RdbDoubleWriteTest::DATABASE_NAME);
1267 config.SetHaMode(HAMode::MANUAL_TRIGGER);
1268 DoubleWriteTestOpenCallback helper;
1269 store = RdbHelper::GetRdbStore(config, 1, helper, errCode);
1270 EXPECT_EQ(errCode, E_OK);
1271 ASSERT_NE(store, nullptr);
1272 LOG_INFO("RdbStore_DoubleWrite_Manual_Trigger_Not_Verify_Db reopen main db finish");
1273
1274 int64_t id = 10;
1275 int count = 100;
1276 Insert(id, count);
1277 LOG_INFO("RdbStore_DoubleWrite_Manual_Trigger_Not_Verify_Db insert finish");
1278
1279 RdbDoubleWriteTest::CheckNumber(store, count);
1280 store = nullptr;
1281
1282 std::fstream file(RdbDoubleWriteTest::DATABASE_NAME, std::ios::in | std::ios::out | std::ios::binary);
1283 ASSERT_TRUE(file.is_open());
1284
1285 file.seekp(0x2000, std::ios::beg);
1286 ASSERT_TRUE(file.good());
1287
1288 char bytes[128];
1289 std::fill_n(bytes, 128, 0xff);
1290 file.write(bytes, 128);
1291 file.flush();
1292 file.close();
1293 LOG_INFO("RdbStore_DoubleWrite_Manual_Trigger_Not_Verify_Db corrupt db finish");
1294
1295 store = RdbHelper::GetRdbStore(config, 1, helper, errCode);
1296 EXPECT_EQ(errCode, E_OK);
1297 ASSERT_NE(store, nullptr);
1298
1299 errCode = store->Backup(std::string(""));
1300 EXPECT_EQ(errCode, E_SQLITE_CORRUPT);
1301
1302 errCode = store->Backup(std::string(""), {}, false);
1303 EXPECT_EQ(errCode, E_OK);
1304 store = nullptr;
1305 }
1306
1307 /**
1308 * @tc.name: RdbStore_DoubleWrite_Huge_DB_001
1309 * @tc.desc: test db is deleted while open huge database, in MANUAL_TRIGGER
1310 * @tc.type: FUNC
1311 */
1312 HWTEST_F(RdbDoubleWriteTest, RdbStore_DoubleWrite_Huge_DB_001, TestSize.Level3)
1313 {
1314 LOG_INFO("---- start RdbStore_DoubleWrite_Huge_DB_001 ----");
1315 InitDb(HAMode::MANUAL_TRIGGER);
1316 int errCode = store->Backup(std::string(""), {});
1317 EXPECT_EQ(errCode, E_OK);
1318 int64_t id = 10;
1319 int count = 200;
1320 LOG_INFO("---- step 1: insert huge data ----");
1321 Insert(id, count, false, HUGE_DATA_SIZE);
1322 RdbDoubleWriteTest::CheckNumber(store, count);
1323 RdbDoubleWriteTest::CheckNumber(slaveStore, count);
1324 LOG_INFO("---- step 2: close store ----");
1325 store = nullptr;
1326 slaveStore = nullptr;
1327 LOG_INFO("---- step 3: remove db file ----");
1328 remove(RdbDoubleWriteTest::DATABASE_NAME.c_str());
1329 LOG_INFO("---- step 4: reopen and trigger restore ----");
1330 SqliteUtils::DeleteFile(RdbDoubleWriteTest::DATABASE_NAME + "-dwr");
1331 SqliteUtils::DeleteFile(RdbDoubleWriteTest::SLAVE_DATABASE_NAME + "-dwr");
1332 RdbStoreConfig config(RdbDoubleWriteTest::DATABASE_NAME);
1333 config.SetHaMode(HAMode::MANUAL_TRIGGER);
1334 DoubleWriteTestOpenCallback helper;
1335 store = RdbHelper::GetRdbStore(config, 1, helper, errCode);
1336 if (errCode != E_SQLITE_BUSY) {
1337 EXPECT_EQ(errCode, E_OK);
1338 ASSERT_NE(store, nullptr);
1339 LOG_INFO("---- step 5: execute sql while restore ----");
1340 EXPECT_EQ(store->ExecuteSql("select * from test;"), E_DATABASE_BUSY);
1341 LOG_INFO("---- step 6: check db count ----");
1342 RdbDoubleWriteTest::WaitForAsyncRepairFinish();
1343 RdbDoubleWriteTest::CheckNumber(store, count);
1344 }
1345 LOG_INFO("---- end RdbStore_DoubleWrite_Huge_DB_001 ----");
1346 }
1347
1348 /**
1349 * @tc.name: RdbStore_DoubleWrite_Huge_DB_002
1350 * @tc.desc: test db is deleted while open huge database, in MAIN_REPLICA
1351 * @tc.type: FUNC
1352 */
1353 HWTEST_F(RdbDoubleWriteTest, RdbStore_DoubleWrite_Huge_DB_002, TestSize.Level3)
1354 {
1355 if (!IsUsingArkData()) {
1356 GTEST_SKIP() << "Current testcase is not compatible from current rdb";
1357 }
1358 LOG_INFO("---- start RdbStore_DoubleWrite_Huge_DB_002 ----");
1359 InitDb();
1360 int64_t id = 10;
1361 int count = 200;
1362 LOG_INFO("---- step 1: insert huge data ----");
1363 Insert(id, count, false, HUGE_DATA_SIZE);
1364 RdbDoubleWriteTest::CheckNumber(store, count);
1365 RdbDoubleWriteTest::CheckNumber(slaveStore, count);
1366 LOG_INFO("---- step 2: close store ----");
1367 store = nullptr;
1368 slaveStore = nullptr;
1369 LOG_INFO("---- step 3: remove db file ----");
1370 remove(RdbDoubleWriteTest::DATABASE_NAME.c_str());
1371 LOG_INFO("---- step 4: reopen and trigger restore ----");
1372 SqliteUtils::DeleteFile(RdbDoubleWriteTest::DATABASE_NAME + "-dwr");
1373 SqliteUtils::DeleteFile(RdbDoubleWriteTest::SLAVE_DATABASE_NAME + "-dwr");
1374 int errCode = E_OK;
1375 RdbStoreConfig config(RdbDoubleWriteTest::DATABASE_NAME);
1376 config.SetHaMode(HAMode::MAIN_REPLICA);
1377 DoubleWriteTestOpenCallback helper;
1378 store = RdbHelper::GetRdbStore(config, 1, helper, errCode);
1379 if (errCode != E_SQLITE_BUSY) {
1380 EXPECT_EQ(errCode, E_OK);
1381 ASSERT_NE(store, nullptr);
1382 LOG_INFO("---- step 5: execute sql while restore ----");
1383 EXPECT_EQ(store->ExecuteSql("select * from test;"), E_DATABASE_BUSY);
1384 LOG_INFO("---- step 6: check db count ----");
1385 RdbDoubleWriteTest::WaitForAsyncRepairFinish();
1386 RdbDoubleWriteTest::CheckNumber(store, count);
1387 }
1388 LOG_INFO("---- end RdbStore_DoubleWrite_Huge_DB_002 ----");
1389 }
1390
1391 /**
1392 * @tc.name: RdbStore_DoubleWrite_Huge_DB_003
1393 * @tc.desc: test async restore for huge db in MAIN_REPLICA
1394 * @tc.type: FUNC
1395 */
1396 HWTEST_F(RdbDoubleWriteTest, RdbStore_DoubleWrite_Huge_DB_003, TestSize.Level3)
1397 {
1398 if (!IsUsingArkData()) {
1399 GTEST_SKIP() << "Current testcase is not compatible from current rdb";
1400 }
1401 LOG_INFO("---- start RdbStore_DoubleWrite_Huge_DB_003 ----");
1402 InitDb();
1403 int64_t id = 10;
1404 int count = 200;
1405 LOG_INFO("---- step 1: insert huge data ----");
1406 Insert(id, count, false, HUGE_DATA_SIZE);
1407 RdbDoubleWriteTest::CheckNumber(store, count);
1408 RdbDoubleWriteTest::CheckNumber(slaveStore, count);
1409 LOG_INFO("---- step 2: corrupt store ----");
1410 std::fstream file(DATABASE_NAME, std::ios::in | std::ios::out | std::ios::binary);
1411 ASSERT_TRUE(file.is_open() == true);
1412 file.seekp(30, std::ios::beg);
1413 ASSERT_TRUE(file.good() == true);
1414 char bytes[2] = { 0x6, 0x6 };
1415 file.write(bytes, 2);
1416 ASSERT_TRUE(file.good() == true);
1417 file.close();
1418 LOG_INFO("---- step 3: manually trigger repair ----");
1419 EXPECT_EQ(store->Restore(std::string(""), {}), E_OK);
1420 EXPECT_EQ(store->ExecuteSql("select * from test;"), E_DATABASE_BUSY);
1421 LOG_INFO("---- step 4: check db count ----");
1422 RdbDoubleWriteTest::WaitForAsyncRepairFinish();
1423 RdbDoubleWriteTest::CheckNumber(store, count);
1424 LOG_INFO("---- end RdbStore_DoubleWrite_Huge_DB_003 ----");
1425 }
1426
1427 /**
1428 * @tc.name: RdbStore_DoubleWrite_Huge_DB_004
1429 * @tc.desc: test async restore for huge db in MANUAL_TRIGGER
1430 * @tc.type: FUNC
1431 */
1432 HWTEST_F(RdbDoubleWriteTest, RdbStore_DoubleWrite_Huge_DB_004, TestSize.Level3)
1433 {
1434 if (!IsUsingArkData()) {
1435 GTEST_SKIP() << "Current testcase is not compatible from current rdb";
1436 }
1437 LOG_INFO("---- start RdbStore_DoubleWrite_Huge_DB_004 ----");
1438 InitDb(HAMode::MANUAL_TRIGGER);
1439 int errCode = store->Backup(std::string(""), {});
1440 EXPECT_EQ(errCode, E_OK);
1441 int64_t id = 10;
1442 int count = 200;
1443 LOG_INFO("---- step 1: insert huge data ----");
1444 Insert(id, count, false, HUGE_DATA_SIZE);
1445 RdbDoubleWriteTest::CheckNumber(store, count);
1446 RdbDoubleWriteTest::CheckNumber(slaveStore, count);
1447 LOG_INFO("---- step 2: corrupt store ----");
1448 std::fstream file(DATABASE_NAME, std::ios::in | std::ios::out | std::ios::binary);
1449 ASSERT_TRUE(file.is_open() == true);
1450 file.seekp(30, std::ios::beg);
1451 ASSERT_TRUE(file.good() == true);
1452 char bytes[2] = { 0x6, 0x6 };
1453 file.write(bytes, 2);
1454 ASSERT_TRUE(file.good() == true);
1455 file.close();
1456 LOG_INFO("---- step 3: manually trigger repair ----");
1457 EXPECT_EQ(store->Restore(std::string(""), {}), E_OK);
1458 EXPECT_EQ(store->ExecuteSql("select * from test;"), E_DATABASE_BUSY);
1459 LOG_INFO("---- step 4: check db count ----");
1460 RdbDoubleWriteTest::WaitForAsyncRepairFinish();
1461 RdbDoubleWriteTest::CheckNumber(store, count);
1462 LOG_INFO("---- end RdbStore_DoubleWrite_Huge_DB_004 ----");
1463 }
1464
1465 /**
1466 * @tc.name: RdbStore_DoubleWrite_Huge_DB_005
1467 * @tc.desc: test restore is called while doing async restore
1468 * @tc.type: FUNC
1469 */
1470 HWTEST_F(RdbDoubleWriteTest, RdbStore_DoubleWrite_Huge_DB_005, TestSize.Level3)
1471 {
1472 if (!IsUsingArkData()) {
1473 GTEST_SKIP() << "Current testcase is not compatible from current rdb";
1474 }
1475 LOG_INFO("---- start RdbStore_DoubleWrite_Huge_DB_005 ----");
1476 InitDb(HAMode::MANUAL_TRIGGER);
1477 int errCode = store->Backup(std::string(""), {});
1478 EXPECT_EQ(errCode, E_OK);
1479 int64_t id = 10;
1480 int count = 200;
1481 LOG_INFO("---- step 1: insert huge data ----");
1482 Insert(id, count, false, HUGE_DATA_SIZE);
1483 RdbDoubleWriteTest::CheckNumber(store, count);
1484 RdbDoubleWriteTest::CheckNumber(slaveStore, count);
1485 LOG_INFO("---- step 2: corrupt store ----");
1486 std::fstream file(DATABASE_NAME, std::ios::in | std::ios::out | std::ios::binary);
1487 ASSERT_TRUE(file.is_open() == true);
1488 file.seekp(30, std::ios::beg);
1489 ASSERT_TRUE(file.good() == true);
1490 char bytes[2] = { 0x6, 0x6 };
1491 file.write(bytes, 2);
1492 ASSERT_TRUE(file.good() == true);
1493 file.close();
1494 LOG_INFO("---- step 3: manually trigger repair ----");
1495 EXPECT_EQ(store->Restore(std::string(""), {}), E_OK);
1496 EXPECT_EQ(store->ExecuteSql("select * from test;"), E_DATABASE_BUSY);
1497 LOG_INFO("---- step 4: trigger repair again ----");
1498 EXPECT_EQ(store->Restore(std::string(""), {}), E_OK);
1499 LOG_INFO("---- step 5: check db count ----");
1500 RdbDoubleWriteTest::WaitForAsyncRepairFinish();
1501 RdbDoubleWriteTest::CheckNumber(store, count);
1502 LOG_INFO("---- end RdbStore_DoubleWrite_Huge_DB_005 ----");
1503 }
1504
1505 /**
1506 * @tc.name: RdbStore_DoubleWrite_Huge_DB_006
1507 * @tc.desc: test call restore for huge db when slave db is corrupted
1508 * @tc.type: FUNC
1509 */
1510 HWTEST_F(RdbDoubleWriteTest, RdbStore_DoubleWrite_Huge_DB_006, TestSize.Level3)
1511 {
1512 if (!IsUsingArkData()) {
1513 GTEST_SKIP() << "Current testcase is not compatible from current rdb";
1514 }
1515 LOG_INFO("---- start RdbStore_DoubleWrite_Huge_DB_006 ----");
1516 InitDb(HAMode::MANUAL_TRIGGER);
1517 int errCode = store->Backup(std::string(""), {});
1518 EXPECT_EQ(errCode, E_OK);
1519 int64_t id = 10;
1520 int count = 200;
1521 LOG_INFO("---- step 1: insert huge data ----");
1522 Insert(id, count, false, HUGE_DATA_SIZE);
1523 RdbDoubleWriteTest::CheckNumber(store, count);
1524 RdbDoubleWriteTest::CheckNumber(slaveStore, count);
1525 LOG_INFO("---- step 2: corrupt store ----");
1526 std::fstream file(DATABASE_NAME, std::ios::in | std::ios::out | std::ios::binary);
1527 ASSERT_TRUE(file.is_open() == true);
1528 file.seekp(30, std::ios::beg);
1529 ASSERT_TRUE(file.good() == true);
1530 char bytes[2] = { 0x6, 0x6 };
1531 file.write(bytes, 2);
1532 ASSERT_TRUE(file.good() == true);
1533 file.close();
1534 LOG_INFO("---- step 3: mark backup db corrupted ----");
1535 SqliteUtils::SetSlaveInvalid(DATABASE_NAME);
1536 EXPECT_TRUE(SqliteUtils::IsSlaveInvalid(DATABASE_NAME));
1537 LOG_INFO("---- step 4: manually trigger repair ----");
1538 EXPECT_EQ(store->Restore(std::string(""), {}), E_SQLITE_CORRUPT);
1539 LOG_INFO("---- end RdbStore_DoubleWrite_Huge_DB_006 ----");
1540 }
1541
1542 /**
1543 * @tc.name: RdbStore_DoubleWrite_Huge_DB_007
1544 * @tc.desc: test execsql when restore mark is abnormal
1545 * @tc.type: FUNC
1546 */
1547 HWTEST_F(RdbDoubleWriteTest, RdbStore_DoubleWrite_Huge_DB_007, TestSize.Level3)
1548 {
1549 if (!IsUsingArkData()) {
1550 GTEST_SKIP() << "Current testcase is not compatible from current rdb";
1551 }
1552 LOG_INFO("---- start RdbStore_DoubleWrite_Huge_DB_007 ----");
1553 InitDb(HAMode::MANUAL_TRIGGER);
1554 int errCode = store->Backup(std::string(""), {});
1555 EXPECT_EQ(errCode, E_OK);
1556 int64_t id = 10;
1557 int count = 200;
1558 LOG_INFO("---- step 1: insert huge data ----");
1559 Insert(id, count, false, HUGE_DATA_SIZE);
1560 RdbDoubleWriteTest::CheckNumber(store, count);
1561 RdbDoubleWriteTest::CheckNumber(slaveStore, count);
1562 LOG_INFO("---- step 2: mark backup db as restoring ----");
1563 SqliteUtils::SetSlaveRestoring(DATABASE_NAME);
1564 EXPECT_TRUE(SqliteUtils::IsSlaveRestoring(DATABASE_NAME));
1565 LOG_INFO("---- step 3: manually trigger create statement should remove the mark ----");
1566 EXPECT_EQ(store->ExecuteSql("select * from test;"), E_OK);
1567 EXPECT_FALSE(SqliteUtils::IsSlaveRestoring(DATABASE_NAME));
1568 LOG_INFO("---- step 4: lock database for restoring and trigger create statement should not remove the mark ----");
1569 SqliteUtils::SetSlaveRestoring(DATABASE_NAME);
1570 EXPECT_TRUE(SqliteUtils::IsSlaveRestoring(DATABASE_NAME));
1571 auto keyFiles = RdbSecurityManager::KeyFiles(DATABASE_NAME + "-async.restore");
1572 EXPECT_EQ(keyFiles.Lock(false), E_OK);
1573 LOG_INFO("---- step 5: manually trigger create statement should not remove the mark ----");
1574 EXPECT_EQ(store->ExecuteSql("select * from test;"), E_DATABASE_BUSY);
1575 EXPECT_TRUE(SqliteUtils::IsSlaveRestoring(DATABASE_NAME));
1576 SqliteUtils::SetSlaveRestoring(DATABASE_NAME, false);
1577 keyFiles.Unlock();
1578 LOG_INFO("---- end RdbStore_DoubleWrite_Huge_DB_007 ----");
1579 }
1580
1581 /**
1582 * @tc.name: RdbStore_DoubleWrite_Huge_DB_008
1583 * @tc.desc: test trigger async repair
1584 * @tc.type: FUNC
1585 */
1586 HWTEST_F(RdbDoubleWriteTest, RdbStore_DoubleWrite_Huge_DB_008, TestSize.Level3)
1587 {
1588 if (!IsUsingArkData()) {
1589 GTEST_SKIP() << "Current testcase is not compatible from current rdb";
1590 }
1591 LOG_INFO("---- start RdbStore_DoubleWrite_Huge_DB_008 ----");
1592 InitDb(HAMode::MANUAL_TRIGGER);
1593 int errCode = store->Backup(std::string(""), {});
1594 EXPECT_EQ(errCode, E_OK);
1595 int64_t id = 10;
1596 int count = 200;
1597 LOG_INFO("---- step 1: insert huge data ----");
1598 Insert(id, count, false, HUGE_DATA_SIZE);
1599 RdbDoubleWriteTest::CheckNumber(store, count);
1600 RdbDoubleWriteTest::CheckNumber(slaveStore, count);
1601 LOG_INFO("---- step 2: corrupt both slave and master db ----");
1602 store = nullptr;
1603 slaveStore = nullptr;
1604 EXPECT_TRUE(SqliteUtils::CopyFile(DATABASE_NAME + "-dwr", DATABASE_NAME));
1605 std::fstream file(SLAVE_DATABASE_NAME, std::ios::in | std::ios::out | std::ios::binary);
1606 file.seekp(1, std::ios::beg);
1607 std::vector<char> null_buffer(count, '\0');
1608 file.write(null_buffer.data(), count);
1609 file.close();
1610 SqliteUtils::DeleteFile(RdbDoubleWriteTest::DATABASE_NAME + "-dwr");
1611 SqliteUtils::DeleteFile(RdbDoubleWriteTest::SLAVE_DATABASE_NAME + "-dwr");
1612 SqliteUtils::SetSlaveInvalid(DATABASE_NAME);
1613 EXPECT_TRUE(SqliteUtils::IsSlaveInvalid(DATABASE_NAME));
1614
1615 LOG_INFO("---- step 3: reopen should give E_SQLITE_CORRUPT ----");
1616 RdbStoreConfig config(RdbDoubleWriteTest::DATABASE_NAME);
1617 config.SetHaMode(HAMode::MANUAL_TRIGGER);
1618 DoubleWriteTestOpenCallback helper;
1619 store = RdbHelper::GetRdbStore(config, 1, helper, errCode);
1620 EXPECT_EQ(errCode, E_SQLITE_CORRUPT);
1621 LOG_INFO("---- end RdbStore_DoubleWrite_Huge_DB_008 ----");
1622 }
1623
1624 /**
1625 * @tc.name: RdbStore_DoubleWrite_Huge_DB_009
1626 * @tc.desc: test trigger async repair
1627 * @tc.type: FUNC
1628 */
1629 HWTEST_F(RdbDoubleWriteTest, RdbStore_DoubleWrite_Huge_DB_009, TestSize.Level3)
1630 {
1631 if (!IsUsingArkData()) {
1632 GTEST_SKIP() << "Current testcase is not compatible from current rdb";
1633 }
1634 LOG_INFO("---- start RdbStore_DoubleWrite_Huge_DB_009 ----");
1635 InitDb(HAMode::MANUAL_TRIGGER);
1636 int errCode = store->Backup(std::string(""), {});
1637 EXPECT_EQ(errCode, E_OK);
1638 int64_t id = 10;
1639 int count = 200;
1640 LOG_INFO("---- step 1: insert huge data ----");
1641 Insert(id, count, false, HUGE_DATA_SIZE);
1642 RdbDoubleWriteTest::CheckNumber(store, count);
1643 RdbDoubleWriteTest::CheckNumber(slaveStore, count);
1644 LOG_INFO("---- step 2: corrupt master db ----");
1645 store = nullptr;
1646 slaveStore = nullptr;
1647 EXPECT_TRUE(SqliteUtils::CopyFile(DATABASE_NAME + "-dwr", DATABASE_NAME));
1648 SqliteUtils::DeleteFile(RdbDoubleWriteTest::DATABASE_NAME + "-dwr");
1649 SqliteUtils::DeleteFile(RdbDoubleWriteTest::SLAVE_DATABASE_NAME + "-dwr");
1650 LOG_INFO("---- step 3: reopen should give ok ----");
1651 RdbStoreConfig config(RdbDoubleWriteTest::DATABASE_NAME);
1652 config.SetHaMode(HAMode::MANUAL_TRIGGER);
1653 DoubleWriteTestOpenCallback helper;
1654 store = RdbHelper::GetRdbStore(config, 1, helper, errCode);
1655 if (errCode != E_SQLITE_BUSY) {
1656 EXPECT_EQ(errCode, E_OK);
1657 ASSERT_NE(store, nullptr);
1658 LOG_INFO("---- step 4: trigger statement should busy ----");
1659 EXPECT_EQ(store->ExecuteSql("select * from test;"), E_DATABASE_BUSY);
1660 store = nullptr;
1661 }
1662 LOG_INFO("---- step 5: check db count ----");
1663 RdbDoubleWriteTest::WaitForAsyncRepairFinish();
1664 store = RdbHelper::GetRdbStore(config, 1, helper, errCode);
1665 ASSERT_NE(store, nullptr);
1666 RdbDoubleWriteTest::CheckNumber(store, count);
1667 LOG_INFO("---- end RdbStore_DoubleWrite_Huge_DB_009 ----");
1668 }
1669
1670 /*
1671 * @tc.name: RdbStore_Mock_Binlog_001
1672 * @tc.desc: test call backup and restore when binlog is supported
1673 * @tc.type: FUNC
1674 */
1675 HWTEST_F(RdbDoubleWriteTest, RdbStore_Mock_Binlog_001, TestSize.Level0)
1676 {
1677 if (!IsUsingArkData()) {
1678 GTEST_SKIP() << "Current testcase is not compatible from current rdb";
1679 }
1680 mockExtraApi.is_support_binlog = MockSupportBinlog;
1681 sqlite3_export_extra_symbols = &mockExtraApi;
1682 #ifndef CROSS_PLATFORM
1683 mockKvApi.is_support_binlog = MockSupportBinlogWithParam;
1684 sqlite3_export_relational_symbols = &mockKvApi;
1685 #endif
1686
1687 InitDb(HAMode::MANUAL_TRIGGER, false);
1688 EXPECT_EQ(store->Backup(std::string(""), {}), E_OK);
1689 EXPECT_EQ(store->Restore(std::string(""), {}), E_OK);
1690 }
1691
1692 /*
1693 * @tc.name: RdbStore_Mock_Binlog_002
1694 * @tc.desc: test call CheckReplicaIntegrity when binlog is supported
1695 * @tc.type: FUNC
1696 */
1697 HWTEST_F(RdbDoubleWriteTest, RdbStore_Mock_Binlog_002, TestSize.Level0)
1698 {
1699 if (!IsUsingArkData()) {
1700 GTEST_SKIP() << "Current testcase is not compatible from current rdb";
1701 }
1702 mockExtraApi.is_support_binlog = MockSupportBinlog;
1703 sqlite3_export_extra_symbols = &mockExtraApi;
1704 #ifndef CROSS_PLATFORM
1705 mockKvApi.is_support_binlog = MockSupportBinlogWithParam;
1706 sqlite3_export_relational_symbols = &mockKvApi;
1707 #endif
1708 InitDb(HAMode::MAIN_REPLICA, false);
1709 store = nullptr;
1710
1711 // open slave for conflict by compress
1712 sqlite3 *db = nullptr;
1713 int rc = sqlite3_open_v2(RdbDoubleWriteTest::SLAVE_DATABASE_NAME.c_str(),
1714 &db, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, "compressvfs");
1715 EXPECT_EQ(rc, SQLITE_OK);
1716 EXPECT_NE(db, nullptr);
1717 const char *ddl = DoubleWriteTestOpenCallback::CREATE_TABLE_TEST.c_str();
1718 EXPECT_EQ(sqlite3_exec(db, ddl, nullptr, nullptr, nullptr), SQLITE_OK);
1719 sqlite3_close_v2(db);
1720
1721 RdbStoreConfig config(RdbDoubleWriteTest::DATABASE_NAME);
1722 config.SetHaMode(HAMode::MAIN_REPLICA);
1723 EXPECT_EQ(Connection::CheckReplicaIntegrity(config), E_OK);
1724 }
1725
1726 /**
1727 * @tc.name: CreateReplicaStatement_Test_001
1728 * @tc.desc: Normal testCase of CreateReplicaStatement.
1729 * @tc.type: FUNC
1730 */
1731 HWTEST_F(RdbDoubleWriteTest, CreateReplicaStatement_Test_001, TestSize.Level2)
1732 {
1733 InitDb();
1734
1735 RdbStoreConfig config(RdbDoubleWriteTest::DATABASE_NAME);
1736 config.SetHaMode(HAMode::MAIN_REPLICA);
1737 auto [errCode, readConn] = SqliteConnection::Create(config, false);
1738 EXPECT_EQ(errCode, SQLITE_OK);
1739 ASSERT_NE(readConn, nullptr);
1740 auto [err, statement] = readConn->CreateReplicaStatement("select * from test;", readConn);
1741 EXPECT_EQ(err, SQLITE_OK);
1742 EXPECT_NE(statement, nullptr);
1743 statement = nullptr;
1744 readConn = nullptr;
1745 }
1746
1747 /**
1748 * @tc.name: CreateReplicaStatement_Test_002
1749 * @tc.desc: Abnormal testCase of CreateReplicaStatement.
1750 * @tc.type: FUNC
1751 */
1752 HWTEST_F(RdbDoubleWriteTest, CreateReplicaStatement_Test_002, TestSize.Level2)
1753 {
1754 InitDb();
1755 SqliteUtils::DeleteFile(RdbDoubleWriteTest::SLAVE_DATABASE_NAME);
1756
1757 RdbStoreConfig config(RdbDoubleWriteTest::DATABASE_NAME);
1758 config.SetHaMode(HAMode::MAIN_REPLICA);
1759 auto [errCode, readConn] = SqliteConnection::Create(config, false);
1760 EXPECT_EQ(errCode, SQLITE_OK);
1761 ASSERT_NE(readConn, nullptr);
1762 auto [err, statement] = readConn->CreateReplicaStatement("select * from test;", readConn);
1763 EXPECT_EQ(err, SQLITE_OK);
1764 EXPECT_NE(statement, nullptr);
1765 statement = nullptr;
1766 readConn = nullptr;
1767 }
1768
1769 /**
1770 * @tc.name: CreateReplicaStatement_Test_003
1771 * @tc.desc: Abnormal testCase of CreateReplicaStatement.
1772 * @tc.type: FUNC
1773 */
1774 HWTEST_F(RdbDoubleWriteTest, CreateReplicaStatement_Test_003, TestSize.Level2)
1775 {
1776 InitDb();
1777 EXPECT_TRUE(SqliteUtils::CopyFile(SLAVE_DATABASE_NAME + "-dwr", SLAVE_DATABASE_NAME));
1778
1779 RdbStoreConfig config(RdbDoubleWriteTest::DATABASE_NAME);
1780 config.SetHaMode(HAMode::MANUAL_TRIGGER);
1781 auto [errCode, readConn] = SqliteConnection::Create(config, false);
1782 EXPECT_EQ(errCode, SQLITE_OK);
1783 ASSERT_NE(readConn, nullptr);
1784 auto [err, statement] = readConn->CreateReplicaStatement("select * from test;", readConn);
1785 EXPECT_EQ(err, SQLITE_OK);
1786 EXPECT_NE(statement, nullptr);
1787 }
1788