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 DBStatus g_kvDelegateStatus = INVALID_ARGS;
39 DBStatus g_kvNbDelegateStatus = INVALID_ARGS;
40 KvStoreDelegate *g_kvDelegatePtr = nullptr;
41 KvStoreNbDelegate *g_kvNbDelegatePtr = nullptr;
42 auto g_kvDelegateCallback = std::bind(&DistributedDBToolsUnitTest::KvStoreDelegateCallback, std::placeholders::_1,
43 std::placeholders::_2, std::ref(g_kvDelegateStatus), std::ref(g_kvDelegatePtr));
44 auto g_kvNbDelegateCallback = std::bind(&DistributedDBToolsUnitTest::KvStoreNbDelegateCallback,
45 std::placeholders::_1, std::placeholders::_2, std::ref(g_kvNbDelegateStatus), std::ref(g_kvNbDelegatePtr));
46
GetKvStoreDirectory(const std::string & storeId,int databaseType)47 std::string GetKvStoreDirectory(const std::string &storeId, int databaseType)
48 {
49 std::string identifier = USER_NAME + "-" + APP_NAME + "-" + storeId;
50 std::string hashIdentifierName = DBCommon::TransferHashString(identifier);
51 std::string identifierName = DBCommon::TransferStringToHex(hashIdentifierName);
52 std::string filePath = g_testDir + "/" + identifierName + "/";
53 if (databaseType == DBConstant::DB_TYPE_LOCAL) { // local
54 filePath += (DBConstant::LOCAL_SUB_DIR + "/" + DBConstant::LOCAL_DATABASE_NAME +
55 DBConstant::SQLITE_DB_EXTENSION);
56 } else if (databaseType == DBConstant::DB_TYPE_SINGLE_VER) { // single ver
57 filePath += (DBConstant::SINGLE_SUB_DIR + "/" + DBConstant::MAINDB_DIR + "/" +
58 DBConstant::SINGLE_VER_DATA_STORE + DBConstant::SQLITE_DB_EXTENSION);
59 } else if (databaseType == DBConstant::DB_TYPE_MULTI_VER) { // multi ver
60 filePath += (DBConstant::MULTI_SUB_DIR + "/" + DBConstant::MULTI_VER_DATA_STORE +
61 DBConstant::SQLITE_DB_EXTENSION);
62 } else {
63 filePath = "";
64 }
65
66 return filePath;
67 }
68
PutDataIntoDatabase(KvStoreDelegate * kvDelegate,KvStoreNbDelegate * kvNbDelegate)69 int PutDataIntoDatabase(KvStoreDelegate *kvDelegate, KvStoreNbDelegate *kvNbDelegate)
70 {
71 if (kvDelegate == nullptr && kvNbDelegate == nullptr) {
72 return DBStatus::DB_ERROR;
73 }
74 Key key;
75 Value value;
76 DistributedDBToolsUnitTest::GetRandomKeyValue(key);
77 DistributedDBToolsUnitTest::GetRandomKeyValue(value);
78 DBStatus status = OK;
79 if (kvDelegate != nullptr) {
80 status = kvDelegate->Put(key, value);
81 if (status != OK) {
82 return status;
83 }
84 }
85 if (kvNbDelegate != nullptr) {
86 status = kvNbDelegate->Put(key, value);
87 if (status != OK) {
88 return status;
89 }
90 }
91 return status;
92 }
93 }
94
95 class DistributedDBInterfacesDatabaseCorruptTest : public testing::Test {
96 public:
97 static void SetUpTestCase(void);
98 static void TearDownTestCase(void);
99 void SetUp();
100 void TearDown();
101 };
102
SetUpTestCase(void)103 void DistributedDBInterfacesDatabaseCorruptTest::SetUpTestCase(void)
104 {
105 DistributedDBToolsUnitTest::TestDirInit(g_testDir);
106 g_config.dataDir = g_testDir;
107 g_mgr.SetKvStoreConfig(g_config);
108 }
109
TearDownTestCase(void)110 void DistributedDBInterfacesDatabaseCorruptTest::TearDownTestCase(void)
111 {
112 if (DistributedDBToolsUnitTest::RemoveTestDbFiles(g_testDir) != 0) {
113 LOGE("rm test db files error!");
114 }
115 }
116
SetUp(void)117 void DistributedDBInterfacesDatabaseCorruptTest::SetUp(void)
118 {
119 DistributedDBToolsUnitTest::PrintTestCaseInfo();
120 g_kvDelegateStatus = INVALID_ARGS;
121 g_kvDelegatePtr = nullptr;
122 }
123
TearDown(void)124 void DistributedDBInterfacesDatabaseCorruptTest::TearDown(void)
125 {
126 g_mgr.SetKvStoreCorruptionHandler(nullptr);
127 }
128
129 /**
130 * @tc.name: DatabaseCorruptionHandleTest001
131 * @tc.desc: Check the corruption detect without setting the corrupt handler.
132 * @tc.type: FUNC
133 * @tc.require: AR000D487C SR000D4878
134 * @tc.author: wangbingquan
135 */
136 HWTEST_F(DistributedDBInterfacesDatabaseCorruptTest, DatabaseCorruptionHandleTest001, TestSize.Level3)
137 {
138 /**
139 * @tc.steps: step1. Obtain the kvStore.
140 * @tc.steps: step2. Put one data into the store.
141 * @tc.steps: step3. Close the store.
142 */
143 CipherPassword passwd;
144 Key randomPassword;
145 DistributedDBToolsUnitTest::GetRandomKeyValue(randomPassword, PASSWD_SIZE);
146 int errCode = passwd.SetValue(randomPassword.data(), randomPassword.size());
147 ASSERT_EQ(errCode, CipherPassword::ErrorCode::OK);
148 KvStoreDelegate::Option option = {true, true, false, CipherType::DEFAULT, passwd};
149 g_mgr.GetKvStore("corrupt1", option, g_kvDelegateCallback);
150 ASSERT_TRUE(g_kvDelegatePtr != nullptr);
151 EXPECT_TRUE(g_kvDelegateStatus == OK);
152 ASSERT_EQ(PutDataIntoDatabase(g_kvDelegatePtr, nullptr), OK);
153 EXPECT_EQ(g_mgr.CloseKvStore(g_kvDelegatePtr), OK);
154 g_kvDelegatePtr = nullptr;
155
156 /**
157 * @tc.steps: step4. Modify the database file.
158 */
159 std::string filePath = GetKvStoreDirectory("corrupt1", DBConstant::DB_TYPE_LOCAL); // local database.
160 DistributedDBToolsUnitTest::ModifyDatabaseFile(filePath);
161
162 /**
163 * @tc.steps: step5. Re-obtain the kvStore.
164 * @tc.expected: step5. Returns null kvstore.
165 */
166 g_mgr.GetKvStore("corrupt1", option, g_kvDelegateCallback);
167 ASSERT_TRUE(g_kvDelegatePtr == nullptr);
168 EXPECT_TRUE(g_kvDelegateStatus == INVALID_PASSWD_OR_CORRUPTED_DB);
169 g_mgr.DeleteKvStore("corrupt1");
170 }
171
172 /**
173 * @tc.name: DatabaseCorruptionHandleTest002
174 * @tc.desc: Get kv store through different parameters for the same storeID.
175 * @tc.type: FUNC
176 * @tc.require: AR000D487C SR000D4878
177 * @tc.author: wangbingquan
178 */
179 HWTEST_F(DistributedDBInterfacesDatabaseCorruptTest, DatabaseCorruptionHandleTest002, TestSize.Level1)
180 {
181 /**
182 * @tc.steps: step1. Get the kvStore.
183 * @tc.steps: step2. Put data into the store.
184 * @tc.steps: step3. Close the store.
185 */
186 CipherPassword passwd;
187 Key randomPassword;
188 DistributedDBToolsUnitTest::GetRandomKeyValue(randomPassword, PASSWD_SIZE);
189 int errCode = passwd.SetValue(randomPassword.data(), randomPassword.size());
190 ASSERT_EQ(errCode, CipherPassword::ErrorCode::OK);
191 KvStoreDelegate::Option option = {true, false, false, CipherType::DEFAULT, passwd};
192 KvStoreNbDelegate::Option nbOption = {true, false, false, CipherType::DEFAULT, passwd};
193
194 g_mgr.GetKvStore("corrupt2", option, g_kvDelegateCallback);
195 g_mgr.GetKvStore("corrupt3", nbOption, g_kvNbDelegateCallback);
196 ASSERT_TRUE(g_kvDelegatePtr != nullptr);
197 ASSERT_TRUE(g_kvNbDelegatePtr != nullptr);
198 ASSERT_EQ(PutDataIntoDatabase(g_kvDelegatePtr, g_kvNbDelegatePtr), OK);
199 EXPECT_EQ(g_mgr.CloseKvStore(g_kvDelegatePtr), OK);
200 EXPECT_EQ(g_mgr.CloseKvStore(g_kvNbDelegatePtr), OK);
201 g_kvDelegatePtr = nullptr;
202 g_kvNbDelegatePtr = nullptr;
203
204 /**
205 * @tc.steps: step4. Modify the database file.
206 */
207 std::string filePath = GetKvStoreDirectory("corrupt2", DBConstant::DB_TYPE_MULTI_VER);
208 DistributedDBToolsUnitTest::ModifyDatabaseFile(filePath);
209 filePath = GetKvStoreDirectory("corrupt3", DBConstant::DB_TYPE_SINGLE_VER); // single ver database.
210 DistributedDBToolsUnitTest::ModifyDatabaseFile(filePath);
211 KvStoreCorruptInfo corruptInfo;
212 auto notifier = bind(&KvStoreCorruptInfo::CorruptCallBack, &corruptInfo, std::placeholders::_1,
213 std::placeholders::_2, std::placeholders::_3);
214 g_mgr.SetKvStoreCorruptionHandler(notifier);
215 std::this_thread::sleep_for(std::chrono::milliseconds(WAIT_CALLBACK_TIME));
216 /**
217 * @tc.steps: step5. Re-obtain the kvStore.
218 * @tc.expected: step5. Returns null kvstore.
219 */
220 g_mgr.GetKvStore("corrupt2", option, g_kvDelegateCallback);
221 g_mgr.GetKvStore("corrupt3", nbOption, g_kvNbDelegateCallback);
222 ASSERT_TRUE(g_kvDelegateStatus != OK);
223 ASSERT_TRUE(g_kvNbDelegateStatus != OK);
224 std::this_thread::sleep_for(std::chrono::milliseconds(WAIT_CALLBACK_TIME));
225 EXPECT_EQ(corruptInfo.GetDatabaseInfoSize(), 2UL); // 2 callback
226 EXPECT_EQ(corruptInfo.IsDataBaseCorrupted(APP_NAME, USER_NAME, "corrupt2"), true);
227 EXPECT_EQ(corruptInfo.IsDataBaseCorrupted(APP_NAME, USER_NAME, "corrupt3"), true);
228 g_mgr.DeleteKvStore("corrupt2");
229 g_mgr.DeleteKvStore("corrupt3");
230 }
231
232 /**
233 * @tc.name: DatabaseCorruptionHandleTest003
234 * @tc.desc: Test the CloseKvStore Interface and check whether the database file can be closed.
235 * @tc.type: FUNC
236 * @tc.require: AR000D487C SR000D4878
237 * @tc.author: wangbingquan
238 */
239 HWTEST_F(DistributedDBInterfacesDatabaseCorruptTest, DatabaseCorruptionHandleTest003, TestSize.Level1)
240 {
241 /**
242 * @tc.steps: step1. Get the kvStore.
243 * @tc.steps: step2. Put data into the store.
244 * @tc.steps: step3. Close the store.
245 */
246 CipherPassword passwd;
247 Key randomPassword;
248 DistributedDBToolsUnitTest::GetRandomKeyValue(randomPassword, PASSWD_SIZE);
249 int errCode = passwd.SetValue(randomPassword.data(), randomPassword.size());
250 ASSERT_EQ(errCode, CipherPassword::ErrorCode::OK);
251 KvStoreDelegate::Option option = {true, true, false, CipherType::DEFAULT, passwd};
252 KvStoreNbDelegate::Option nbOption = {true, false, false, CipherType::DEFAULT, passwd};
253
254 g_mgr.GetKvStore("corrupt4", option, g_kvDelegateCallback);
255 g_mgr.GetKvStore("corrupt5", nbOption, g_kvNbDelegateCallback);
256 ASSERT_TRUE(g_kvDelegatePtr != nullptr);
257 ASSERT_TRUE(g_kvNbDelegatePtr != nullptr);
258 ASSERT_EQ(PutDataIntoDatabase(g_kvDelegatePtr, g_kvNbDelegatePtr), OK);
259
260 /**
261 * @tc.steps: step4. Modify the database file.
262 */
263 std::string filePath = GetKvStoreDirectory("corrupt4", DBConstant::DB_TYPE_LOCAL); // local database.
264 DistributedDBToolsUnitTest::ModifyDatabaseFile(filePath);
265 DistributedDBToolsUnitTest::ModifyDatabaseFile(filePath + "-wal");
266 filePath = GetKvStoreDirectory("corrupt5", DBConstant::DB_TYPE_SINGLE_VER); // single ver database.
267 DistributedDBToolsUnitTest::ModifyDatabaseFile(filePath);
268 DistributedDBToolsUnitTest::ModifyDatabaseFile(filePath + "-wal");
269 KvStoreCorruptInfo corruptInfo;
270 auto notifier = bind(&KvStoreCorruptInfo::CorruptCallBack, &corruptInfo, std::placeholders::_1,
271 std::placeholders::_2, std::placeholders::_3);
272 g_mgr.SetKvStoreCorruptionHandler(notifier);
273
274 /**
275 * @tc.steps: step5. Put data into the kvStore.
276 * @tc.expected: step5. The corrupt handler is called twice.
277 */
278 ASSERT_NE(PutDataIntoDatabase(g_kvDelegatePtr, nullptr), OK);
279 ASSERT_NE(PutDataIntoDatabase(nullptr, g_kvNbDelegatePtr), OK);
280 std::this_thread::sleep_for(std::chrono::milliseconds(WAIT_CALLBACK_TIME));
281 EXPECT_TRUE(corruptInfo.GetDatabaseInfoSize() >= 2UL); // 2 more callback
282 EXPECT_EQ(corruptInfo.IsDataBaseCorrupted(APP_NAME, USER_NAME, "corrupt4"), true);
283 EXPECT_EQ(corruptInfo.IsDataBaseCorrupted(APP_NAME, USER_NAME, "corrupt5"), true);
284 EXPECT_EQ(g_mgr.CloseKvStore(g_kvDelegatePtr), OK);
285 EXPECT_EQ(g_mgr.CloseKvStore(g_kvNbDelegatePtr), OK);
286 g_kvDelegatePtr = nullptr;
287 g_kvNbDelegatePtr = nullptr;
288 EXPECT_EQ(g_mgr.DeleteKvStore("corrupt4"), OK);
289 EXPECT_EQ(g_mgr.DeleteKvStore("corrupt5"), OK);
290 }
291
292 /**
293 * @tc.name: DatabaseCorruptionHandleTest004
294 * @tc.desc: Test the DeleteKvStore Interface and check whether the database files can be removed.
295 * @tc.type: FUNC
296 * @tc.require: AR000D487C SR000D4878
297 * @tc.author: wangbingquan
298 */
299 HWTEST_F(DistributedDBInterfacesDatabaseCorruptTest, DatabaseCorruptionHandleTest004, TestSize.Level1)
300 {
301 /**
302 * @tc.steps: step1. Get the kvStore.
303 * @tc.steps: step2. Put data into the store.
304 * @tc.steps: step3. Close the store.
305 */
306 CipherPassword passwd;
307 Key randomPassword;
308 DistributedDBToolsUnitTest::GetRandomKeyValue(randomPassword, PASSWD_SIZE);
309 int errCode = passwd.SetValue(randomPassword.data(), randomPassword.size());
310 ASSERT_EQ(errCode, CipherPassword::ErrorCode::OK);
311 KvStoreDelegate::Option option = {true, true, false, CipherType::DEFAULT, passwd};
312 KvStoreNbDelegate::Option nbOption = {true, false, false, CipherType::DEFAULT, passwd};
313
314 g_mgr.GetKvStore("corrupt6", option, g_kvDelegateCallback);
315 g_mgr.GetKvStore("corrupt7", nbOption, g_kvNbDelegateCallback);
316 ASSERT_TRUE(g_kvDelegatePtr != nullptr);
317 ASSERT_TRUE(g_kvNbDelegatePtr != nullptr);
318 ASSERT_EQ(PutDataIntoDatabase(g_kvDelegatePtr, g_kvNbDelegatePtr), OK);
319
320 /**
321 * @tc.steps: step4. Modify the database file.
322 */
323 std::string filePath = GetKvStoreDirectory("corrupt6", DBConstant::DB_TYPE_LOCAL); // local database.
324 DistributedDBToolsUnitTest::ModifyDatabaseFile(filePath);
325 DistributedDBToolsUnitTest::ModifyDatabaseFile(filePath + "-wal");
326 filePath = GetKvStoreDirectory("corrupt7", DBConstant::DB_TYPE_SINGLE_VER); // single ver database.
327 DistributedDBToolsUnitTest::ModifyDatabaseFile(filePath);
328 DistributedDBToolsUnitTest::ModifyDatabaseFile(filePath + "-wal");
329 KvStoreCorruptInfo corruptInfo;
330 KvStoreCorruptInfo corruptInfoNew;
331 auto notifier = bind(&KvStoreCorruptInfo::CorruptCallBack, &corruptInfo, std::placeholders::_1,
332 std::placeholders::_2, std::placeholders::_3);
333 g_mgr.SetKvStoreCorruptionHandler(notifier);
334 auto notifierNew = bind(&KvStoreCorruptInfo::CorruptCallBack, &corruptInfoNew, std::placeholders::_1,
335 std::placeholders::_2, std::placeholders::_3);
336 g_mgr.SetKvStoreCorruptionHandler(notifierNew);
337 /**
338 * @tc.steps: step5. Re-obtain the kvStore.
339 * @tc.expected: step5. Returns null kvstore.
340 */
341 ASSERT_NE(PutDataIntoDatabase(g_kvDelegatePtr, nullptr), OK);
342 ASSERT_NE(PutDataIntoDatabase(nullptr, g_kvNbDelegatePtr), OK);
343 std::this_thread::sleep_for(std::chrono::milliseconds(WAIT_CALLBACK_TIME));
344 EXPECT_EQ(corruptInfo.GetDatabaseInfoSize(), 0UL); // no callback
345 EXPECT_TRUE(corruptInfoNew.GetDatabaseInfoSize() >= 2UL); // 2 more callback
346 EXPECT_EQ(corruptInfoNew.IsDataBaseCorrupted(APP_NAME, USER_NAME, "corrupt6"), true);
347 EXPECT_EQ(corruptInfoNew.IsDataBaseCorrupted(APP_NAME, USER_NAME, "corrupt7"), true);
348 EXPECT_EQ(g_mgr.CloseKvStore(g_kvDelegatePtr), OK);
349 EXPECT_EQ(g_mgr.CloseKvStore(g_kvNbDelegatePtr), OK);
350 g_kvDelegatePtr = nullptr;
351 g_kvNbDelegatePtr = nullptr;
352 EXPECT_EQ(g_mgr.DeleteKvStore("corrupt6"), OK);
353 EXPECT_EQ(g_mgr.DeleteKvStore("corrupt7"), OK);
354 }
355
356 namespace {
357 const uint32_t MODIFY_SIZE = 12; // Modify size is 12 * sizeof(uint32_t);
358 const uint32_t MODIFY_VALUE = 0xF3F3F3F3; // random value, make sure to destroy the page header.
TestDatabaseIntegrityCheckOption(const std::string & storeId,bool isEncrypted)359 void TestDatabaseIntegrityCheckOption(const std::string &storeId, bool isEncrypted)
360 {
361 KvStoreNbDelegate::Option nbOption = {true, false, isEncrypted};
362 nbOption.isNeedIntegrityCheck = false;
363 nbOption.isNeedRmCorruptedDb = false;
364 if (isEncrypted) {
365 Key randPassword;
366 DistributedDBToolsUnitTest::GetRandomKeyValue(randPassword, PASSWD_SIZE);
367 ASSERT_EQ(nbOption.passwd.SetValue(randPassword.data(), randPassword.size()), CipherPassword::ErrorCode::OK);
368 }
369 auto filePath = GetKvStoreDirectory(storeId, DBConstant::DB_TYPE_SINGLE_VER);
370 g_mgr.GetKvStore(storeId, nbOption, g_kvNbDelegateCallback);
371 ASSERT_EQ(g_kvNbDelegateStatus, OK);
372 ASSERT_TRUE(g_kvNbDelegatePtr != nullptr);
373 ASSERT_EQ(PutDataIntoDatabase(nullptr, g_kvNbDelegatePtr), OK);
374 EXPECT_EQ(g_mgr.CloseKvStore(g_kvNbDelegatePtr), OK);
375
376 /**
377 * @tc.steps: step1. Modify the database file header to destroy the header and call the GetKvStore.
378 * @tc.expected: step1. Returns null kv store and the errCode is INVALID_PASSWD_OR_CORRUPTED_DB.
379 */
380 DistributedDBToolsUnitTest::ModifyDatabaseFile(filePath, 0, MODIFY_SIZE, MODIFY_VALUE);
381 g_mgr.GetKvStore(storeId, nbOption, g_kvNbDelegateCallback);
382 ASSERT_EQ(g_kvNbDelegateStatus, INVALID_PASSWD_OR_CORRUPTED_DB);
383 ASSERT_TRUE(g_kvNbDelegatePtr == nullptr);
384
385 /**
386 * @tc.steps: step2. call the GetKvStore with integrity check option is true.
387 * @tc.expected: step2. Returns null kv store and the errCode is INVALID_PASSWD_OR_CORRUPTED_DB.
388 */
389 nbOption.isNeedIntegrityCheck = true;
390 g_mgr.GetKvStore(storeId, nbOption, g_kvNbDelegateCallback);
391 ASSERT_EQ(g_kvNbDelegateStatus, INVALID_PASSWD_OR_CORRUPTED_DB);
392 ASSERT_TRUE(g_kvNbDelegatePtr == nullptr);
393
394 /**
395 * @tc.steps: step3. call the GetKvStore with remove corrupted database option is true.
396 * @tc.expected: step3. Returns non-null kv store and the errCode is OK.
397 */
398 nbOption.isNeedIntegrityCheck = false;
399 nbOption.isNeedRmCorruptedDb = true;
400 g_mgr.GetKvStore(storeId, nbOption, g_kvNbDelegateCallback);
401 ASSERT_TRUE(g_kvNbDelegatePtr != nullptr);
402
403 ASSERT_EQ(PutDataIntoDatabase(nullptr, g_kvNbDelegatePtr), OK);
404 EXPECT_EQ(g_mgr.CloseKvStore(g_kvNbDelegatePtr), OK);
405
406 /**
407 * @tc.steps: step4. Modify the second page of the database file and Get the kv store.
408 * @tc.expected: step4. Returns non-null kv store and the errCode is OK(GetKvStore skip the check of the page 2).
409 */
410 size_t filePos = isEncrypted ? 1024 : 4096; // 1024 and 4096 is the page size.
411 DistributedDBToolsUnitTest::ModifyDatabaseFile(filePath, filePos, MODIFY_SIZE, MODIFY_VALUE);
412 nbOption.isNeedRmCorruptedDb = false;
413 g_mgr.GetKvStore(storeId, nbOption, g_kvNbDelegateCallback);
414 ASSERT_TRUE(g_kvNbDelegatePtr != nullptr);
415 EXPECT_EQ(g_mgr.CloseKvStore(g_kvNbDelegatePtr), OK);
416
417 /**
418 * @tc.steps: step5. Get the kv store with check the integrity.
419 * @tc.expected: step5. Returns null kv store and the errCode is INVALID_PASSWD_OR_CORRUPTED_DB.
420 */
421 nbOption.isNeedIntegrityCheck = true;
422 g_mgr.GetKvStore(storeId, nbOption, g_kvNbDelegateCallback);
423 ASSERT_EQ(g_kvNbDelegateStatus, INVALID_PASSWD_OR_CORRUPTED_DB);
424 ASSERT_TRUE(g_kvNbDelegatePtr == nullptr);
425
426 /**
427 * @tc.steps: step5. Get the kv store with check the integrity and the rm corrupted database option.
428 * @tc.expected: step5. Returns non-null kv store and the errCode is OK.
429 */
430 nbOption.isNeedRmCorruptedDb = true;
431 g_mgr.GetKvStore(storeId, nbOption, g_kvNbDelegateCallback);
432 ASSERT_TRUE(g_kvNbDelegatePtr != nullptr);
433 EXPECT_EQ(g_mgr.CloseKvStore(g_kvNbDelegatePtr), OK);
434 EXPECT_EQ(g_mgr.DeleteKvStore(storeId), OK);
435 }
436 }
437
438 /**
439 * @tc.name: DatabaseIntegrityCheck001
440 * @tc.desc: Test the integrity check option.
441 * @tc.type: FUNC
442 * @tc.require: AR000D487C SR000D4878
443 * @tc.author: wangbingquan
444 */
445 HWTEST_F(DistributedDBInterfacesDatabaseCorruptTest, DatabaseIntegrityCheck001, TestSize.Level2)
446 {
447 LOGI("Begin to check the unencrypted database");
448 TestDatabaseIntegrityCheckOption("integrity_check001", false);
449 std::this_thread::sleep_for(std::chrono::milliseconds(500));
450 LOGI("Begin to check the encrypted database");
451 TestDatabaseIntegrityCheckOption("integrity_check002", true);
452 }
453
454 /**
455 * @tc.name: DatabaseIntegrityCheck002
456 * @tc.desc: Test the integrity check interface.
457 * @tc.type: FUNC
458 * @tc.require: AR000D487C SR000D4878
459 * @tc.author: wangbingquan
460 */
461 HWTEST_F(DistributedDBInterfacesDatabaseCorruptTest, DatabaseIntegrityCheck002, TestSize.Level1)
462 {
463 CipherPassword passwd;
464 KvStoreNbDelegate::Option nbOption = {true, false, false, CipherType::DEFAULT, passwd};
465 nbOption.isNeedIntegrityCheck = true;
466 nbOption.isNeedRmCorruptedDb = true;
467 auto filePath = GetKvStoreDirectory("integrity021", DBConstant::DB_TYPE_SINGLE_VER);
468 for (uint32_t i = 1; i < 4; i++) {
469 LOGI("%u th test!", i);
470 g_mgr.GetKvStore("integrity021", nbOption, g_kvNbDelegateCallback);
471 ASSERT_TRUE(g_kvNbDelegatePtr != nullptr);
472 ASSERT_EQ(g_kvNbDelegatePtr->CheckIntegrity(), OK);
473 ASSERT_EQ(PutDataIntoDatabase(nullptr, g_kvNbDelegatePtr), OK);
474 EXPECT_EQ(g_mgr.CloseKvStore(g_kvNbDelegatePtr), OK);
475 DistributedDBToolsUnitTest::ModifyDatabaseFile(filePath, i * 4096, MODIFY_SIZE, MODIFY_VALUE); // page size 4096
476 g_mgr.GetKvStore("integrity021", nbOption, g_kvNbDelegateCallback);
477 ASSERT_TRUE(g_kvNbDelegatePtr != nullptr);
478 EXPECT_EQ(g_kvNbDelegatePtr->CheckIntegrity(), OK);
479 EXPECT_EQ(g_mgr.CloseKvStore(g_kvNbDelegatePtr), OK);
480 EXPECT_EQ(g_mgr.DeleteKvStore("integrity021"), OK);
481 }
482 LOGI("Begin the encrypted check");
483 Key randomPassword;
484 DistributedDBToolsUnitTest::GetRandomKeyValue(randomPassword, PASSWD_SIZE);
485 int errCode = passwd.SetValue(randomPassword.data(), randomPassword.size());
486 ASSERT_EQ(errCode, CipherPassword::ErrorCode::OK);
487 nbOption = {true, false, true, CipherType::DEFAULT, passwd};
488 nbOption.isNeedIntegrityCheck = true;
489 nbOption.isNeedRmCorruptedDb = true;
490 filePath = GetKvStoreDirectory("integrity022", DBConstant::DB_TYPE_SINGLE_VER);
491 for (uint32_t i = 1; i < 4; i++) {
492 LOGI("%u th test the encrypted database!", i);
493 g_mgr.GetKvStore("integrity022", nbOption, g_kvNbDelegateCallback);
494 ASSERT_TRUE(g_kvNbDelegatePtr != nullptr);
495 ASSERT_EQ(g_kvNbDelegatePtr->CheckIntegrity(), OK);
496 ASSERT_EQ(PutDataIntoDatabase(nullptr, g_kvNbDelegatePtr), OK);
497 EXPECT_EQ(g_mgr.CloseKvStore(g_kvNbDelegatePtr), OK);
498 DistributedDBToolsUnitTest::ModifyDatabaseFile(filePath, i * 1024, MODIFY_SIZE, MODIFY_VALUE); // page size 1024
499 g_mgr.GetKvStore("integrity022", nbOption, g_kvNbDelegateCallback);
500 ASSERT_TRUE(g_kvNbDelegatePtr != nullptr);
501 EXPECT_EQ(g_kvNbDelegatePtr->CheckIntegrity(), OK);
502 EXPECT_EQ(g_mgr.CloseKvStore(g_kvNbDelegatePtr), OK);
503 EXPECT_EQ(g_mgr.DeleteKvStore("integrity022"), OK);
504 }
505 }