• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #include <chrono>
17 #include <functional>
18 #include <gtest/gtest.h>
19 #include <thread>
20 
21 #include "db_common.h"
22 #include "db_constant.h"
23 #include "distributeddb_tools_unit_test.h"
24 
25 using namespace testing::ext;
26 using namespace DistributedDB;
27 using namespace DistributedDBUnitTest;
28 
29 namespace {
30     const std::string APP_NAME = "app";
31     const std::string USER_NAME = "account0";
32     const int PASSWD_SIZE = 20;
33     const int WAIT_CALLBACK_TIME = 100;
34     KvStoreDelegateManager g_mgr(APP_NAME, USER_NAME);
35     string g_testDir;
36     KvStoreConfig g_config;
37 
38 #ifndef OMIT_MULTI_VER
39     DBStatus g_kvDelegateStatus = INVALID_ARGS;
40     KvStoreDelegate *g_kvDelegatePtr = nullptr;
41     auto g_kvDelegateCallback = std::bind(&DistributedDBToolsUnitTest::KvStoreDelegateCallback, std::placeholders::_1,
42         std::placeholders::_2, std::ref(g_kvDelegateStatus), std::ref(g_kvDelegatePtr));
43 #endif // OMIT_MULTI_VER
44 
45     DBStatus g_kvNbDelegateStatus = INVALID_ARGS;
46     KvStoreNbDelegate *g_kvNbDelegatePtr = nullptr;
47     auto g_kvNbDelegateCallback = std::bind(&DistributedDBToolsUnitTest::KvStoreNbDelegateCallback,
48         std::placeholders::_1, std::placeholders::_2, std::ref(g_kvNbDelegateStatus), std::ref(g_kvNbDelegatePtr));
49 
GetKvStoreDirectory(const std::string & storeId,int databaseType)50     std::string GetKvStoreDirectory(const std::string &storeId, int databaseType)
51     {
52         std::string identifier = USER_NAME + "-" + APP_NAME + "-" + storeId;
53         std::string hashIdentifierName = DBCommon::TransferHashString(identifier);
54         std::string identifierName = DBCommon::TransferStringToHex(hashIdentifierName);
55         std::string filePath = g_testDir + "/" + identifierName + "/";
56         if (databaseType == DBConstant::DB_TYPE_LOCAL) { // local
57             filePath += (std::string(DBConstant::LOCAL_SUB_DIR) + "/" + DBConstant::LOCAL_DATABASE_NAME +
58                 DBConstant::DB_EXTENSION);
59         } else if (databaseType == DBConstant::DB_TYPE_SINGLE_VER) { // single ver
60             filePath += (std::string(DBConstant::SINGLE_SUB_DIR) + "/" + DBConstant::MAINDB_DIR + "/" +
61                 DBConstant::SINGLE_VER_DATA_STORE + DBConstant::DB_EXTENSION);
62         } else if (databaseType == DBConstant::DB_TYPE_MULTI_VER) { // multi ver
63             filePath += (std::string(DBConstant::MULTI_SUB_DIR) + "/" + DBConstant::MULTI_VER_DATA_STORE +
64                 DBConstant::DB_EXTENSION);
65         } else {
66             filePath = "";
67         }
68 
69         return filePath;
70     }
71 
PutDataIntoDatabaseSingleVer(KvStoreNbDelegate * kvNbDelegate)72     int PutDataIntoDatabaseSingleVer(KvStoreNbDelegate *kvNbDelegate)
73     {
74         if (kvNbDelegate == nullptr) {
75             return DBStatus::DB_ERROR;
76         }
77         Key key;
78         Value value;
79         DistributedDBToolsUnitTest::GetRandomKeyValue(key);
80         DistributedDBToolsUnitTest::GetRandomKeyValue(value);
81         return kvNbDelegate->Put(key, value);
82     }
83 #ifndef OMIT_MULTI_VER
PutDataIntoDatabaseMultiVer(KvStoreDelegate * kvDelegate)84     int PutDataIntoDatabaseMultiVer(KvStoreDelegate *kvDelegate)
85     {
86         if (kvDelegate == nullptr) {
87             return DBStatus::DB_ERROR;
88         }
89         Key key;
90         Value value;
91         DistributedDBToolsUnitTest::GetRandomKeyValue(key);
92         DistributedDBToolsUnitTest::GetRandomKeyValue(value);
93         return kvDelegate->Put(key, value);
94     }
95 #endif // OMIT_MULTI_VER
96 }
97 
98 class DistributedDBInterfacesDatabaseCorruptTest : public testing::Test {
99 public:
100     static void SetUpTestCase(void);
101     static void TearDownTestCase(void);
102     void SetUp();
103     void TearDown();
104 };
105 
SetUpTestCase(void)106 void DistributedDBInterfacesDatabaseCorruptTest::SetUpTestCase(void)
107 {
108     DistributedDBToolsUnitTest::TestDirInit(g_testDir);
109     g_config.dataDir = g_testDir;
110     g_mgr.SetKvStoreConfig(g_config);
111 }
112 
TearDownTestCase(void)113 void DistributedDBInterfacesDatabaseCorruptTest::TearDownTestCase(void)
114 {
115     if (DistributedDBToolsUnitTest::RemoveTestDbFiles(g_testDir) != 0) {
116         LOGE("rm test db files error!");
117     }
118 }
119 
SetUp(void)120 void DistributedDBInterfacesDatabaseCorruptTest::SetUp(void)
121 {
122 #ifndef OMIT_MULTI_VER
123     DistributedDBToolsUnitTest::PrintTestCaseInfo();
124     g_kvDelegateStatus = INVALID_ARGS;
125     g_kvDelegatePtr = nullptr;
126 #endif // OMIT_MULTI_VER
127 }
128 
TearDown(void)129 void DistributedDBInterfacesDatabaseCorruptTest::TearDown(void)
130 {
131     g_mgr.SetKvStoreCorruptionHandler(nullptr);
132 }
133 
134 #ifndef OMIT_MULTI_VER
135 /**
136   * @tc.name: DatabaseCorruptionHandleTest001
137   * @tc.desc: Check the corruption detect without setting the corrupt handler.
138   * @tc.type: FUNC
139   * @tc.require:
140   * @tc.author: wangbingquan
141   */
142 HWTEST_F(DistributedDBInterfacesDatabaseCorruptTest, DatabaseCorruptionHandleTest001, TestSize.Level3)
143 {
144     /**
145      * @tc.steps: step1. Obtain the kvStore.
146      * @tc.steps: step2. Put one data into the store.
147      * @tc.steps: step3. Close the store.
148      */
149     CipherPassword passwd;
150     Key randomPassword;
151     DistributedDBToolsUnitTest::GetRandomKeyValue(randomPassword, PASSWD_SIZE);
152     int errCode = passwd.SetValue(randomPassword.data(), randomPassword.size());
153     ASSERT_EQ(errCode, CipherPassword::ErrorCode::OK);
154     KvStoreDelegate::Option option = {true, true, false, CipherType::DEFAULT, passwd};
155     g_mgr.GetKvStore("corrupt1", option, g_kvDelegateCallback);
156     ASSERT_TRUE(g_kvDelegatePtr != nullptr);
157     EXPECT_TRUE(g_kvDelegateStatus == OK);
158     ASSERT_EQ(PutDataIntoDatabaseMultiVer(g_kvDelegatePtr), OK);
159     EXPECT_EQ(g_mgr.CloseKvStore(g_kvDelegatePtr), OK);
160     g_kvDelegatePtr = nullptr;
161 
162     /**
163      * @tc.steps: step4. Modify the database file.
164      */
165     std::string filePath = GetKvStoreDirectory("corrupt1", DBConstant::DB_TYPE_LOCAL); // local database.
166     DistributedDBToolsUnitTest::ModifyDatabaseFile(filePath);
167 
168     /**
169      * @tc.steps: step5. Re-obtain the kvStore.
170      * @tc.expected: step5. Returns null kvstore.
171      */
172     g_mgr.GetKvStore("corrupt1", option, g_kvDelegateCallback);
173     ASSERT_TRUE(g_kvDelegatePtr == nullptr);
174     EXPECT_TRUE(g_kvDelegateStatus == INVALID_PASSWD_OR_CORRUPTED_DB);
175     g_mgr.DeleteKvStore("corrupt1");
176 }
177 #endif // OMIT_MULTI_VER
178 
179 /**
180   * @tc.name: DatabaseCorruptionHandleTest002
181   * @tc.desc: Get kv store through different parameters for the same storeID.
182   * @tc.type: FUNC
183   * @tc.require:
184   * @tc.author: wangbingquan
185   */
186 HWTEST_F(DistributedDBInterfacesDatabaseCorruptTest, DatabaseCorruptionHandleTest002, TestSize.Level1)
187 {
188     /**
189      * @tc.steps: step1. Get the kvStore.
190      * @tc.steps: step2. Put data into the store.
191      * @tc.steps: step3. Close the store.
192      */
193     CipherPassword passwd;
194     Key randomPassword;
195     DistributedDBToolsUnitTest::GetRandomKeyValue(randomPassword, PASSWD_SIZE);
196     int errCode = passwd.SetValue(randomPassword.data(), randomPassword.size());
197     ASSERT_EQ(errCode, CipherPassword::ErrorCode::OK);
198 #ifndef OMIT_MULTI_VER
199     KvStoreDelegate::Option option = {true, false, false, CipherType::DEFAULT, passwd};
200     g_mgr.GetKvStore("corrupt2", option, g_kvDelegateCallback);
201     ASSERT_TRUE(g_kvDelegatePtr != nullptr);
202     ASSERT_EQ(PutDataIntoDatabaseMultiVer(g_kvDelegatePtr), OK);
203     EXPECT_EQ(g_mgr.CloseKvStore(g_kvDelegatePtr), OK);
204     g_kvDelegatePtr = nullptr;
205 #endif // OMIT_MULTI_VER
206 
207     KvStoreNbDelegate::Option nbOption = {true, false, false, CipherType::DEFAULT, passwd};
208     g_mgr.GetKvStore("corrupt3", nbOption, g_kvNbDelegateCallback);
209     ASSERT_TRUE(g_kvNbDelegatePtr != nullptr);
210     ASSERT_EQ(PutDataIntoDatabaseSingleVer(g_kvNbDelegatePtr), OK);
211     EXPECT_EQ(g_mgr.CloseKvStore(g_kvNbDelegatePtr), OK);
212     g_kvNbDelegatePtr = nullptr;
213 
214     /**
215      * @tc.steps: step4. Modify the database file.
216      */
217     std::string filePath;
218 #ifndef OMIT_MULTI_VER
219     filePath = GetKvStoreDirectory("corrupt2", DBConstant::DB_TYPE_MULTI_VER);
220     DistributedDBToolsUnitTest::ModifyDatabaseFile(filePath);
221 #endif // OMIT_MULTI_VER
222     filePath = GetKvStoreDirectory("corrupt3", DBConstant::DB_TYPE_SINGLE_VER); // single ver database.
223     DistributedDBToolsUnitTest::ModifyDatabaseFile(filePath);
224     KvStoreCorruptInfo corruptInfo;
225     auto notifier = bind(&KvStoreCorruptInfo::CorruptCallBack, &corruptInfo, std::placeholders::_1,
226         std::placeholders::_2, std::placeholders::_3);
227     g_mgr.SetKvStoreCorruptionHandler(notifier);
228     std::this_thread::sleep_for(std::chrono::milliseconds(WAIT_CALLBACK_TIME));
229     /**
230      * @tc.steps: step5. Re-obtain the kvStore.
231      * @tc.expected: step5. Returns null kvstore.
232      */
233     size_t infoSize = 0;
234 #ifndef OMIT_MULTI_VER
235     g_mgr.GetKvStore("corrupt2", option, g_kvDelegateCallback);
236     ASSERT_TRUE(g_kvDelegateStatus != OK);
237     EXPECT_EQ(corruptInfo.IsDataBaseCorrupted(APP_NAME, USER_NAME, "corrupt2"), true);
238     g_mgr.DeleteKvStore("corrupt2");
239     infoSize++;
240 #endif // OMIT_MULTI_VER
241 
242     g_mgr.GetKvStore("corrupt3", nbOption, g_kvNbDelegateCallback);
243     ASSERT_TRUE(g_kvNbDelegateStatus != OK);
244     infoSize++;
245     std::this_thread::sleep_for(std::chrono::milliseconds(WAIT_CALLBACK_TIME));
246     EXPECT_EQ(corruptInfo.GetDatabaseInfoSize(), infoSize); // 2 callback
247     EXPECT_EQ(corruptInfo.IsDataBaseCorrupted(APP_NAME, USER_NAME, "corrupt3"), true);
248     g_mgr.DeleteKvStore("corrupt3");
249 }
250 
251 /**
252   * @tc.name: DatabaseCorruptionHandleTest003
253   * @tc.desc: Test the CloseKvStore Interface and check whether the database file can be closed.
254   * @tc.type: FUNC
255   * @tc.require:
256   * @tc.author: wangbingquan
257   */
258 HWTEST_F(DistributedDBInterfacesDatabaseCorruptTest, DatabaseCorruptionHandleTest003, TestSize.Level1)
259 {
260     /**
261      * @tc.steps: step1. Get the kvStore.
262      * @tc.steps: step2. Put data into the store.
263      * @tc.steps: step3. Close the store.
264      */
265     CipherPassword passwd;
266     Key randomPassword;
267     DistributedDBToolsUnitTest::GetRandomKeyValue(randomPassword, PASSWD_SIZE);
268     int errCode = passwd.SetValue(randomPassword.data(), randomPassword.size());
269     ASSERT_EQ(errCode, CipherPassword::ErrorCode::OK);
270 #ifndef OMIT_MULTI_VER
271     KvStoreDelegate::Option option = {true, true, false, CipherType::DEFAULT, passwd};
272     g_mgr.GetKvStore("corrupt4", option, g_kvDelegateCallback);
273     ASSERT_TRUE(g_kvDelegatePtr != nullptr);
274     ASSERT_EQ(PutDataIntoDatabaseMultiVer(g_kvDelegatePtr), OK);
275 #endif // OMIT_MULTI_VER
276     KvStoreNbDelegate::Option nbOption = {true, false, false, CipherType::DEFAULT, passwd};
277     g_mgr.GetKvStore("corrupt5", nbOption, g_kvNbDelegateCallback);
278     ASSERT_TRUE(g_kvNbDelegatePtr != nullptr);
279     ASSERT_EQ(PutDataIntoDatabaseSingleVer(g_kvNbDelegatePtr), OK);
280     EXPECT_EQ(g_mgr.CloseKvStore(g_kvNbDelegatePtr), OK);
281     g_kvNbDelegatePtr = nullptr;
282 
283     /**
284      * @tc.steps: step4. Modify the database file.
285      */
286     std::string  filePath;
287 #ifndef OMIT_MULTI_VER
288     filePath = GetKvStoreDirectory("corrupt4", DBConstant::DB_TYPE_LOCAL); // local database.
289     DistributedDBToolsUnitTest::ModifyDatabaseFile(filePath);
290 #endif // OMIT_MULTI_VER
291     DistributedDBToolsUnitTest::ModifyDatabaseFile(filePath + "-wal");
292     filePath = GetKvStoreDirectory("corrupt5", DBConstant::DB_TYPE_SINGLE_VER); // single ver database.
293     DistributedDBToolsUnitTest::ModifyDatabaseFile(filePath);
294     DistributedDBToolsUnitTest::ModifyDatabaseFile(filePath + "-wal");
295     KvStoreCorruptInfo corruptInfo;
296     auto notifier = bind(&KvStoreCorruptInfo::CorruptCallBack, &corruptInfo, std::placeholders::_1,
297         std::placeholders::_2, std::placeholders::_3);
298     g_mgr.SetKvStoreCorruptionHandler(notifier);
299 
300     /**
301      * @tc.steps: step5. Put data into the kvStore.
302      * @tc.expected: step5. The corrupt handler is called twice.
303      */
304     size_t infoSize = 0;
305 #ifndef OMIT_MULTI_VER
306     ASSERT_NE(PutDataIntoDatabaseMultiVer(g_kvDelegatePtr), OK);
307     std::this_thread::sleep_for(std::chrono::milliseconds(WAIT_CALLBACK_TIME));
308     EXPECT_EQ(corruptInfo.IsDataBaseCorrupted(APP_NAME, USER_NAME, "corrupt4"), true);
309     EXPECT_EQ(g_mgr.CloseKvStore(g_kvDelegatePtr), OK);
310     g_kvDelegatePtr = nullptr;
311     EXPECT_EQ(g_mgr.DeleteKvStore("corrupt4"), OK);
312     infoSize++;
313 #endif // OMIT_MULTI_VER
314     g_mgr.GetKvStore("corrupt5", nbOption, g_kvNbDelegateCallback);
315     ASSERT_TRUE(g_kvNbDelegatePtr == nullptr);
316     ASSERT_NE(PutDataIntoDatabaseSingleVer(g_kvNbDelegatePtr), OK);
317     infoSize++;
318     std::this_thread::sleep_for(std::chrono::milliseconds(WAIT_CALLBACK_TIME));
319     EXPECT_TRUE(corruptInfo.GetDatabaseInfoSize() >= infoSize); // 2 more callback
320     EXPECT_EQ(corruptInfo.IsDataBaseCorrupted(APP_NAME, USER_NAME, "corrupt5"), true);
321     EXPECT_EQ(g_mgr.DeleteKvStore("corrupt5"), OK);
322 }
323 
324 /**
325   * @tc.name: DatabaseCorruptionHandleTest004
326   * @tc.desc: Test the DeleteKvStore Interface and check whether the database files can be removed.
327   * @tc.type: FUNC
328   * @tc.require:
329   * @tc.author: wangbingquan
330   */
331 HWTEST_F(DistributedDBInterfacesDatabaseCorruptTest, DatabaseCorruptionHandleTest004, TestSize.Level1)
332 {
333     /**
334      * @tc.steps: step1. Get the kvStore.
335      * @tc.steps: step2. Put data into the store.
336      * @tc.steps: step3. Close the store.
337      */
338     CipherPassword passwd;
339     Key randomPassword;
340     DistributedDBToolsUnitTest::GetRandomKeyValue(randomPassword, PASSWD_SIZE);
341     int errCode = passwd.SetValue(randomPassword.data(), randomPassword.size());
342     ASSERT_EQ(errCode, CipherPassword::ErrorCode::OK);
343 
344     KvStoreNbDelegate::Option nbOption = {true, false, false, CipherType::DEFAULT, passwd};
345     g_mgr.GetKvStore("corrupt7", nbOption, g_kvNbDelegateCallback);
346     ASSERT_TRUE(g_kvNbDelegatePtr != nullptr);
347     ASSERT_EQ(PutDataIntoDatabaseSingleVer(g_kvNbDelegatePtr), OK);
348     EXPECT_EQ(g_mgr.CloseKvStore(g_kvNbDelegatePtr), OK);
349     g_kvNbDelegatePtr = nullptr;
350 
351     /**
352      * @tc.steps: step4. Modify the database file.
353      */
354     std::string filePath;
355     DistributedDBToolsUnitTest::ModifyDatabaseFile(filePath + "-wal");
356     filePath = GetKvStoreDirectory("corrupt7", DBConstant::DB_TYPE_SINGLE_VER); // single ver database.
357     DistributedDBToolsUnitTest::ModifyDatabaseFile(filePath);
358     DistributedDBToolsUnitTest::ModifyDatabaseFile(filePath + "-wal");
359     KvStoreCorruptInfo corruptInfo;
360     KvStoreCorruptInfo corruptInfoNew;
361     auto notifier = bind(&KvStoreCorruptInfo::CorruptCallBack, &corruptInfo, std::placeholders::_1,
362         std::placeholders::_2, std::placeholders::_3);
363     g_mgr.SetKvStoreCorruptionHandler(notifier);
364     auto notifierNew = bind(&KvStoreCorruptInfo::CorruptCallBack, &corruptInfoNew, std::placeholders::_1,
365         std::placeholders::_2, std::placeholders::_3);
366     g_mgr.SetKvStoreCorruptionHandler(notifierNew);
367     /**
368      * @tc.steps: step5. Re-obtain the kvStore.
369      * @tc.expected: step5. Returns null kvstore.
370      */
371     g_mgr.GetKvStore("corrupt7", nbOption, g_kvNbDelegateCallback);
372     ASSERT_TRUE(g_kvNbDelegatePtr == nullptr);
373     size_t infoSize = 0;
374     ASSERT_NE(PutDataIntoDatabaseSingleVer(g_kvNbDelegatePtr), OK);
375     infoSize++;
376     std::this_thread::sleep_for(std::chrono::milliseconds(WAIT_CALLBACK_TIME));
377     EXPECT_EQ(corruptInfo.GetDatabaseInfoSize(), 0UL); // no callback
378     EXPECT_TRUE(corruptInfoNew.GetDatabaseInfoSize() >= infoSize); // 2 more callback
379     EXPECT_EQ(corruptInfoNew.IsDataBaseCorrupted(APP_NAME, USER_NAME, "corrupt7"), true);
380     EXPECT_EQ(g_mgr.DeleteKvStore("corrupt7"), OK);
381 }
382 
383 #ifndef OMIT_MULTI_VER
384 /**
385   * @tc.name: DatabaseCorruptionHandleTest005
386   * @tc.desc: Test the DeleteKvStore Interface and check whether the database files can be removed.
387   * @tc.type: FUNC
388   * @tc.require:
389   * @tc.author: wangbingquan
390   */
391 HWTEST_F(DistributedDBInterfacesDatabaseCorruptTest, DatabaseCorruptionHandleTest005, TestSize.Level1)
392 {
393     /**
394      * @tc.steps: step1. Get the kvStore.
395      * @tc.steps: step2. Put data into the store.
396      * @tc.steps: step3. Close the store.
397      */
398     CipherPassword passwd;
399     Key randomPassword;
400     DistributedDBToolsUnitTest::GetRandomKeyValue(randomPassword, PASSWD_SIZE);
401     int errCode = passwd.SetValue(randomPassword.data(), randomPassword.size());
402     ASSERT_EQ(errCode, CipherPassword::ErrorCode::OK);
403     KvStoreDelegate::Option option = {true, true, false, CipherType::DEFAULT, passwd};
404     g_mgr.GetKvStore("corrupt6", option, g_kvDelegateCallback);
405     ASSERT_TRUE(g_kvDelegatePtr != nullptr);
406     ASSERT_EQ(PutDataIntoDatabaseMultiVer(g_kvDelegatePtr), OK);
407     ASSERT_EQ(PutDataIntoDatabaseMultiVer(g_kvDelegatePtr), OK);
408 
409     /**
410      * @tc.steps: step4. Modify the database file.
411      */
412     std::string filePath = GetKvStoreDirectory("corrupt6", DBConstant::DB_TYPE_LOCAL); // local database.
413     DistributedDBToolsUnitTest::ModifyDatabaseFile(filePath);
414     DistributedDBToolsUnitTest::ModifyDatabaseFile(filePath + "-wal");
415     filePath = GetKvStoreDirectory("corrupt7", DBConstant::DB_TYPE_SINGLE_VER); // single ver database.
416     DistributedDBToolsUnitTest::ModifyDatabaseFile(filePath);
417     DistributedDBToolsUnitTest::ModifyDatabaseFile(filePath + "-wal");
418     KvStoreCorruptInfo corruptInfo;
419     KvStoreCorruptInfo corruptInfoNew;
420     auto notifier = bind(&KvStoreCorruptInfo::CorruptCallBack, &corruptInfo, std::placeholders::_1,
421                          std::placeholders::_2, std::placeholders::_3);
422     g_mgr.SetKvStoreCorruptionHandler(notifier);
423     auto notifierNew = bind(&KvStoreCorruptInfo::CorruptCallBack, &corruptInfoNew, std::placeholders::_1,
424                             std::placeholders::_2, std::placeholders::_3);
425     g_mgr.SetKvStoreCorruptionHandler(notifierNew);
426     /**
427      * @tc.steps: step5. Re-obtain the kvStore.
428      * @tc.expected: step5. Returns null kvstore.
429      */
430     size_t infoSize = 0;
431     ASSERT_NE(PutDataIntoDatabaseMultiVer(g_kvDelegatePtr), OK);
432     std::this_thread::sleep_for(std::chrono::milliseconds(WAIT_CALLBACK_TIME));
433     EXPECT_EQ(corruptInfoNew.IsDataBaseCorrupted(APP_NAME, USER_NAME, "corrupt6"), true);
434     EXPECT_EQ(g_mgr.CloseKvStore(g_kvDelegatePtr), OK);
435     g_kvDelegatePtr = nullptr;
436     EXPECT_EQ(g_mgr.DeleteKvStore("corrupt6"), OK);
437     infoSize++;
438 
439     std::this_thread::sleep_for(std::chrono::milliseconds(WAIT_CALLBACK_TIME));
440     EXPECT_EQ(corruptInfo.GetDatabaseInfoSize(), 0UL); // no callback
441     EXPECT_TRUE(corruptInfoNew.GetDatabaseInfoSize() >= infoSize); // 2 more callback
442 }
443 #endif // OMIT_MULTI_VER
444 
445 namespace {
446 const uint32_t MODIFY_SIZE = 12; // Modify size is 12 * sizeof(uint32_t);
447 const uint32_t MODIFY_VALUE = 0xF3F3F3F3; // random value, make sure to destroy the page header.
TestDatabaseIntegrityCheckOption(const std::string & storeId,bool isEncrypted)448 void TestDatabaseIntegrityCheckOption(const std::string &storeId, bool isEncrypted)
449 {
450     KvStoreNbDelegate::Option nbOption = {true, false, isEncrypted};
451     nbOption.isNeedIntegrityCheck = false;
452     nbOption.isNeedRmCorruptedDb = false;
453     if (isEncrypted) {
454         Key randPassword;
455         DistributedDBToolsUnitTest::GetRandomKeyValue(randPassword, PASSWD_SIZE);
456         ASSERT_EQ(nbOption.passwd.SetValue(randPassword.data(), randPassword.size()), CipherPassword::ErrorCode::OK);
457     }
458     auto filePath = GetKvStoreDirectory(storeId, DBConstant::DB_TYPE_SINGLE_VER);
459     g_mgr.GetKvStore(storeId, nbOption, g_kvNbDelegateCallback);
460     ASSERT_EQ(g_kvNbDelegateStatus, OK);
461     ASSERT_TRUE(g_kvNbDelegatePtr != nullptr);
462     ASSERT_EQ(PutDataIntoDatabaseSingleVer(g_kvNbDelegatePtr), OK);
463     EXPECT_EQ(g_mgr.CloseKvStore(g_kvNbDelegatePtr), OK);
464 
465     /**
466      * @tc.steps: step1. Modify the database file header to destroy the header and call the GetKvStore.
467      * @tc.expected: step1. Returns null kv store and the errCode is INVALID_PASSWD_OR_CORRUPTED_DB.
468      */
469     DistributedDBToolsUnitTest::ModifyDatabaseFile(filePath, 0, MODIFY_SIZE, MODIFY_VALUE);
470     g_mgr.GetKvStore(storeId, nbOption, g_kvNbDelegateCallback);
471     ASSERT_EQ(g_kvNbDelegateStatus, INVALID_PASSWD_OR_CORRUPTED_DB);
472     ASSERT_TRUE(g_kvNbDelegatePtr == nullptr);
473 
474     /**
475      * @tc.steps: step2. call the GetKvStore with integrity check option is true.
476      * @tc.expected: step2. Returns null kv store and the errCode is INVALID_PASSWD_OR_CORRUPTED_DB.
477      */
478     nbOption.isNeedIntegrityCheck = true;
479     g_mgr.GetKvStore(storeId, nbOption, g_kvNbDelegateCallback);
480     ASSERT_EQ(g_kvNbDelegateStatus, INVALID_PASSWD_OR_CORRUPTED_DB);
481     ASSERT_TRUE(g_kvNbDelegatePtr == nullptr);
482 
483     /**
484      * @tc.steps: step3. call the GetKvStore with remove corrupted database option is true.
485      * @tc.expected: step3. Returns non-null kv store and the errCode is OK.
486      */
487     nbOption.isNeedIntegrityCheck = false;
488     nbOption.isNeedRmCorruptedDb = true;
489     g_mgr.GetKvStore(storeId, nbOption, g_kvNbDelegateCallback);
490     ASSERT_TRUE(g_kvNbDelegatePtr != nullptr);
491 
492     ASSERT_EQ(PutDataIntoDatabaseSingleVer(g_kvNbDelegatePtr), OK);
493     EXPECT_EQ(g_mgr.CloseKvStore(g_kvNbDelegatePtr), OK);
494 
495     /**
496      * @tc.steps: step4. Modify the second page of the database file and Get the kv store.
497      * @tc.expected: step4. Returns non-null kv store and the errCode is OK(GetKvStore skip the check of the page 2).
498      */
499     size_t filePos = isEncrypted ? 1024 : 4096; // 1024 and 4096 is the page size.
500     DistributedDBToolsUnitTest::ModifyDatabaseFile(filePath, filePos, MODIFY_SIZE, MODIFY_VALUE);
501     nbOption.isNeedRmCorruptedDb = false;
502     g_mgr.GetKvStore(storeId, nbOption, g_kvNbDelegateCallback);
503     ASSERT_TRUE(g_kvNbDelegatePtr != nullptr);
504     EXPECT_EQ(g_mgr.CloseKvStore(g_kvNbDelegatePtr), OK);
505 
506     /**
507      * @tc.steps: step5. Get the kv store with check the integrity.
508      * @tc.expected: step5. Returns null kv store and the errCode is INVALID_PASSWD_OR_CORRUPTED_DB.
509      */
510     nbOption.isNeedIntegrityCheck = true;
511     g_mgr.GetKvStore(storeId, nbOption, g_kvNbDelegateCallback);
512     ASSERT_EQ(g_kvNbDelegateStatus, INVALID_PASSWD_OR_CORRUPTED_DB);
513     ASSERT_TRUE(g_kvNbDelegatePtr == nullptr);
514 
515     /**
516      * @tc.steps: step5. Get the kv store with check the integrity and the rm corrupted database option.
517      * @tc.expected: step5. Returns non-null kv store and the errCode is OK.
518      */
519     nbOption.isNeedRmCorruptedDb = true;
520     g_mgr.GetKvStore(storeId, nbOption, g_kvNbDelegateCallback);
521     ASSERT_TRUE(g_kvNbDelegatePtr != nullptr);
522     EXPECT_EQ(g_mgr.CloseKvStore(g_kvNbDelegatePtr), OK);
523     EXPECT_EQ(g_mgr.DeleteKvStore(storeId), OK);
524 }
525 }
526 
527 /**
528   * @tc.name: DatabaseRebuildTest001
529   * @tc.desc: Test DB rebuild.
530   * @tc.type: FUNC
531   * @tc.require:
532   * @tc.author: liaoyonghuang
533   */
534 HWTEST_F(DistributedDBInterfacesDatabaseCorruptTest, DatabaseRebuildTest001, TestSize.Level0)
535 {
536     /**
537      * @tc.steps: step1. Get the kv store
538      * @tc.expected: step1. Returns OK.
539      */
540     KvStoreNbDelegate::Option nbOption;
541     nbOption.isNeedIntegrityCheck = false;
542     nbOption.isNeedRmCorruptedDb = true;
543     std::string storeId = "DatabaseRebuildTest001";
544     auto filePath = GetKvStoreDirectory(storeId, DBConstant::DB_TYPE_SINGLE_VER);
545     g_mgr.GetKvStore(storeId, nbOption, g_kvNbDelegateCallback);
546     ASSERT_EQ(g_kvNbDelegateStatus, OK);
547     ASSERT_TRUE(g_kvNbDelegatePtr != nullptr);
548     ASSERT_EQ(PutDataIntoDatabaseSingleVer(g_kvNbDelegatePtr), OK);
549     EXPECT_EQ(g_mgr.CloseKvStore(g_kvNbDelegatePtr), OK);
550     /**
551      * @tc.steps: step2. Modify database file and get the kv store
552      * @tc.expected: step2. Check database status OK.
553      */
554     DistributedDBToolsUnitTest::ModifyDatabaseFile(filePath, 0, MODIFY_SIZE, MODIFY_VALUE);
555     g_mgr.GetKvStore(storeId, nbOption, g_kvNbDelegateCallback);
556     ASSERT_EQ(g_kvNbDelegateStatus, OK);
557     ASSERT_TRUE(g_kvNbDelegatePtr != nullptr);
558     KvStoreNbDelegate::DatabaseStatus actualStatus = g_kvNbDelegatePtr->GetDatabaseStatus();
559     EXPECT_EQ(actualStatus.isRebuild, true);
560     EXPECT_EQ(g_mgr.CloseKvStore(g_kvNbDelegatePtr), OK);
561     EXPECT_EQ(g_mgr.DeleteKvStore(storeId), OK);
562 }
563 
564 /**
565   * @tc.name: DatabaseIntegrityCheck001
566   * @tc.desc: Test the integrity check option.
567   * @tc.type: FUNC
568   * @tc.require:
569   * @tc.author: wangbingquan
570   */
571 HWTEST_F(DistributedDBInterfacesDatabaseCorruptTest, DatabaseIntegrityCheck001, TestSize.Level2)
572 {
573     LOGI("Begin to check the unencrypted database");
574     TestDatabaseIntegrityCheckOption("integrity_check001", false);
575     std::this_thread::sleep_for(std::chrono::milliseconds(500));
576     LOGI("Begin to check the encrypted database");
577     TestDatabaseIntegrityCheckOption("integrity_check002", true);
578 }
579 
580 /**
581   * @tc.name: DatabaseIntegrityCheck002
582   * @tc.desc: Test the integrity check interface.
583   * @tc.type: FUNC
584   * @tc.require:
585   * @tc.author: wangbingquan
586   */
587 HWTEST_F(DistributedDBInterfacesDatabaseCorruptTest, DatabaseIntegrityCheck002, TestSize.Level1)
588 {
589     CipherPassword passwd;
590     KvStoreNbDelegate::Option nbOption = {true, false, false, CipherType::DEFAULT, passwd};
591     nbOption.isNeedIntegrityCheck = true;
592     nbOption.isNeedRmCorruptedDb = true;
593     auto filePath = GetKvStoreDirectory("integrity021", DBConstant::DB_TYPE_SINGLE_VER);
594     for (uint32_t i = 1; i < 4; i++) {
595         LOGI("%u th test!", i);
596         g_mgr.GetKvStore("integrity021", nbOption, g_kvNbDelegateCallback);
597         ASSERT_TRUE(g_kvNbDelegatePtr != nullptr);
598         ASSERT_EQ(g_kvNbDelegatePtr->CheckIntegrity(), OK);
599         ASSERT_EQ(PutDataIntoDatabaseSingleVer(g_kvNbDelegatePtr), OK);
600         EXPECT_EQ(g_mgr.CloseKvStore(g_kvNbDelegatePtr), OK);
601         DistributedDBToolsUnitTest::ModifyDatabaseFile(filePath, i * 4096, MODIFY_SIZE, MODIFY_VALUE); // page size 4096
602         g_mgr.GetKvStore("integrity021", nbOption, g_kvNbDelegateCallback);
603         ASSERT_TRUE(g_kvNbDelegatePtr != nullptr);
604         EXPECT_EQ(g_kvNbDelegatePtr->CheckIntegrity(), OK);
605         EXPECT_EQ(g_mgr.CloseKvStore(g_kvNbDelegatePtr), OK);
606         EXPECT_EQ(g_mgr.DeleteKvStore("integrity021"), OK);
607     }
608     LOGI("Begin the encrypted check");
609     Key randomPassword;
610     DistributedDBToolsUnitTest::GetRandomKeyValue(randomPassword, PASSWD_SIZE);
611     int errCode = passwd.SetValue(randomPassword.data(), randomPassword.size());
612     ASSERT_EQ(errCode, CipherPassword::ErrorCode::OK);
613     nbOption = {true, false, true, CipherType::DEFAULT, passwd};
614     nbOption.isNeedIntegrityCheck = true;
615     nbOption.isNeedRmCorruptedDb = true;
616     filePath = GetKvStoreDirectory("integrity022", DBConstant::DB_TYPE_SINGLE_VER);
617     for (uint32_t i = 1; i < 4; i++) {
618         LOGI("%u th test the encrypted database!", i);
619         g_mgr.GetKvStore("integrity022", nbOption, g_kvNbDelegateCallback);
620         ASSERT_TRUE(g_kvNbDelegatePtr != nullptr);
621         ASSERT_EQ(g_kvNbDelegatePtr->CheckIntegrity(), OK);
622         ASSERT_EQ(PutDataIntoDatabaseSingleVer(g_kvNbDelegatePtr), OK);
623         EXPECT_EQ(g_mgr.CloseKvStore(g_kvNbDelegatePtr), OK);
624         DistributedDBToolsUnitTest::ModifyDatabaseFile(filePath, i * 1024, MODIFY_SIZE, MODIFY_VALUE); // page size 1024
625         g_mgr.GetKvStore("integrity022", nbOption, g_kvNbDelegateCallback);
626         ASSERT_TRUE(g_kvNbDelegatePtr != nullptr);
627         EXPECT_EQ(g_kvNbDelegatePtr->CheckIntegrity(), OK);
628         EXPECT_EQ(g_mgr.CloseKvStore(g_kvNbDelegatePtr), OK);
629         EXPECT_EQ(g_mgr.DeleteKvStore("integrity022"), OK);
630     }
631 }