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 #include <gtest/gtest.h>
16
17 #include <atomic>
18 #include <ctime>
19 #include <cmath>
20 #include <random>
21 #include <chrono>
22 #include <string>
23 #include <thread>
24 #include <mutex>
25 #include <fstream>
26
27 #include "kv_store_nb_delegate.h"
28 #include "kv_store_delegate_manager.h"
29 #include "distributeddb_nb_test_tools.h"
30 #include "distributeddb_data_generator.h"
31 #include "process_communicator_test_stub.h"
32
33 using namespace std;
34 using namespace chrono;
35 using namespace testing;
36 #if defined TESTCASES_USING_GTEST_EXT
37 using namespace testing::ext;
38 #endif
39 using namespace std::placeholders;
40 using namespace DistributedDB;
41 using namespace DistributedDBDataGenerator;
42
43 namespace DistributeddbNbBackup {
44 KvStoreNbDelegate *g_nbBackupDelegate = nullptr;
45 KvStoreDelegateManager *g_manager = nullptr;
46 static std::condition_variable g_backupVar;
47 std::atomic<bool> g_readyFlag(false);
48
49 DistributedDB::CipherPassword g_passwd1;
50 DistributedDB::CipherPassword g_passwd2;
51 DistributedDB::CipherPassword g_filePasswd1;
52 DistributedDB::CipherPassword g_filePasswd2;
53
54 class DistributeddbNbBackupTest : public testing::Test {
55 public:
56 static void SetUpTestCase(void);
57 static void TearDownTestCase(void);
58 void SetUp();
59 void TearDown();
60 private:
61 };
62
SetUpTestCase(void)63 void DistributeddbNbBackupTest::SetUpTestCase(void)
64 {
65 KvStoreDelegateManager *manager = new (std::nothrow) KvStoreDelegateManager(APP_ID_1, USER_ID_1);
66 ASSERT_NE(manager, nullptr);
67 manager->SetProcessLabel("MST", "GetDevicesID");
68 manager->SetProcessCommunicator(std::make_shared<ProcessCommunicatorTestStub>());
69 delete manager;
70 manager = nullptr;
71 (void)g_passwd1.SetValue(PASSWD_VECTOR_1.data(), PASSWD_VECTOR_1.size());
72 (void)g_passwd2.SetValue(PASSWD_VECTOR_2.data(), PASSWD_VECTOR_2.size());
73 (void)g_filePasswd1.SetValue(FILE_PASSWD_VECTOR_1.data(), FILE_PASSWD_VECTOR_1.size());
74 (void)g_filePasswd2.SetValue(FILE_PASSWD_VECTOR_2.data(), FILE_PASSWD_VECTOR_2.size());
75 }
76
TearDownTestCase(void)77 void DistributeddbNbBackupTest::TearDownTestCase(void)
78 {
79 }
80
SetUp(void)81 void DistributeddbNbBackupTest::SetUp(void)
82 {
83 const std::string exportPath = DistributedDBConstant::NB_DIRECTOR + "export";
84 RemoveDir(exportPath);
85 RemoveDir(DistributedDBConstant::NB_DIRECTOR);
86
87 UnitTest *test = UnitTest::GetInstance();
88 ASSERT_NE(test, nullptr);
89 const TestInfo *testinfo = test->current_test_info();
90 ASSERT_NE(testinfo, nullptr);
91 string testCaseName = string(testinfo->name());
92 MST_LOG("[SetUp] test case %s is start to run", testCaseName.c_str());
93
94 g_nbBackupDelegate = DistributedDBNbTestTools::GetNbDelegateSuccess(g_manager, g_dbParameter1, g_option);
95 ASSERT_TRUE(g_manager != nullptr && g_nbBackupDelegate != nullptr);
96 }
97
TearDown(void)98 void DistributeddbNbBackupTest::TearDown(void)
99 {
100 MST_LOG("TearDown after case.");
101 ASSERT_NE(g_manager, nullptr);
102 EXPECT_TRUE(EndCaseDeleteDB(g_manager, g_nbBackupDelegate, STORE_ID_1, g_option.isMemoryDb));
103 }
104
105 /*
106 * @tc.name: ExportTest001
107 * @tc.desc: test checking in parameter of filepath of export interface.
108 * @tc.type: FUNC
109 * @tc.require: SR000D4878
110 * @tc.author: fengxiaoyun
111 */
112 HWTEST_F(DistributeddbNbBackupTest, ExportTest001, TestSize.Level1)
113 {
114 /**
115 * @tc.steps: step1. call export interface and the dir of filepath is nonexistent.
116 * @tc.expected: step1. call failed and return INVALID_ARGS.
117 */
118 int fileCount = 0;
119 const std::string exportPath = DistributedDBConstant::NB_DIRECTOR + "export";
120 const std::string filePath = exportPath + "/bkpDB.bin";
121 EXPECT_EQ(g_nbBackupDelegate->Export(filePath, NULL_PASSWD), INVALID_ARGS);
122
123 /**
124 * @tc.steps: step2. call export interface, the filepath is absolute path and legal then check file number.
125 * @tc.expected: step2. call successfully and the file number is 1.
126 */
127 SetDir(exportPath);
128 EXPECT_EQ(g_nbBackupDelegate->Export(filePath, NULL_PASSWD), OK);
129 CheckFileNumber(exportPath, fileCount);
130 EXPECT_EQ(fileCount, 1);
131 RemoveDir(exportPath);
132 RemoveDatabaseDirectory(exportPath);
133
134 /**
135 * @tc.steps: step3. call export interface to export data and the dir of filepath is no r,w right.
136 * @tc.expected: step3. call failed return INVALID_ARGS.
137 */
138 #ifdef RUNNING_ON_SIMULATED_ENV
139 const std::string noRightPath = "../noright";
140 const int authRight = 0111;
141 SetDir(noRightPath, authRight);
142 std::string filePath2 = noRightPath + "/bkpDB.bin";
143 EXPECT_EQ(g_nbBackupDelegate->Export(filePath2, NULL_PASSWD), NO_PERMISSION);
144 RemoveDatabaseDirectory(noRightPath);
145 #endif
146 /**
147 * @tc.steps: step4. call export interface, the filepath is relative path and legal then check file number.
148 * @tc.expected: step4. call successfully and the file number is 1.
149 */
150 const std::string exportPath2 = "../export";
151 SetDir(exportPath2);
152 const std::string filePath3 = exportPath2 + "/bkpDB.bin";
153 EXPECT_EQ(g_nbBackupDelegate->Export(filePath3, NULL_PASSWD), OK);
154 CheckFileNumber(exportPath2, fileCount);
155 EXPECT_EQ(fileCount, 1);
156 RemoveDir(exportPath2);
157 }
158
159 /*
160 * @tc.name: ExportTest 002
161 * @tc.desc: Verify that the export interface will return FILE_ALREADY_EXISTED if the export file has been exist and
162 * the memory db doesn't support export.
163 * @tc.type: FUNC
164 * @tc.require: SR000D4878
165 * @tc.author: fengxiaoyun
166 */
167 HWTEST_F(DistributeddbNbBackupTest, ExportTest002, TestSize.Level1)
168 {
169 /**
170 * @tc.steps: step1. call export interface and the dir of filepath is legal then check file number.
171 * @tc.expected: step1. call successfully and the file number of filepath is 1.
172 */
173 int fileCount = 0;
174 const std::string exportPath = DistributedDBConstant::NB_DIRECTOR + "export";
175 SetDir(exportPath);
176 std::string filePath = exportPath + "/bkpDB.bin";
177 EXPECT_TRUE(g_nbBackupDelegate->Export(filePath, NULL_PASSWD) == OK);
178 CheckFileNumber(exportPath, fileCount);
179 EXPECT_EQ(fileCount, 1);
180
181 /**
182 * @tc.steps: step2. call export interface and the directory of file is existent.
183 * @tc.expected: step2. call failed and return FILE_ALREADY_EXISTED.
184 */
185 EXPECT_TRUE(g_nbBackupDelegate->Export(filePath, NULL_PASSWD) == FILE_ALREADY_EXISTED);
186 CheckFileNumber(exportPath, fileCount);
187 EXPECT_EQ(fileCount, 1); // the number of files is 1.
188
189 /**
190 * @tc.steps: step3. create memory db and call export interface.
191 * @tc.expected: step3. call failed and return NOT_SUPPORT.
192 */
193 KvStoreNbDelegate *delegate = nullptr;
194 KvStoreDelegateManager *manager = nullptr;
195 Option option;
196 option.isMemoryDb = true;
197 delegate = DistributedDBNbTestTools::GetNbDelegateSuccess(manager, g_dbParameter2, option);
198 ASSERT_TRUE(manager != nullptr && delegate != nullptr);
199 filePath = exportPath + "/bkpDB1.bin";
200 EXPECT_TRUE(delegate->Export(filePath, NULL_PASSWD) == NOT_SUPPORT);
201 EXPECT_EQ((manager->CloseKvStore(delegate)), OK);
202
203 /**
204 * @tc.steps: step4. call export interface when there is unclosed resultset and check the number of files.
205 * @tc.expected: step4. call successfully and the number of files is 2.
206 */
207 KvStoreResultSet *resultSet;
208 EXPECT_EQ(g_nbBackupDelegate->GetEntries(KEY_EMPTY, resultSet), OK);
209 filePath = exportPath + "/bkpDB2.bin";
210 EXPECT_TRUE(g_nbBackupDelegate->Export(filePath, NULL_PASSWD) == OK);
211 CheckFileNumber(exportPath, fileCount);
212 EXPECT_EQ(fileCount, 2); // the number of files is 2.
213 EXPECT_EQ(g_nbBackupDelegate->CloseResultSet(resultSet), OK);
214 RemoveDir(exportPath);
215 delete manager;
216 manager = nullptr;
217 }
218
219 /*
220 * @tc.name: ExportTest 003
221 * @tc.desc: Verify that the export interface will return busy when the import hasn't completed.
222 * @tc.type: FUNC
223 * @tc.require: SR000D4878
224 * @tc.author: fengxiaoyun
225 */
226 HWTEST_F(DistributeddbNbBackupTest, ExportTest003, TestSize.Level2)
227 {
228 std::vector<DistributedDB::Entry> entriesBatch;
229 std::vector<DistributedDB::Key> allKeys;
230 GenerateFixedRecords(entriesBatch, allKeys, TEN_RECORDS, ONE_K_LONG_STRING, ONE_M_LONG_STRING);
231 for (vector<Entry>::iterator iter = entriesBatch.begin(); iter != entriesBatch.end(); iter++) {
232 EXPECT_TRUE(g_nbBackupDelegate->Put(iter->key, iter->value) == OK);
233 }
234 int fileCount = 0;
235 const std::string exportPath = DistributedDBConstant::NB_DIRECTOR + "export";
236 SetDir(exportPath);
237 std::string filePath = exportPath + "/bkpDB.bin";
238 EXPECT_TRUE(g_nbBackupDelegate->Export(filePath, NULL_PASSWD) == OK);
239 CheckFileNumber(exportPath, fileCount);
240 EXPECT_EQ(fileCount, 1);
241
242 /**
243 * @tc.steps: step1. call import interface to import the file that prepared in advance.
244 * @tc.expected: step1. call successfully.
245 */
246 g_readyFlag.store(false);
__anonced11ad80102() 247 thread subThread([&filePath]() {
248 EXPECT_EQ(g_nbBackupDelegate->Import(filePath, NULL_PASSWD), OK);
249 g_readyFlag.store(true);
250 g_backupVar.notify_all();
251 });
252 subThread.detach();
253
254 /**
255 * @tc.steps: step2. call export interface when step1 is running.
256 * @tc.expected: step2. return busy if step1 hasn't completed, else return OK.
257 */
258 std::this_thread::sleep_for(std::chrono::microseconds(WAIT_FOR_TWO_HUNDREDS_MS));
259 filePath = exportPath + "/bkpDB1.bin";
260 DBStatus status = g_nbBackupDelegate->Export(filePath, NULL_PASSWD);
261 EXPECT_TRUE(status == BUSY || status == OK);
262 CheckFileNumber(exportPath, fileCount);
263 if (status == BUSY) {
264 EXPECT_EQ(fileCount, 1);
265 } else {
266 EXPECT_EQ(fileCount, 2); // if export success, the number of file is 2.
267 }
268
269 std::mutex count;
270 std::unique_lock<std::mutex> lck(count);
__anonced11ad80202null271 g_backupVar.wait(lck, [&]{ return g_readyFlag.load(); });
272 RemoveDir(exportPath);
273 }
274
275 #ifndef LOW_LEVEL_MEM_DEV
276 /*
277 * @tc.name: ExportTest 004
278 * @tc.desc: Verify that the export interface will return busy when the rekey hasn't completed.
279 * @tc.type: FUNC
280 * @tc.require: SR000D4878
281 * @tc.author: fengxiaoyun
282 */
283 HWTEST_F(DistributeddbNbBackupTest, ExportTest004, TestSize.Level3)
284 {
285 std::vector<DistributedDB::Entry> entriesBatch;
286 std::vector<DistributedDB::Key> allKeys;
287 GenerateFixedRecords(entriesBatch, allKeys, NB_PREDATA_NUM, ONE_K_LONG_STRING, TWO_M_LONG_STRING);
288 for (vector<Entry>::iterator iter = entriesBatch.begin(); iter != entriesBatch.end(); iter++) {
289 EXPECT_TRUE(g_nbBackupDelegate->Put(iter->key, iter->value) == OK);
290 }
291 /**
292 * @tc.steps: step1. call import interface to import the file that prepared in advance.
293 * @tc.expected: step1. call successfully if step1 running before step2, else return busy.
294 */
295 g_readyFlag.store(false);
__anonced11ad80302() 296 thread subThread([]() {
297 DBStatus rekeyStatus = g_nbBackupDelegate->Rekey(g_passwd1);
298 EXPECT_TRUE(rekeyStatus == OK || rekeyStatus == BUSY);
299 MST_LOG("The rekeyStatus is %d", rekeyStatus);
300 g_readyFlag.store(true);
301 g_backupVar.notify_all();
302 });
303 subThread.detach();
304
305 /**
306 * @tc.steps: step2. call export interface when step1 is running.
307 * @tc.expected: step2. return busy if step1 is running, else return OK.
308 */
309 int fileCount = 0;
310 const std::string exportPath = DistributedDBConstant::NB_DIRECTOR + "export";
311 SetDir(exportPath);
312 const std::string filePath = exportPath + "/bkpDB.bin";
313 std::this_thread::sleep_for(std::chrono::microseconds(WAIT_FOR_LONG_TIME));
314 DBStatus status = g_nbBackupDelegate->Export(filePath, NULL_PASSWD);
315 EXPECT_TRUE(status == BUSY || status == OK);
316 CheckFileNumber(exportPath, fileCount);
317 if (status == BUSY) {
318 EXPECT_EQ(fileCount, 0);
319 } else {
320 EXPECT_EQ(fileCount, 1);
321 }
322
323 std::mutex count;
324 std::unique_lock<std::mutex> lck(count);
__anonced11ad80402null325 g_backupVar.wait(lck, [&]{ return g_readyFlag.load(); });
326 RemoveDir(exportPath);
327 }
328 #endif
329
330 /*
331 * @tc.name: ExportTest 005
332 * @tc.desc: Verify that the export interface will execute blockly when last export hasn't completed.
333 * @tc.type: FUNC
334 * @tc.require: SR000D4878
335 * @tc.author: fengxiaoyun
336 */
337 HWTEST_F(DistributeddbNbBackupTest, ExportTest005, TestSize.Level2)
338 {
339 int fileCount = 0;
340 const std::string exportPath = DistributedDBConstant::NB_DIRECTOR + "export";
341 SetDir(exportPath);
342 std::string filePath = exportPath + "/bkpDB.bin";
343 std::vector<DistributedDB::Entry> entriesBatch;
344 std::vector<DistributedDB::Key> allKeys;
345 GenerateFixedRecords(entriesBatch, allKeys, TEN_RECORDS, ONE_K_LONG_STRING, FOUR_M_LONG_STRING);
346 for (vector<Entry>::iterator iter = entriesBatch.begin(); iter != entriesBatch.end(); iter++) {
347 EXPECT_TRUE(g_nbBackupDelegate->Put(iter->key, iter->value) == OK);
348 }
349 /**
350 * @tc.steps: step1. call import interface to import the file that prepared in advance.
351 * @tc.expected: step1. call successfully.
352 */
353 g_readyFlag.store(false);
__anonced11ad80502() 354 thread subThread([&filePath]() {
355 std::this_thread::sleep_for(std::chrono::microseconds(WAIT_FOR_LONG_TIME));
356 DBStatus exportStatus = g_nbBackupDelegate->Export(filePath, NULL_PASSWD);
357 EXPECT_EQ(exportStatus, OK);
358 g_readyFlag.store(true);
359 g_backupVar.notify_one();
360 });
361 subThread.detach();
362
363 /**
364 * @tc.steps: step2. call export interface when step1 is running.
365 * @tc.expected: step2. it can be called after last export finished.
366 */
367 std::string filePath2 = exportPath + "/bkpDB1.bin";
368 EXPECT_EQ(g_nbBackupDelegate->Export(filePath2, NULL_PASSWD), OK);
369
370 std::mutex count;
371 std::unique_lock<std::mutex> lck(count);
__anonced11ad80602null372 g_backupVar.wait(lck, [&]{ return g_readyFlag.load(); });
373 CheckFileNumber(exportPath, fileCount);
374 EXPECT_EQ(fileCount, 2); // the export file number is 2.
375 RemoveDir(exportPath);
376 }
377
378 /*
379 * @tc.name: ExportTest 006
380 * @tc.desc: Verify that the put/delete operation will execute blockly when export hasn't completed.
381 * @tc.type: FUNC
382 * @tc.require: SR000D4878
383 * @tc.author: fengxiaoyun
384 */
385 HWTEST_F(DistributeddbNbBackupTest, ExportTest006, TestSize.Level3)
386 {
387 int fileCount = 0;
388 const std::string exportPath = DistributedDBConstant::NB_DIRECTOR + "export";
389 SetDir(exportPath);
390 std::string filePath = exportPath + "/bkpDB.bin";
391 std::vector<DistributedDB::Entry> entriesBatch;
392 std::vector<DistributedDB::Key> allKeys;
393 GenerateFixedRecords(entriesBatch, allKeys, FIFTY_RECORDS, ONE_K_LONG_STRING, TWO_M_LONG_STRING);
394 for (vector<Entry>::iterator iter = entriesBatch.begin(); iter != entriesBatch.end(); iter++) {
395 EXPECT_TRUE(g_nbBackupDelegate->Put(iter->key, iter->value) == OK);
396 EXPECT_TRUE(g_nbBackupDelegate->PutLocal(iter->key, iter->value) == OK);
397 }
398 /**
399 * @tc.steps: step1. call export interface in subthread.
400 * @tc.expected: step1. call successfully.
401 */
402 g_readyFlag.store(false);
__anonced11ad80702() 403 thread subThread([&filePath]() {
404 DBStatus exportStatus = g_nbBackupDelegate->Export(filePath, NULL_PASSWD);
405 EXPECT_EQ(exportStatus, OK);
406 g_readyFlag.store(true);
407 g_backupVar.notify_all();
408 });
409 subThread.detach();
410
411 /**
412 * @tc.steps: step2. call Get,GetLocal,GetEntries to query data from db.
413 * @tc.expected: step2. call successfully(if export continued over 30s, put will return busy).
414 */
415 Value valueResult;
416 EXPECT_TRUE(g_nbBackupDelegate->Get(allKeys[0], valueResult) == OK);
417 EXPECT_EQ(valueResult, entriesBatch[0].value);
418 EXPECT_TRUE(g_nbBackupDelegate->GetLocal(allKeys[1], valueResult) == OK);
419 EXPECT_EQ(valueResult, entriesBatch[1].value);
420 std::vector<Entry> entries;
421 EXPECT_TRUE(g_nbBackupDelegate->GetEntries(KEY_EMPTY, entries) == OK);
422 EXPECT_EQ(entries.size(), entriesBatch.size());
423 /**
424 * @tc.steps: step3. call put/delete/putlocal/deletelocal interface when step1 is running.
425 * @tc.expected: step3. return ok, if step1 need more than 30s to finish, it will return busy.
426 */
427 DBStatus status = g_nbBackupDelegate->Put(entriesBatch[0].key, entriesBatch[0].value);
428 EXPECT_TRUE((status == OK) || (status == BUSY));
429 status = g_nbBackupDelegate->PutLocal(entriesBatch[1].key, entriesBatch[1].value);
430 EXPECT_TRUE((status == OK) || (status == BUSY));
431 status = g_nbBackupDelegate->Delete(allKeys[0]);
432 EXPECT_TRUE((status == OK) || (status == BUSY));
433
434 std::mutex count;
435 std::unique_lock<std::mutex> lck(count);
__anonced11ad80802null436 g_backupVar.wait(lck, [&]{ return g_readyFlag.load(); });
437 CheckFileNumber(exportPath, fileCount);
438 EXPECT_EQ(fileCount, 1);
439 RemoveDir(exportPath);
440 }
441
442 /*
443 * @tc.name: ExportTest 007
444 * @tc.desc: Verify that passwd parameter of export interface decide the file exported is encrypted or not.
445 * @tc.type: FUNC
446 * @tc.require: SR000D4878
447 * @tc.author: fengxiaoyun
448 */
449 HWTEST_F(DistributeddbNbBackupTest, ExportTest007, TestSize.Level1)
450 {
451 int fileCount = 0;
452 const std::string exportPath = DistributedDBConstant::NB_DIRECTOR + "export";
453 SetDir(exportPath);
454 std::string filePath = exportPath + "/bkpDB1.bin";
455
456 /**
457 * @tc.steps: step1. call export interface with NULL_PASSWD.
458 * @tc.expected: step1. call successfully.
459 */
460 EXPECT_EQ(g_nbBackupDelegate->Export(filePath, NULL_PASSWD), OK);
461 CheckFileNumber(exportPath, fileCount);
462 EXPECT_EQ(fileCount, 1);
463
464 /**
465 * @tc.steps: step2. call export interface with the passwd = password(129B).
466 * @tc.expected: step2. return INVALID_ARGS.
467 */
468 filePath = exportPath + "/bkpDB2.bin";
469 vector<uint8_t> passwordVector(PASSWD_BYTE, 'a');
470 CipherPassword password;
471 EXPECT_EQ(password.SetValue(passwordVector.data(), passwordVector.size()), CipherPassword::ErrorCode::OVERSIZE);
472 CheckFileNumber(exportPath, fileCount);
473 EXPECT_EQ(fileCount, 1);
474
475 /**
476 * @tc.steps: step3. call export interface with the passwd = password(1B).
477 * @tc.expected: step3. return OK.
478 */
479 filePath = exportPath + "/bkpDB3.bin";
480 passwordVector.assign(1, 'b'); // 1 Byte of passwd.
481 EXPECT_EQ(password.SetValue(passwordVector.data(), passwordVector.size()), CipherPassword::ErrorCode::OK);
482 EXPECT_EQ(g_nbBackupDelegate->Export(filePath, password), OK);
483 CheckFileNumber(exportPath, fileCount);
484 EXPECT_EQ(fileCount, 2); // the number of file is 2.
485
486 /**
487 * @tc.steps: step3. call export interface with the passwd = password(128B).
488 * @tc.expected: step3. return OK.
489 */
490 filePath = exportPath + "/bkpDB4.bin";
491 passwordVector.assign(BATCH_RECORDS, 'b'); // 1 Byte of passwd.
492 EXPECT_EQ(password.SetValue(passwordVector.data(), passwordVector.size()), CipherPassword::ErrorCode::OK);
493 EXPECT_EQ(g_nbBackupDelegate->Export(filePath, password), OK);
494 CheckFileNumber(exportPath, fileCount);
495 EXPECT_EQ(fileCount, 3); // the number of file is 3.
496 RemoveDir(exportPath);
497 }
498
499 /*
500 * @tc.name: ImportTest 001
501 * @tc.desc: Verify that it can only import success when the pass word is rightly match(exist and rightly or not).
502 * @tc.type: FUNC
503 * @tc.require: SR000D4878
504 * @tc.author: fengxiaoyun
505 */
506 HWTEST_F(DistributeddbNbBackupTest, ImportTest001, TestSize.Level1)
507 {
508 /**
509 * @tc.steps: step1. device put (k1, v2) to DB and then update it to (k1, v1).
510 * @tc.expected: step1. put successfully.
511 */
512 EXPECT_EQ(g_nbBackupDelegate->Put(KEY_1, VALUE_1), OK);
513 const std::string importPath = DistributedDBConstant::NB_DIRECTOR + "export";
514 SetDir(importPath);
515 std::string filePath1 = importPath + "/bkpDB1.bin";
516 EXPECT_EQ(g_nbBackupDelegate->Export(filePath1, NULL_PASSWD), OK);
517 std::string filePath2 = importPath + "/bkpDB2.bin";
518 EXPECT_EQ(g_nbBackupDelegate->Export(filePath2, g_filePasswd1), OK);
519 EXPECT_EQ(g_nbBackupDelegate->Put(KEY_1, VALUE_2), OK);
520
521 /**
522 * @tc.steps: step2. import backup file bkpDB1.bin with passwd f1.
523 * @tc.expected: step2. import failed and return INVALID_FILE.
524 */
525 EXPECT_EQ(g_nbBackupDelegate->Import(filePath1, g_filePasswd1), INVALID_FILE);
526
527 /**
528 * @tc.steps: step3. import backup file bkpDB1.bin with empty passwd and get the value of key1.
529 * @tc.expected: step3. import successfully, and the value of key1 is value1.
530 */
531 EXPECT_EQ(g_nbBackupDelegate->Import(filePath1, NULL_PASSWD), OK);
532 Value valueResult;
533 g_nbBackupDelegate->Get(KEY_1, valueResult);
534 EXPECT_EQ(valueResult, VALUE_1);
535
536 /**
537 * @tc.steps: step4. update the entry (k1, v1) to (k1, v2).
538 * @tc.expected: step4. update success.
539 */
540 EXPECT_EQ(g_nbBackupDelegate->Put(KEY_1, VALUE_2), OK);
541 /**
542 * @tc.steps: step5. import backup file bkpDB2.bin with empty passwd.
543 * @tc.expected: step5. import failed and return INVALID_FILE.
544 */
545 EXPECT_EQ(g_nbBackupDelegate->Import(filePath2, NULL_PASSWD), INVALID_FILE);
546 /**
547 * @tc.steps: step6. import backup file bkpDB2.bin with DB passwd p1.
548 * @tc.expected: step6. import failed and return INVALID_FILE.
549 */
550 EXPECT_EQ(g_nbBackupDelegate->Import(filePath2, g_passwd1), INVALID_FILE);
551 /**
552 * @tc.steps: step7. import backup file bkpDB2.bin with passwd = password(129B).
553 * @tc.expected: step7. import failed and return INVALID_FILE.
554 */
555 vector<uint8_t> passwordVector(PASSWD_BYTE, 'a');
556 CipherPassword password;
557 EXPECT_EQ(password.SetValue(passwordVector.data(), passwordVector.size()), CipherPassword::ErrorCode::OVERSIZE);
558 /**
559 * @tc.steps: step8. import backup file bkpDB2.bin with DB passwd f1 and get the value of k1.
560 * @tc.expected: step8. import success and return INVALID_FILE.
561 */
562 EXPECT_EQ(g_nbBackupDelegate->Import(filePath2, g_filePasswd1), OK);
563 g_nbBackupDelegate->Get(KEY_1, valueResult);
564 EXPECT_EQ(valueResult, VALUE_1);
565 RemoveDir(importPath);
566 }
567
568 /*
569 * @tc.name: ImportTest 002
570 * @tc.desc: Verify that memory DB can't support to import.
571 * @tc.type: FUNC
572 * @tc.require: SR000D4878
573 * @tc.author: fengxiaoyun
574 */
575 HWTEST_F(DistributeddbNbBackupTest, ImportTest002, TestSize.Level1)
576 {
577 std::string importPath1 = DistributedDBConstant::NB_DIRECTOR + "export";
578 SetDir(importPath1);
579 std::string filePath = importPath1 + "/bkpDB.bin";
580 EXPECT_EQ(g_nbBackupDelegate->Export(filePath, NULL_PASSWD), OK);
581
582 /**
583 * @tc.steps: step1. create memory DB and import the backup file.
584 * @tc.expected: step1. create success but import failed and return NOT_SUPPORT.
585 */
586 KvStoreNbDelegate *delegate2 = nullptr;
587 KvStoreDelegateManager *manager2 = nullptr;
588 Option option;
589 option.isMemoryDb = true;
590 delegate2 = DistributedDBNbTestTools::GetNbDelegateSuccess(manager2, g_dbParameter2, option);
591 ASSERT_TRUE(manager2 != nullptr && delegate2 != nullptr);
592 EXPECT_EQ(delegate2->Import(filePath, NULL_PASSWD), NOT_SUPPORT);
593 /**
594 * @tc.steps: step2. the disk DB import backup file bkpDB1.bin from noexsit path with empty passwd.
595 * @tc.expected: step2. import failed and returned INVALID_FILE.
596 */
597 std::string importPath2 = DistributedDBConstant::NB_DIRECTOR + "/noexsit";
598 std::string filePath2 = importPath2 + "/bkpDB.bin";
599 EXPECT_EQ(g_nbBackupDelegate->Import(filePath2, NULL_PASSWD), INVALID_ARGS);
600
601 /**
602 * @tc.steps: step3. the disk DB import noexsit backup file bkpDB1.bin from noexsit path with empty passwd..
603 * @tc.expected: step3. import failed and returned INVALID_FILE.
604 */
605 std::string filePath3 = importPath1 + "/bkpDB2.bin";
606 EXPECT_EQ(g_nbBackupDelegate->Import(filePath3, NULL_PASSWD), INVALID_FILE);
607
608 EXPECT_EQ(manager2->CloseKvStore(delegate2), OK);
609 delegate2 = nullptr;
610 delete manager2;
611 manager2 = nullptr;
612 RemoveDir(importPath1);
613 }
614
615 /*
616 * @tc.name: ImportTest 003
617 * @tc.desc: Verify that it can't import the not DB file and damaged file.
618 * @tc.type: FUNC
619 * @tc.require: SR000D4878
620 * @tc.author: fengxiaoyun
621 */
622 HWTEST_F(DistributeddbNbBackupTest, ImportTest003, TestSize.Level1)
623 {
624 const std::string importPath = DistributedDBConstant::NB_DIRECTOR + "export";
625 SetDir(importPath);
626 std::string filePath = importPath + "/bkpDB.bin";
627 EXPECT_EQ(g_nbBackupDelegate->Export(filePath, NULL_PASSWD), OK);
628
629 /**
630 * @tc.steps: step1. import a.txt in the right path.
631 * @tc.expected: step1. call failed and return INVALID_FILE.
632 */
633 std::string filePath1 = importPath + "/a.txt";
634 ofstream createFile(filePath1);
635 if (createFile) {
636 createFile << '1' << endl;
637 createFile.close();
638 }
639 EXPECT_EQ(g_nbBackupDelegate->Import(filePath1, NULL_PASSWD), INVALID_FILE);
640
641 /**
642 * @tc.steps: step2. write some data to DB file1.
643 * @tc.expected: step2. write successfully
644 */
645 ofstream damageFile(filePath, ios::out | ios::binary);
646 ASSERT_TRUE(damageFile.is_open());
647 damageFile.write(reinterpret_cast<char *>(&filePath), filePath.size());
648 damageFile.close();
649
650 /**
651 * @tc.steps: step3. import DB file with empty password.
652 * @tc.expected: step3. import failed and returned INVALID_FILE
653 */
654 EXPECT_EQ(g_nbBackupDelegate->Import(filePath, NULL_PASSWD), INVALID_FILE);
655 RemoveDir(importPath);
656 }
657
658 /*
659 * @tc.name: ImportTest 004
660 * @tc.desc: Verify that multi-DB can't import nb-DB backup file, and nb-DB can't import multi-DB backup file too.
661 * @tc.type: FUNC
662 * @tc.require: SR000D4878
663 * @tc.author: fengxiaoyun
664 */
665 HWTEST_F(DistributeddbNbBackupTest, ImportTest004, TestSize.Level1)
666 {
667 KvStoreDelegate *multiEncryptDelegate = nullptr;
668 KvStoreDelegateManager *multiEncryptManager = nullptr;
669
670 KvOption option = g_kvOption;
671 multiEncryptDelegate = DistributedTestTools::GetDelegateSuccess(multiEncryptManager, g_kvdbParameter2, option);
672 ASSERT_TRUE(multiEncryptManager != nullptr && multiEncryptDelegate != nullptr);
673 const std::string multiImportPath = DIRECTOR + "export";
674 SetDir(multiImportPath);
675 std::string multiFilePath1 = multiImportPath + "/bkpDB1.bin";
676 multiEncryptDelegate->Export(multiFilePath1, g_filePasswd1);
677
678 KvStoreDelegate *localDelegate = nullptr;
679 KvStoreDelegateManager *localManager = nullptr;
680 option.localOnly = true;
681 localDelegate = DistributedTestTools::GetDelegateSuccess(localManager, g_kvdbParameter3, option);
682 ASSERT_TRUE(localManager != nullptr && localDelegate != nullptr);
683
684 std::string multiFilePath2 = multiImportPath + "/bkpDB2.bin";
685 localDelegate->Export(multiFilePath2, g_filePasswd1);
686
687 const std::string nbImportPath = DistributedDBConstant::NB_DIRECTOR + "export";
688 SetDir(nbImportPath);
689 std::string nbFilePath = nbImportPath + "/bkpDB1.bin";
690 g_nbBackupDelegate->Export(nbFilePath, g_filePasswd1);
691 /**
692 * @tc.steps: step1. the multi DB1 import the nb DB backup file with the password f1.
693 * @tc.expected: step1. call failed and return INVALID_FILE.
694 */
695 EXPECT_EQ(multiEncryptDelegate->Import(nbFilePath, g_filePasswd1), INVALID_FILE);
696 /**
697 * @tc.steps: step2. the multi DB1 import backup file of local db with the password f1.
698 * @tc.expected: step2. call failed and return INVALID_FILE.
699 */
700 EXPECT_EQ(multiEncryptDelegate->Import(multiFilePath2, g_filePasswd1), INVALID_FILE);
701 /**
702 * @tc.steps: step3. the nb DB import the multi DB backup file with the password f1.
703 * @tc.expected: step3. call failed and return INVALID_FILE.
704 */
705 EXPECT_EQ(g_nbBackupDelegate->Import(multiFilePath1, g_filePasswd1), INVALID_FILE);
706 /**
707 * @tc.steps: step4. the nb DB import the noexsit nb DB backup file with the password f1.
708 * @tc.expected: step4. call failed and return INVALID_FILE.
709 */
710 EXPECT_EQ(g_nbBackupDelegate->Import(multiFilePath2, g_filePasswd1), INVALID_FILE);
711
712 /**
713 * @tc.steps: step5. Local DB import nb-backup file with the password f1.
714 * @tc.expected: step5. call failed and return INVALID_FILE.
715 */
716 EXPECT_EQ(localDelegate->Import(nbFilePath, g_filePasswd1), INVALID_FILE);
717 /**
718 * @tc.steps: step6. Local DB import multi-backup file with the password f1.
719 * @tc.expected: step6. call failed and return INVALID_FILE.
720 */
721 EXPECT_EQ(localDelegate->Import(multiFilePath1, g_filePasswd1), INVALID_FILE);
722 EXPECT_EQ(multiEncryptManager->CloseKvStore(multiEncryptDelegate), OK);
723 multiEncryptDelegate = nullptr;
724 EXPECT_EQ(multiEncryptManager->DeleteKvStore(STORE_ID_2), OK);
725 delete multiEncryptManager;
726 multiEncryptManager = nullptr;
727 EXPECT_EQ(localManager->CloseKvStore(localDelegate), OK);
728 localDelegate = nullptr;
729 EXPECT_EQ(localManager->DeleteKvStore(STORE_ID_3), OK);
730 delete localManager;
731 localManager = nullptr;
732 RemoveDir(multiImportPath);
733 RemoveDir(nbImportPath);
734 }
735
736 /*
737 * @tc.name: ImportTest 006
738 * @tc.desc: Verify that many kvstore of one DB or the DB registered observer can't import the backup file.
739 * @tc.type: FUNC
740 * @tc.require: SR000D4878
741 * @tc.author: fengxiaoyun
742 */
743 HWTEST_F(DistributeddbNbBackupTest, ImportTest006, TestSize.Level1)
744 {
745 const std::string importPath = DistributedDBConstant::NB_DIRECTOR + "export";
746 SetDir(importPath);
747 std::string filePath = importPath + "/bkpDB.bin";
748 EXPECT_EQ(g_nbBackupDelegate->Export(filePath, g_filePasswd1), OK);
749
750 /**
751 * @tc.steps: step1. create another delegate of the same storeId.
752 * @tc.expected: step1. create success.
753 */
754 KvStoreNbDelegate *delegate2 = nullptr;
755 KvStoreDelegateManager *manager2 = nullptr;
756 delegate2 = DistributedDBNbTestTools::GetNbDelegateSuccess(manager2, g_dbParameter1, g_option);
757 ASSERT_TRUE(manager2 != nullptr && delegate2 != nullptr);
758
759 /**
760 * @tc.steps: step2. use the second delegate to import the backup file.
761 * @tc.expected: step2. import failed and return busy
762 */
763 EXPECT_EQ(delegate2->Import(filePath, g_filePasswd1), BUSY);
764
765 EXPECT_TRUE(manager2->CloseKvStore(delegate2) == OK);
766 delegate2 = nullptr;
767 delete manager2;
768 manager2 = nullptr;
769 /**
770 * @tc.steps: step3. delegate1 register observer.
771 * @tc.expected: step3. register success
772 */
773 KvStoreObserverImpl observerSync;
774 EXPECT_EQ(g_nbBackupDelegate->RegisterObserver(KEY_1, OBSERVER_CHANGES_NATIVE, &observerSync), OK);
775 /**
776 * @tc.steps: step4. delegate1 import the backup file with the password f1.
777 * @tc.expected: step4. register success
778 */
779 EXPECT_EQ(g_nbBackupDelegate->Import(filePath, g_filePasswd1), BUSY);
780 RemoveDir(importPath);
781 }
782
783 /*
784 * @tc.name: ImportTest 007
785 * @tc.desc: Verify that the DB registered conflict notifier or hadn't resultSet can't import the backup file.
786 * @tc.type: FUNC
787 * @tc.require: SR000D4878
788 * @tc.author: fengxiaoyun
789 */
790 HWTEST_F(DistributeddbNbBackupTest, ImportTest007, TestSize.Level1)
791 {
792 const std::string importPath = DistributedDBConstant::NB_DIRECTOR + "export";
793 SetDir(importPath);
794 std::string filePath = importPath + "/bkpDB.bin";
795 EXPECT_EQ(g_nbBackupDelegate->Export(filePath, g_filePasswd1), OK);
796
797 /**
798 * @tc.steps: step1. register conflict notifier.
799 * @tc.expected: step1. register successfully.
800 */
801 ConflictNbCallback callback;
802 std::vector<ConflictData> conflictData;
803 auto notifier = bind(&ConflictNbCallback::NotifyCallBack, &callback, placeholders::_1, &conflictData);
804 EXPECT_EQ(g_nbBackupDelegate->SetConflictNotifier(CONFLICT_NATIVE_ALL, notifier), OK);
805 /**
806 * @tc.steps: step2. import the backup file with the password f1.
807 * @tc.expected: step2. import failed and returned BUSY.
808 */
809 EXPECT_EQ(g_nbBackupDelegate->Import(filePath, g_filePasswd1), BUSY);
810 EXPECT_EQ(g_nbBackupDelegate->SetConflictNotifier(CONFLICT_NATIVE_ALL, nullptr), OK);
811
812 /**
813 * @tc.steps: step3. call GetEntries to get resultSet.
814 * @tc.expected: step3. get successfully.
815 */
816 KvStoreResultSet *resultSet;
817 EXPECT_EQ(g_nbBackupDelegate->GetEntries(KEY_K, resultSet), OK);
818 /**
819 * @tc.steps: step4. import the backup file with the password f1.
820 * @tc.expected: step4. import failed and returned BUSY.
821 */
822 EXPECT_EQ(g_nbBackupDelegate->Import(filePath, g_filePasswd1), BUSY);
823 EXPECT_EQ(g_nbBackupDelegate->CloseResultSet(resultSet), OK);
824
825 RemoveDir(importPath);
826 }
827
828 #ifndef LOW_LEVEL_MEM_DEV
829 /*
830 * @tc.name: ImportTest 008
831 * @tc.desc: Verify that it will return busy when GetKvStore again or crud during it is importing.
832 * @tc.type: FUNC
833 * @tc.require: SR000D4878
834 * @tc.author: fengxiaoyun
835 */
836 HWTEST_F(DistributeddbNbBackupTest, ImportTest008, TestSize.Level3)
837 {
838 vector<Entry> entries;
839 std::vector<DistributedDB::Key> allKeys;
840 GenerateFixedRecords(entries, allKeys, FIFTY_RECORDS, KEY_SIX_BYTE, TWO_M_LONG_STRING);
841 for (auto iter = entries.begin(); iter != entries.end(); iter++) {
842 EXPECT_TRUE(g_nbBackupDelegate->Put(iter->key, iter->value) == OK);
843 }
844
845 const std::string importPath = DistributedDBConstant::NB_DIRECTOR + "export";
846 SetDir(importPath);
847 std::string filePath = importPath + "/bkpDB.bin";
848 EXPECT_EQ(g_nbBackupDelegate->Export(filePath, NULL_PASSWD), OK);
849
850 /**
851 * @tc.steps: step1. start subthread to import the backup file with empty password.
852 * @tc.expected: step1. start successfully if step1 running before step2, else return BUSY.
853 */
854 g_readyFlag.store(false);
__anonced11ad80902() 855 thread subThread([&filePath]() {
856 DBStatus importStatus = g_nbBackupDelegate->Import(filePath, NULL_PASSWD);
857 EXPECT_TRUE(importStatus == OK || importStatus == BUSY);
858 g_readyFlag.store(true);
859 g_backupVar.notify_one();
860 });
861 subThread.detach();
862
863 /**
864 * @tc.steps: step2. GetKvStore again during the subthread is importing.
865 * @tc.expected: step2. GetKvStore failed and returned BUSY if step1 is running, else return OK.
866 */
867 std::this_thread::sleep_for(std::chrono::microseconds(WAIT_FOR_LONG_TIME));
868 KvStoreDelegateManager *manager = nullptr;
869 DBStatus statusReturn;
870 DistributedDBNbTestTools::GetNbDelegateStatus(manager, statusReturn, g_dbParameter1, g_option);
871 EXPECT_TRUE(statusReturn == BUSY || statusReturn == OK);
872 /**
873 * @tc.steps: step3. put (k1, v1) during the subthread is importing.
874 * @tc.expected: step3. put failed and returned BUSY if step1 is running, else return OK.
875 */
876 statusReturn = g_nbBackupDelegate->Put(KEY_1, VALUE_1);
877 EXPECT_TRUE(statusReturn == BUSY || statusReturn == OK);
878 std::mutex rekeyMtx;
879 std::unique_lock<std::mutex> lck(rekeyMtx);
__anonced11ad80a02null880 g_backupVar.wait(lck, [&]{ return g_readyFlag.load(); });
881 RemoveDir(importPath);
882 }
883
884 #ifndef LOW_LEVEL_MEM_DEV
885 /*
886 * @tc.name: ImportTest 009
887 * @tc.desc: Verify that it will return busy when rekey during it is importing.
888 * @tc.type: FUNC
889 * @tc.require: SR000D4878
890 * @tc.author: fengxiaoyun
891 */
892 HWTEST_F(DistributeddbNbBackupTest, ImportTest009, TestSize.Level3)
893 {
894 vector<Entry> entriesRekey;
895 std::vector<DistributedDB::Key> allKeys;
896 GenerateFixedRecords(entriesRekey, allKeys, FIFTY_RECORDS, KEY_SIX_BYTE, FOUR_M_LONG_STRING);
897 for (auto iter = entriesRekey.begin(); iter != entriesRekey.end(); iter++) {
898 EXPECT_TRUE(g_nbBackupDelegate->Put(iter->key, iter->value) == OK);
899 }
900
901 const std::string importPath = DistributedDBConstant::NB_DIRECTOR + "export";
902 SetDir(importPath);
903 std::string filePath = importPath + "/bkpDB.bin";
904 EXPECT_EQ(g_nbBackupDelegate->Export(filePath, NULL_PASSWD), OK);
905
906 /**
907 * @tc.steps: step1. start subthread to import the backup file with empty password.
908 * @tc.expected: step1. start successfully if step1 running before step2, else return BUSY.
909 */
910 g_readyFlag.store(false);
__anonced11ad80b02() 911 thread subThread([&filePath]() {
912 DBStatus importStatus = g_nbBackupDelegate->Import(filePath, NULL_PASSWD);
913 EXPECT_TRUE(importStatus == OK || importStatus == BUSY);
914 g_readyFlag.store(true);
915 g_backupVar.notify_one();
916 });
917 subThread.detach();
918 /**
919 * @tc.steps: step2. rekey during the subthread is importing.
920 * @tc.expected: step2. rekey failed and returned BUSY if step1 is running, else return OK.
921 */
922 std::this_thread::sleep_for(std::chrono::microseconds(WAIT_FOR_LAST_SYNC));
923 DBStatus status = g_nbBackupDelegate->Rekey(g_passwd1);
924 EXPECT_TRUE(status == BUSY || status == OK);
925
926 std::mutex rekeyMtx;
927 std::unique_lock<std::mutex> lck(rekeyMtx);
__anonced11ad80c02null928 g_backupVar.wait(lck, [&]{ return g_readyFlag.load(); });
929 RemoveDir(importPath);
930 }
931 #endif
932
933 /*
934 * @tc.name: ImportTest 010
935 * @tc.desc: Verify that it will return busy when rekey during it is importing.
936 * @tc.type: FUNC
937 * @tc.require: SR000D4878
938 * @tc.author: fengxiaoyun
939 */
940 HWTEST_F(DistributeddbNbBackupTest, ImportTest010, TestSize.Level3)
941 {
942 vector<Entry> entriesRekey2;
943 std::vector<DistributedDB::Key> allKeys;
944 GenerateFixedRecords(entriesRekey2, allKeys, FIFTY_RECORDS, KEY_SIX_BYTE, TWO_M_LONG_STRING);
945 for (auto iter = entriesRekey2.begin(); iter != entriesRekey2.end(); iter++) {
946 EXPECT_TRUE(g_nbBackupDelegate->Put(iter->key, iter->value) == OK);
947 }
948
949 const std::string importPath = DistributedDBConstant::NB_DIRECTOR + "export";
950 SetDir(importPath);
951 std::string filePath = importPath + "/bkpDB.bin";
952 EXPECT_EQ(g_nbBackupDelegate->Export(filePath, NULL_PASSWD), OK);
953
954 /**
955 * @tc.steps: step1. start subthread to rekey DB with password 1.
956 * @tc.expected: step1. start successfully.
957 */
958 g_readyFlag.store(false);
__anonced11ad80d02() 959 thread subThread([]() {
960 EXPECT_EQ(g_nbBackupDelegate->Rekey(g_passwd1), OK);
961 g_readyFlag.store(true);
962 g_backupVar.notify_one();
963 });
964 subThread.detach();
965 /**
966 * @tc.steps: step2. import the backup file during the subthread is rekeying.
967 * @tc.expected: step2. import failed and returned BUSY.
968 */
969 std::this_thread::sleep_for(std::chrono::microseconds(WAIT_FOR_LAST_SYNC));
970 EXPECT_EQ(g_nbBackupDelegate->Import(filePath, NULL_PASSWD), BUSY);
971
972 std::mutex rekeyMtx;
973 std::unique_lock<std::mutex> lck(rekeyMtx);
__anonced11ad80e02null974 g_backupVar.wait(lck, [&]{ return g_readyFlag.load(); });
975 RemoveDir(importPath);
976 }
977 #endif
978
979 /*
980 * @tc.name: ImportTest 011
981 * @tc.desc: Verify that it will allow to import backup file again during it is importing.
982 * @tc.type: FUNC
983 * @tc.require: SR000D4878
984 * @tc.author: fengxiaoyun
985 */
986 HWTEST_F(DistributeddbNbBackupTest, ImportTest011, TestSize.Level3)
987 {
988 vector<Entry> entriesReImport;
989 std::vector<DistributedDB::Key> allKeys;
990 GenerateFixedRecords(entriesReImport, allKeys, TEN_RECORDS, KEY_SIX_BYTE, FOUR_M_LONG_STRING);
991 for (auto iter = entriesReImport.begin(); iter != entriesReImport.end(); iter++) {
992 EXPECT_TRUE(g_nbBackupDelegate->Put(iter->key, iter->value) == OK);
993 }
994
995 const std::string importPath = DistributedDBConstant::NB_DIRECTOR + "export";
996 SetDir(importPath);
997 std::string filePath = importPath + "/bkpDB.bin";
998 EXPECT_EQ(g_nbBackupDelegate->Export(filePath, NULL_PASSWD), OK);
999
1000 /**
1001 * @tc.steps: step1. start subthread to import the backup file.
1002 * @tc.expected: step1. start successfully.
1003 */
1004 g_readyFlag.store(false);
__anonced11ad80f02() 1005 thread subThread([&filePath]() {
1006 EXPECT_EQ(g_nbBackupDelegate->Import(filePath, NULL_PASSWD), OK);
1007 g_readyFlag.store(true);
1008 g_backupVar.notify_one();
1009 });
1010 subThread.detach();
1011 /**
1012 * @tc.steps: step2. import the backup file during the subthread is importing with empty password.
1013 * @tc.expected: step2. import successfully and return OK.
1014 */
1015 EXPECT_EQ(g_nbBackupDelegate->Import(filePath, NULL_PASSWD), OK);
1016
1017 std::mutex rekeyMtx;
1018 std::unique_lock<std::mutex> lck(rekeyMtx);
__anonced11ad81002null1019 g_backupVar.wait(lck, [&]{ return g_readyFlag.load(); });
1020
1021 RemoveDir(importPath);
1022 }
1023
NbSubImportThread(int index,std::string importPath)1024 void NbSubImportThread(int index, std::string importPath)
1025 {
1026 vector<Entry> tenEntries;
1027 std::vector<DistributedDB::Key> allKeys;
1028 GenerateFixedRecords(tenEntries, allKeys, FIVE_RECORDS, KEY_SIX_BYTE, FOUR_M_LONG_STRING);
1029 /**
1030 * @tc.steps: step1. every thread create one DB put 10 entries into the DB.
1031 * @tc.expected: step1. put successfully.
1032 */
1033 KvStoreNbDelegate *delegate2 = nullptr;
1034 KvStoreDelegateManager *manager2 = nullptr;
1035 DBParameters parameter[] = {g_dbParameter2, g_dbParameter3, g_dbParameter4, g_dbParameter5, g_dbParameter6};
1036 Option option[] = {g_createDiskUnencrypted, g_createDiskUnencrypted, g_createDiskUnencrypted,
1037 g_createDiskEncrypted, g_createDiskEncrypted};
1038 delegate2 = DistributedDBNbTestTools::GetNbDelegateSuccess(manager2, parameter[index], option[index]);
1039 ASSERT_TRUE(manager2 != nullptr && delegate2 != nullptr);
1040
1041 for (auto iter = tenEntries.begin(); iter != tenEntries.end(); iter++) {
1042 EXPECT_TRUE(delegate2->Put(iter->key, iter->value) == OK);
1043 }
1044
1045 /**
1046 * @tc.steps: step2. every thread export DB to backup file.
1047 * @tc.expected: step2. export successfully.
1048 */
1049 DistributedDB::CipherPassword passwd[] = {NULL_PASSWD, NULL_PASSWD, NULL_PASSWD, g_filePasswd1, g_filePasswd2};
1050
1051 const std::string backupFile[] = {"/bkpDB1.bin", "/bkpDB2.bin", "/bkpDB3.bin", "/bkpDB4.bin", "/bkpDB5.bin"};
1052 std::string nbFilePath[] = {(importPath + backupFile[INDEX_ZEROTH]), (importPath + backupFile[INDEX_FIRST]),
1053 (importPath + backupFile[INDEX_SECOND]), (importPath + backupFile[INDEX_THIRD]),
1054 (importPath + backupFile[INDEX_FORTH])};
1055 delegate2->Export(nbFilePath[index], passwd[index]);
1056
1057 /**
1058 * @tc.steps: step3. every thread import backup file to DB.
1059 * @tc.expected: step3. import successfully.
1060 */
1061 EXPECT_EQ(delegate2->Import(nbFilePath[index], passwd[index]), OK);
1062 EXPECT_EQ(manager2->CloseKvStore(delegate2), OK);
1063 delegate2 = nullptr;
1064 std::string storeId[] = {STORE_ID_2, STORE_ID_3, STORE_ID_4, STORE_ID_5, STORE_ID_6};
1065 EXPECT_TRUE(manager2->DeleteKvStore(storeId[index]) == OK);
1066 for (auto &password : passwd) {
1067 password.Clear();
1068 }
1069 delete manager2;
1070 manager2 = nullptr;
1071 }
1072
1073 /*
1074 * @tc.name: ImportTest 012
1075 * @tc.desc: Verify that different DB export and import in the same time won't affect each other.
1076 * @tc.type: FUNC
1077 * @tc.require: SR000D4878
1078 * @tc.author: fengxiaoyun
1079 */
1080 HWTEST_F(DistributeddbNbBackupTest, ImportTest012, TestSize.Level3)
1081 {
1082 std::vector<std::thread> threads;
1083 const std::string importPath = DistributedDBConstant::NB_DIRECTOR + "export";
1084 SetDir(importPath);
1085 for (int index = 0; index < FIVE_TIMES; ++index) {
1086 threads.push_back(std::thread(NbSubImportThread, index, std::ref(importPath)));
1087 }
1088
1089 for (auto& th : threads) {
1090 th.join();
1091 }
1092 RemoveDir(importPath);
1093 }
1094
1095 /*
1096 * @tc.name: Exchange 001
1097 * @tc.desc: whether current db is encrypted or not, import file need to use exported password(or NULL_PASSWD).
1098 * @tc.type: FUNC
1099 * @tc.require: SR000D4878
1100 * @tc.author: fengxiaoyun
1101 */
1102 HWTEST_F(DistributeddbNbBackupTest, Exchange001, TestSize.Level1)
1103 {
1104 const std::string exportPath = DistributedDBConstant::NB_DIRECTOR + "export";
1105 SetDir(exportPath);
1106 std::string filePath1 = exportPath + "/bkpDB1.bin";
1107 std::string filePath2 = exportPath + "/bkpDB2.bin";
1108 /**
1109 * @tc.steps: step1. export data as "bkpDB1.bin" with passwd g_filePasswd1 and "bkpDB2.bin" with NULL_PASSWD.
1110 * @tc.expected: step1. call successfully.
1111 */
1112 EXPECT_EQ(g_nbBackupDelegate->Export(filePath1, g_filePasswd1), OK);
1113 EXPECT_EQ(g_nbBackupDelegate->Export(filePath2, NULL_PASSWD), OK);
1114 /**
1115 * @tc.steps: step2. import "bkpDB1.bin" and "bkpDB2.bin" with NULL_PASSWD.
1116 * @tc.expected: step2. import "bkpDB1.bin" failed and import "bkpDB2.bin" succeeded.
1117 */
1118 EXPECT_EQ(g_nbBackupDelegate->Import(filePath1, NULL_PASSWD), INVALID_FILE);
1119 EXPECT_EQ(g_nbBackupDelegate->Import(filePath2, NULL_PASSWD), OK);
1120 /**
1121 * @tc.steps: step3. import "bkpDB1.bin" and "bkpDB2.bin" with g_filePasswd1.
1122 * @tc.expected: step3. import "bkpDB1.bin" succeeded and import "bkpDB2.bin" failed.
1123 */
1124 EXPECT_EQ(g_nbBackupDelegate->Import(filePath1, g_filePasswd1), OK);
1125 EXPECT_EQ(g_nbBackupDelegate->Import(filePath2, g_filePasswd1), INVALID_FILE);
1126 /**
1127 * @tc.steps: step4. rekey db1 with g_passwd1, and then import "bkpDB1.bin" and "bkpDB2.bin" with p1.
1128 * @tc.expected: step4. rekey succeeded and import failed.
1129 */
1130 EXPECT_EQ(g_nbBackupDelegate->Rekey(g_passwd1), OK);
1131 EXPECT_EQ(g_nbBackupDelegate->Import(filePath1, g_passwd1), INVALID_FILE);
1132 EXPECT_EQ(g_nbBackupDelegate->Import(filePath2, g_passwd1), INVALID_FILE);
1133 /**
1134 * @tc.steps: step5. import "bkpDB1.bin" and "bkpDB2.bin" with g_filePasswd1.
1135 * @tc.expected: step5. import "bkpDB1.bin" succeeded and import "bkpDB2.bin" failed.
1136 */
1137 EXPECT_EQ(g_nbBackupDelegate->Import(filePath1, g_filePasswd1), OK);
1138 EXPECT_EQ(g_nbBackupDelegate->Import(filePath2, g_filePasswd1), INVALID_FILE);
1139 /**
1140 * @tc.steps: step6. import "bkpDB1.bin" and "bkpDB2.bin" with NULL_PASSWD.
1141 * @tc.expected: step6. import "bkpDB1.bin" failed and import "bkpDB2.bin" succeeded.
1142 */
1143 EXPECT_EQ(g_nbBackupDelegate->Import(filePath1, NULL_PASSWD), INVALID_FILE);
1144 EXPECT_EQ(g_nbBackupDelegate->Import(filePath2, NULL_PASSWD), OK);
1145 RemoveDir(exportPath);
1146 }
1147
1148 /*
1149 * @tc.name: Exchange 002
1150 * @tc.desc: whether current db is encrypted or not, import file need to use exported password(or NULL_PASSWD).
1151 * @tc.type: FUNC
1152 * @tc.require: SR000D4878
1153 * @tc.author: fengxiaoyun
1154 */
1155 HWTEST_F(DistributeddbNbBackupTest, Exchange002, TestSize.Level1)
1156 {
1157 const std::string exportPath = DistributedDBConstant::NB_DIRECTOR + "export";
1158 SetDir(exportPath);
1159 std::string filePath1 = exportPath + "/bkpDB1.bin";
1160 std::string filePath2 = exportPath + "/bkpDB2.bin";
1161 /**
1162 * @tc.steps: step1. rekey db1 with g_passwd1,
1163 * export data as "bkpDB1.bin" with passwd g_filePasswd1 and "bkpDB2.bin" with NULL_PASSWD.
1164 * @tc.expected: step1. call successfully.
1165 */
1166 EXPECT_EQ(g_nbBackupDelegate->Rekey(g_passwd1), OK);
1167 EXPECT_EQ(g_nbBackupDelegate->Export(filePath1, g_filePasswd1), OK);
1168 EXPECT_EQ(g_nbBackupDelegate->Export(filePath2, NULL_PASSWD), OK);
1169 /**
1170 * @tc.steps: step2. import "bkpDB1.bin" and "bkpDB2.bin" with NULL_PASSWD.
1171 * @tc.expected: step2. import "bkpDB1.bin" failed and import "bkpDB2.bin" succeeded.
1172 */
1173 EXPECT_EQ(g_nbBackupDelegate->Import(filePath1, NULL_PASSWD), INVALID_FILE);
1174 EXPECT_EQ(g_nbBackupDelegate->Import(filePath2, NULL_PASSWD), OK);
1175 /**
1176 * @tc.steps: step3. import "bkpDB1.bin" and "bkpDB2.bin" with g_passwd1.
1177 * @tc.expected: step3. rekey succeeded and import failed.
1178 */
1179 EXPECT_EQ(g_nbBackupDelegate->Import(filePath1, g_passwd1), INVALID_FILE);
1180 EXPECT_EQ(g_nbBackupDelegate->Import(filePath2, g_passwd1), INVALID_FILE);
1181 /**
1182 * @tc.steps: step4. import "bkpDB1.bin" and "bkpDB2.bin" with g_filePasswd1.
1183 * @tc.expected: step4. import "bkpDB1.bin" succeeded and import "bkpDB2.bin" failed.
1184 */
1185 EXPECT_EQ(g_nbBackupDelegate->Import(filePath1, g_filePasswd1), OK);
1186 EXPECT_EQ(g_nbBackupDelegate->Import(filePath2, g_filePasswd1), INVALID_FILE);
1187 /**
1188 * @tc.steps: step5. rekey db1 with NULL_PASSWD,
1189 * import "bkpDB1.bin" and "bkpDB2.bin" with NULL_PASSWD.
1190 * @tc.expected: step5. import "bkpDB1.bin" failed and import "bkpDB2.bin" succeeded.
1191 */
1192 EXPECT_EQ(g_nbBackupDelegate->Rekey(NULL_PASSWD), OK);
1193 EXPECT_EQ(g_nbBackupDelegate->Import(filePath1, NULL_PASSWD), INVALID_FILE);
1194 EXPECT_EQ(g_nbBackupDelegate->Import(filePath2, NULL_PASSWD), OK);
1195 /**
1196 * @tc.steps: step6. import "bkpDB1.bin" and "bkpDB2.bin" with g_filePasswd1.
1197 * @tc.expected: step6. import "bkpDB1.bin" succeeded and import "bkpDB2.bin" failed.
1198 */
1199 EXPECT_EQ(g_nbBackupDelegate->Import(filePath1, g_filePasswd1), OK);
1200 EXPECT_EQ(g_nbBackupDelegate->Import(filePath2, g_filePasswd1), INVALID_FILE);
1201 RemoveDir(exportPath);
1202 }
1203
1204 /*
1205 * @tc.name: Exchange 003
1206 * @tc.desc: whether current db is encrypted or not, import file need to use exported password(or NULL_PASSWD).
1207 * @tc.type: FUNC
1208 * @tc.require: SR000D4878
1209 * @tc.author: fengxiaoyun
1210 */
1211 HWTEST_F(DistributeddbNbBackupTest, Exchange003, TestSize.Level1)
1212 {
1213 const std::string exportPath = DistributedDBConstant::NB_DIRECTOR + "export";
1214 SetDir(exportPath);
1215 std::string filePath1 = exportPath + "/bkpDB1.bin";
1216 std::string filePath2 = exportPath + "/bkpDB2.bin";
1217 /**
1218 * @tc.steps: step1. rekey db1 with g_passwd1,
1219 * export data as "bkpDB1.bin" with passwd g_filePasswd1 and "bkpDB2.bin" with NULL_PASSWD.
1220 * @tc.expected: step1. call successfully.
1221 */
1222 EXPECT_EQ(g_nbBackupDelegate->Rekey(g_passwd1), OK);
1223 EXPECT_EQ(g_nbBackupDelegate->Export(filePath1, g_filePasswd1), OK);
1224 EXPECT_EQ(g_nbBackupDelegate->Export(filePath2, NULL_PASSWD), OK);
1225 /**
1226 * @tc.steps: step2. rekey db1 with g_passwd2,
1227 * import "bkpDB1.bin" and "bkpDB2.bin" with NULL_PASSWD.
1228 * @tc.expected: step2. import "bkpDB1.bin" failed and import "bkpDB2.bin" succeeded.
1229 */
1230 EXPECT_EQ(g_nbBackupDelegate->Rekey(g_passwd2), OK);
1231 EXPECT_EQ(g_nbBackupDelegate->Import(filePath1, NULL_PASSWD), INVALID_FILE);
1232 EXPECT_EQ(g_nbBackupDelegate->Import(filePath2, NULL_PASSWD), OK);
1233 /**
1234 * @tc.steps: step3. Put (k1,v1), close db, open db with g_passwd2 and delete (k1,v1)
1235 * @tc.expected: step3. operate successfully.
1236 */
1237 EXPECT_EQ(g_nbBackupDelegate->Put(KEY_1, VALUE_1), OK);
1238 EXPECT_EQ((g_manager->CloseKvStore(g_nbBackupDelegate)), OK);
1239 g_nbBackupDelegate = nullptr;
1240 delete g_manager;
1241 g_manager = nullptr;
1242 Option encrypted(true, false, true, DistributedDB::CipherType::DEFAULT, PASSWD_VECTOR_2);
1243 g_nbBackupDelegate = DistributedDBNbTestTools::GetNbDelegateSuccess(g_manager, g_dbParameter1, encrypted);
1244 ASSERT_TRUE(g_manager != nullptr && g_nbBackupDelegate != nullptr);
1245 EXPECT_EQ(g_nbBackupDelegate->Delete(KEY_1), OK);
1246 /**
1247 * @tc.steps: step4. import "bkpDB1.bin" and "bkpDB2.bin" with g_passwd1.
1248 * @tc.expected: step4. import failed.
1249 */
1250 EXPECT_EQ(g_nbBackupDelegate->Import(filePath1, g_passwd1), INVALID_FILE);
1251 EXPECT_EQ(g_nbBackupDelegate->Import(filePath2, g_passwd1), INVALID_FILE);
1252 /**
1253 * @tc.steps: step5. import "bkpDB1.bin" and "bkpDB2.bin" with g_passwd2.
1254 * @tc.expected: step5. import failed.
1255 */
1256 EXPECT_EQ(g_nbBackupDelegate->Import(filePath1, g_passwd2), INVALID_FILE);
1257 EXPECT_EQ(g_nbBackupDelegate->Import(filePath2, g_passwd2), INVALID_FILE);
1258 /**
1259 * @tc.steps: step6. import "bkpDB1.bin" and "bkpDB2.bin" with g_filePasswd1.
1260 * @tc.expected: step6. import "bkpDB1.bin" succeeded and import "bkpDB2.bin" failed.
1261 */
1262 EXPECT_EQ(g_nbBackupDelegate->Import(filePath1, g_filePasswd1), OK);
1263 EXPECT_EQ(g_nbBackupDelegate->Import(filePath2, g_filePasswd1), INVALID_FILE);
1264 /**
1265 * @tc.steps: step7. Put (k2,v2), close db, open db with g_passwd2 and delete (k2,v2)
1266 * @tc.expected: step7. operate successfully.
1267 */
1268 EXPECT_EQ(g_nbBackupDelegate->Put(KEY_2, VALUE_2), OK);
1269 EXPECT_EQ((g_manager->CloseKvStore(g_nbBackupDelegate)), OK);
1270 g_nbBackupDelegate = nullptr;
1271 delete g_manager;
1272 g_manager = nullptr;
1273 g_nbBackupDelegate = DistributedDBNbTestTools::GetNbDelegateSuccess(g_manager, g_dbParameter1, encrypted);
1274 ASSERT_TRUE(g_manager != nullptr && g_nbBackupDelegate != nullptr);
1275 EXPECT_EQ(g_nbBackupDelegate->Delete(KEY_2), OK);
1276 RemoveDir(exportPath);
1277 }
1278
1279 /*
1280 * @tc.name: CorruptionHandler 001
1281 * @tc.desc: Verify that the Corruption Handler can be set only one, if set many times, the last one is valid.
1282 * @tc.type: FUNC
1283 * @tc.require: SR000D4878
1284 * @tc.author: fengxiaoyun
1285 */
1286 HWTEST_F(DistributeddbNbBackupTest, CorruptionHandler001, TestSize.Level1)
1287 {
1288 EXPECT_TRUE(g_nbBackupDelegate->Put(KEY_1, VALUE_1) == OK);
1289 const std::string exportPath = DistributedDBConstant::NB_DIRECTOR + "export";
1290 SetDir(exportPath);
1291 std::string filePath = exportPath + "/bkpDB.bin";
1292 EXPECT_TRUE(g_nbBackupDelegate->Export(filePath, NULL_PASSWD) == OK);
1293 EXPECT_TRUE(g_nbBackupDelegate->Delete(KEY_1) == OK);
1294
1295 /**
1296 * @tc.steps: step1. device A call SetKvStoreCorruptionHandler.
1297 * @tc.expected: step1. call successfully.
1298 */
1299 KvStoreNbCorruptInfo corruptInfo;
1300 KvStoreNbCorruptInfo corruptInfoNew;
1301 bool isCalled = false;
1302 auto notifier = bind(&KvStoreNbCorruptInfo::CorruptCallBack, &corruptInfo,
1303 placeholders::_1, placeholders::_2, placeholders::_3, std::ref(isCalled));
1304 g_manager->SetKvStoreCorruptionHandler(notifier);
1305 /**
1306 * @tc.steps: step2. device A call SetKvStoreCorruptionHandler the second time.
1307 * @tc.expected: step2. call successfully.
1308 */
1309 CallBackParam pathResult = {filePath, true};
1310 auto notifierNew = bind(&KvStoreNbCorruptInfo::CorruptNewCallBack, &corruptInfoNew,
1311 placeholders::_1, placeholders::_2, placeholders::_3, std::ref(g_manager), pathResult);
1312 g_manager->SetKvStoreCorruptionHandler(notifierNew);
1313 EXPECT_TRUE(pathResult.result);
1314 /**
1315 * @tc.steps: step3. make file corrupted and call GetKvStore to trigger callback function.
1316 * @tc.expected: step3. call successfully.
1317 */
1318 EXPECT_EQ((g_manager->CloseKvStore(g_nbBackupDelegate)), OK);
1319 g_nbBackupDelegate = nullptr;
1320 std::string dbFliePath = DistributedDBNbTestTools::GetKvNbStoreDirectory(g_dbParameter1);
1321 EXPECT_TRUE(DistributedDBNbTestTools::ModifyDatabaseFile(dbFliePath));
1322 DBStatus status;
1323 KvStoreDelegateManager *manager = nullptr;
1324 EXPECT_EQ(DistributedDBNbTestTools::GetNbDelegateStatus(manager, status, g_dbParameter1, g_option), nullptr);
1325 EXPECT_EQ(status, INVALID_PASSWD_OR_CORRUPTED_DB);
1326 /**
1327 * @tc.steps: step4. open db and Get(k1) to verify importing in callback is successful.
1328 * @tc.expected: step4. Get(k1)=v1.
1329 */
1330 g_nbBackupDelegate = DistributedDBNbTestTools::GetNbDelegateSuccess(g_manager, g_dbParameter1, g_option);
1331 ASSERT_TRUE(g_manager != nullptr && g_nbBackupDelegate != nullptr);
1332 Value valueResult;
1333 EXPECT_TRUE(g_nbBackupDelegate->Get(KEY_1, valueResult) == OK);
1334 EXPECT_EQ(valueResult, VALUE_1);
1335 g_manager->SetKvStoreCorruptionHandler(nullptr);
1336 RemoveDir(exportPath);
1337 }
1338
1339 /*
1340 * @tc.name: CorruptionHandler 002
1341 * @tc.desc: Verify that can import db files and can't export in the Corruption Handler callback when db files
1342 * are corrupted in using.
1343 * @tc.type: FUNC
1344 * @tc.require: SR000D4878
1345 * @tc.author: fengxiaoyun
1346 */
1347 HWTEST_F(DistributeddbNbBackupTest, CorruptionHandler002, TestSize.Level2)
1348 {
1349 EXPECT_TRUE(g_nbBackupDelegate->Put(KEY_1, VALUE_1) == OK);
1350 const std::string exportPath = DistributedDBConstant::NB_DIRECTOR + "export";
1351 SetDir(exportPath);
1352 std::string filePath = exportPath + "/bkpDB.bin";
1353 EXPECT_TRUE(g_nbBackupDelegate->Export(filePath, g_filePasswd1) == OK);
1354
1355 /**
1356 * @tc.steps: step1. device A call SetKvStoreCorruptionHandler to register CorruptCallBackOfImport.
1357 * @tc.expected: step1. call successfully.
1358 */
1359 KvStoreNbCorruptInfo corruptInfo;
1360 CallBackParam pathResult = {filePath, true};
1361 auto notifier = bind(&KvStoreNbCorruptInfo::CorruptCallBackOfImport, &corruptInfo,
1362 placeholders::_1, placeholders::_2, placeholders::_3, g_nbBackupDelegate, pathResult);
1363 g_manager->SetKvStoreCorruptionHandler(notifier);
1364 EXPECT_TRUE(pathResult.result);
1365 /**
1366 * @tc.steps: step2. device A modify the db files to trigger the CorruptCallBackOfImport and check.
1367 * @tc.expected: step2. operate successfully and import the recover db files in callback successfully.
1368 */
1369 EXPECT_TRUE(g_nbBackupDelegate->Delete(KEY_1) == OK);
1370 std::string dbFliePath = DistributedDBNbTestTools::GetKvNbStoreDirectory(g_dbParameter1);
1371 EXPECT_TRUE(DistributedDBNbTestTools::ModifyDatabaseFile(dbFliePath));
1372 EXPECT_TRUE(DistributedDBNbTestTools::ModifyDatabaseFile(dbFliePath + "-wal"));
1373 EXPECT_EQ(g_nbBackupDelegate->Put(KEY_1, VALUE_1), INVALID_PASSWD_OR_CORRUPTED_DB);
1374 std::this_thread::sleep_for(std::chrono::seconds(UNIQUE_SECOND)); // wait for callback complete for 1 second.
1375 Value valueResult;
1376 EXPECT_TRUE(g_nbBackupDelegate->Get(KEY_1, valueResult) == OK);
1377 EXPECT_EQ(valueResult, VALUE_1);
1378
1379 /**
1380 * @tc.steps: step3. device A call SetKvStoreCorruptionHandler again to register CorruptCallBackOfExport.
1381 * @tc.expected: step3. call successfully.
1382 */
1383 filePath = exportPath + "/bkpDB1.bin";
1384 auto notifierNew = bind(&KvStoreNbCorruptInfo::CorruptCallBackOfExport, &corruptInfo,
1385 placeholders::_1, placeholders::_2, placeholders::_3, g_nbBackupDelegate, pathResult);
1386 g_manager->SetKvStoreCorruptionHandler(notifierNew);
1387 EXPECT_TRUE(pathResult.result);
1388
1389 /**
1390 * @tc.steps: step4. device A modify the db files to trigger the CorruptCallBackOfExport and check.
1391 * @tc.expected: step4. operate successfully and export the recover db data in callback failed.
1392 */
1393 EXPECT_TRUE(DistributedDBNbTestTools::ModifyDatabaseFile(dbFliePath));
1394 EXPECT_EQ(g_nbBackupDelegate->Put(KEY_1, VALUE_1), INVALID_PASSWD_OR_CORRUPTED_DB);
1395 g_manager->SetKvStoreCorruptionHandler(nullptr);
1396 RemoveDir(exportPath);
1397 }
1398
1399 /*
1400 * @tc.name: CorruptionHandler 003
1401 * @tc.desc: Verify that if call SetKvStoreCorruptionHandler(nullptr) will unregister the Corruption Handler.
1402 * @tc.type: FUNC
1403 * @tc.require: SR000D4878
1404 * @tc.author: fengxiaoyun
1405 */
1406 HWTEST_F(DistributeddbNbBackupTest, CorruptionHandler003, TestSize.Level2)
1407 {
1408 EXPECT_TRUE(g_nbBackupDelegate->Put(KEY_1, VALUE_1) == OK);
1409 const std::string exportPath = DistributedDBConstant::NB_DIRECTOR + "export";
1410 SetDir(exportPath);
1411 std::string filePath = exportPath + "/bkpDB.bin";
1412 EXPECT_TRUE(g_nbBackupDelegate->Export(filePath, g_filePasswd1) == OK);
1413
1414 /**
1415 * @tc.steps: step1. device A's db1 call SetKvStoreCorruptionHandler to register CorruptCallBack.
1416 * @tc.expected: step1. call successfully.
1417 */
1418 KvStoreNbCorruptInfo corruptInfo;
1419 bool isCalled = false;
1420 auto notifier = bind(&KvStoreNbCorruptInfo::CorruptCallBack, &corruptInfo,
1421 placeholders::_1, placeholders::_2, placeholders::_3, std::ref(isCalled));
1422 g_manager->SetKvStoreCorruptionHandler(notifier);
1423
1424 /**
1425 * @tc.steps: step2. device A's db2 call SetKvStoreCorruptionHandler to register CorruptCallBackOfImport.
1426 * @tc.expected: step2. call successfully.
1427 */
1428 KvStoreDelegateManager *manager = nullptr;
1429 KvStoreNbDelegate *delegate = nullptr;
1430 delegate = DistributedDBNbTestTools::GetNbDelegateSuccess(manager, g_dbParameter2, g_option);
1431 ASSERT_TRUE(manager != nullptr && delegate != nullptr);
1432 KvStoreNbCorruptInfo corruptInfoNew;
1433 CallBackParam pathResult = {filePath, true};
1434 auto notifierNew = bind(&KvStoreNbCorruptInfo::CorruptCallBackOfImport, &corruptInfoNew,
1435 placeholders::_1, placeholders::_2, placeholders::_3, g_nbBackupDelegate, pathResult);
1436 manager->SetKvStoreCorruptionHandler(notifierNew);
1437 EXPECT_TRUE(pathResult.result);
1438
1439 /**
1440 * @tc.steps: step3. device A modify the db files to trigger the CorruptCallBackOfImport and check.
1441 * @tc.expected: step3. operate successfully and import the recover db files in callback successfully.
1442 */
1443 std::string dbFliePath = DistributedDBNbTestTools::GetKvNbStoreDirectory(g_dbParameter1);
1444 EXPECT_TRUE(DistributedDBNbTestTools::ModifyDatabaseFile(dbFliePath));
1445 EXPECT_TRUE(DistributedDBNbTestTools::ModifyDatabaseFile(dbFliePath + "-wal"));
1446 EXPECT_EQ(g_nbBackupDelegate->Put(KEY_1, VALUE_1), INVALID_PASSWD_OR_CORRUPTED_DB);
1447 std::this_thread::sleep_for(std::chrono::seconds(TWO_SECONDS)); // wait for callback complete for 1 second.
1448 Value valueResult;
1449 EXPECT_EQ(g_nbBackupDelegate->Get(KEY_1, valueResult), OK);
1450 EXPECT_EQ(valueResult, VALUE_1);
1451
1452 /**
1453 * @tc.steps: step4. device A call SetKvStoreCorruptionHandler again to register nullptr.
1454 * @tc.expected: step4. call successfully.
1455 */
1456 manager->SetKvStoreCorruptionHandler(nullptr);
1457
1458 /**
1459 * @tc.steps: step5. device A modify the db files to trigger the CorruptCallBack and check.
1460 * @tc.expected: step5. put return error but trigger the CorruptCallBack failed.
1461 */
1462 EXPECT_TRUE(delegate->Put(KEY_1, VALUE_1) == OK);
1463 dbFliePath = DistributedDBNbTestTools::GetKvNbStoreDirectory(g_dbParameter2);
1464 EXPECT_TRUE(DistributedDBNbTestTools::ModifyDatabaseFile(dbFliePath));
1465 EXPECT_TRUE(DistributedDBNbTestTools::ModifyDatabaseFile(dbFliePath + "-wal"));
1466 EXPECT_EQ(delegate->Put(KEY_1, VALUE_1), INVALID_PASSWD_OR_CORRUPTED_DB);
1467 std::this_thread::sleep_for(std::chrono::seconds(UNIQUE_SECOND)); // wait for callback complete for 1 second.
1468 EXPECT_EQ(delegate->Get(KEY_1, valueResult), INVALID_PASSWD_OR_CORRUPTED_DB);
1469
1470 EXPECT_EQ((manager->CloseKvStore(delegate)), OK);
1471 delegate = nullptr;
1472 manager->DeleteKvStore(STORE_ID_2);
1473 delete manager;
1474 manager = nullptr;
1475 RemoveDir(exportPath);
1476 }
1477 #ifndef RUNNING_ON_SIMULATED_ENV
1478 /*
1479 * @tc.name: CompatibilityTest 001
1480 * @tc.desc: test that use RELEASE_VERSION11.0.0 can import the export file by RELEASE_VERSION10.1.0.
1481 * @tc.type: Compatibility
1482 * @tc.require: SR000EPA24
1483 * @tc.author: fengxiaoyun
1484 */
1485 #ifdef NB_BACKUP
1486 HWTEST_F(DistributeddbNbBackupTest, CompatibilityTest001, TestSize.Level3)
1487 {
1488 const std::string exportPath = "/data/";
1489 std::string filePath = exportPath + "/RELEASE_VERSION1010.bin";
1490 #define COMPATIBILITYTEST_001
1491 #ifndef COMPATIBILITYTEST_001
1492 /**
1493 * @tc.steps: step1. create the db and put some data then export in RELEASE_VERSION10.1.0.
1494 * @tc.expected: step1. operate successfully.
1495 */
1496 EXPECT_TRUE(g_nbBackupDelegate->PutLocal(KEY_1, VALUE_1) == OK);
1497 EXPECT_TRUE(g_nbBackupDelegate->Put(KEY_1, VALUE_1) == OK);
1498 EXPECT_TRUE(g_nbBackupDelegate->PutLocal(KEY_2, VALUE_1) == OK);
1499 EXPECT_TRUE(g_nbBackupDelegate->Put(KEY_2, VALUE_2) == OK);
1500 EXPECT_TRUE(g_nbBackupDelegate->Delete(KEY_2) == OK);
1501 EXPECT_TRUE(g_nbBackupDelegate->Export(filePath, NULL_PASSWD) == OK);
1502 #else
1503 /**
1504 * @tc.steps: step2. import the export file by step1 and check data.
1505 * @tc.expected: step2. import successfully.
1506 */
1507 EXPECT_TRUE(g_nbBackupDelegate->Import(filePath, NULL_PASSWD) == OK);
1508 Value resultValue;
1509 EXPECT_TRUE(g_nbBackupDelegate->GetLocal(KEY_1, resultValue) == OK);
1510 EXPECT_TRUE(resultValue == VALUE_1);
1511 EXPECT_TRUE(g_nbBackupDelegate->GetLocal(KEY_2, resultValue) == OK);
1512 EXPECT_TRUE(resultValue == VALUE_1);
1513 EXPECT_TRUE(g_nbBackupDelegate->Get(KEY_1, resultValue) == OK);
1514 EXPECT_TRUE(resultValue == VALUE_1);
1515 EXPECT_TRUE(g_nbBackupDelegate->Get(KEY_2, resultValue) == NOT_FOUND);
1516 #endif
1517 }
1518 #endif
1519 #endif
1520 }
1521