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 DB_DEBUG_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);
__anonf63d79d80102() 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);
__anonf63d79d80202null271 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);
__anonf63d79d80302() 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);
__anonf63d79d80402null325 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);
__anonf63d79d80502() 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);
__anonf63d79d80602null372 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);
__anonf63d79d80702() 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);
__anonf63d79d80802null436 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 #ifndef OMIT_MULTI_VER
666 HWTEST_F(DistributeddbNbBackupTest, ImportTest004, TestSize.Level1)
667 {
668 KvStoreDelegate *multiEncryptDelegate = nullptr;
669 KvStoreDelegateManager *multiEncryptManager = nullptr;
670
671 KvOption option = g_kvOption;
672 multiEncryptDelegate = DistributedTestTools::GetDelegateSuccess(multiEncryptManager, g_kvdbParameter2, option);
673 ASSERT_TRUE(multiEncryptManager != nullptr && multiEncryptDelegate != nullptr);
674 const std::string multiImportPath = DIRECTOR + "export";
675 SetDir(multiImportPath);
676 std::string multiFilePath1 = multiImportPath + "/bkpDB1.bin";
677 multiEncryptDelegate->Export(multiFilePath1, g_filePasswd1);
678
679 KvStoreDelegate *localDelegate = nullptr;
680 KvStoreDelegateManager *localManager = nullptr;
681 option.localOnly = true;
682 localDelegate = DistributedTestTools::GetDelegateSuccess(localManager, g_kvdbParameter3, option);
683 ASSERT_TRUE(localManager != nullptr && localDelegate != nullptr);
684
685 std::string multiFilePath2 = multiImportPath + "/bkpDB2.bin";
686 localDelegate->Export(multiFilePath2, g_filePasswd1);
687
688 const std::string nbImportPath = DistributedDBConstant::NB_DIRECTOR + "export";
689 SetDir(nbImportPath);
690 std::string nbFilePath = nbImportPath + "/bkpDB1.bin";
691 g_nbBackupDelegate->Export(nbFilePath, g_filePasswd1);
692 /**
693 * @tc.steps: step1. the multi DB1 import the nb DB backup file with the password f1.
694 * @tc.expected: step1. call failed and return INVALID_FILE.
695 */
696 EXPECT_EQ(multiEncryptDelegate->Import(nbFilePath, g_filePasswd1), INVALID_FILE);
697 /**
698 * @tc.steps: step2. the multi DB1 import backup file of local db with the password f1.
699 * @tc.expected: step2. call failed and return INVALID_FILE.
700 */
701 EXPECT_EQ(multiEncryptDelegate->Import(multiFilePath2, g_filePasswd1), INVALID_FILE);
702 /**
703 * @tc.steps: step3. the nb DB import the multi DB backup file with the password f1.
704 * @tc.expected: step3. call failed and return INVALID_FILE.
705 */
706 EXPECT_EQ(g_nbBackupDelegate->Import(multiFilePath1, g_filePasswd1), INVALID_FILE);
707 /**
708 * @tc.steps: step4. the nb DB import the noexsit nb DB backup file with the password f1.
709 * @tc.expected: step4. call failed and return INVALID_FILE.
710 */
711 EXPECT_EQ(g_nbBackupDelegate->Import(multiFilePath2, g_filePasswd1), INVALID_FILE);
712
713 /**
714 * @tc.steps: step5. Local DB import nb-backup file with the password f1.
715 * @tc.expected: step5. call failed and return INVALID_FILE.
716 */
717 EXPECT_EQ(localDelegate->Import(nbFilePath, g_filePasswd1), INVALID_FILE);
718 /**
719 * @tc.steps: step6. Local DB import multi-backup file with the password f1.
720 * @tc.expected: step6. call failed and return INVALID_FILE.
721 */
722 EXPECT_EQ(localDelegate->Import(multiFilePath1, g_filePasswd1), INVALID_FILE);
723 EXPECT_EQ(multiEncryptManager->CloseKvStore(multiEncryptDelegate), OK);
724 multiEncryptDelegate = nullptr;
725 EXPECT_EQ(multiEncryptManager->DeleteKvStore(STORE_ID_2), OK);
726 delete multiEncryptManager;
727 multiEncryptManager = nullptr;
728 EXPECT_EQ(localManager->CloseKvStore(localDelegate), OK);
729 localDelegate = nullptr;
730 EXPECT_EQ(localManager->DeleteKvStore(STORE_ID_3), OK);
731 delete localManager;
732 localManager = nullptr;
733 RemoveDir(multiImportPath);
734 RemoveDir(nbImportPath);
735 }
736 #endif // OMIT_MULTI_VER
737 /*
738 * @tc.name: ImportTest 006
739 * @tc.desc: Verify that many kvstore of one DB or the DB registered observer can't import the backup file.
740 * @tc.type: FUNC
741 * @tc.require: SR000D4878
742 * @tc.author: fengxiaoyun
743 */
744 HWTEST_F(DistributeddbNbBackupTest, ImportTest006, TestSize.Level1)
745 {
746 const std::string importPath = DistributedDBConstant::NB_DIRECTOR + "export";
747 SetDir(importPath);
748 std::string filePath = importPath + "/bkpDB.bin";
749 EXPECT_EQ(g_nbBackupDelegate->Export(filePath, g_filePasswd1), OK);
750
751 /**
752 * @tc.steps: step1. create another delegate of the same storeId.
753 * @tc.expected: step1. create success.
754 */
755 KvStoreNbDelegate *delegate2 = nullptr;
756 KvStoreDelegateManager *manager2 = nullptr;
757 delegate2 = DistributedDBNbTestTools::GetNbDelegateSuccess(manager2, g_dbParameter1, g_option);
758 ASSERT_TRUE(manager2 != nullptr && delegate2 != nullptr);
759
760 /**
761 * @tc.steps: step2. use the second delegate to import the backup file.
762 * @tc.expected: step2. import failed and return busy
763 */
764 EXPECT_EQ(delegate2->Import(filePath, g_filePasswd1), BUSY);
765
766 EXPECT_TRUE(manager2->CloseKvStore(delegate2) == OK);
767 delegate2 = nullptr;
768 delete manager2;
769 manager2 = nullptr;
770 /**
771 * @tc.steps: step3. delegate1 register observer.
772 * @tc.expected: step3. register success
773 */
774 KvStoreObserverImpl observerSync;
775 EXPECT_EQ(g_nbBackupDelegate->RegisterObserver(KEY_1, OBSERVER_CHANGES_NATIVE, &observerSync), OK);
776 /**
777 * @tc.steps: step4. delegate1 import the backup file with the password f1.
778 * @tc.expected: step4. register success
779 */
780 EXPECT_EQ(g_nbBackupDelegate->Import(filePath, g_filePasswd1), BUSY);
781 RemoveDir(importPath);
782 }
783
784 /*
785 * @tc.name: ImportTest 007
786 * @tc.desc: Verify that the DB registered conflict notifier or hadn't resultSet can't import the backup file.
787 * @tc.type: FUNC
788 * @tc.require: SR000D4878
789 * @tc.author: fengxiaoyun
790 */
791 HWTEST_F(DistributeddbNbBackupTest, ImportTest007, TestSize.Level1)
792 {
793 const std::string importPath = DistributedDBConstant::NB_DIRECTOR + "export";
794 SetDir(importPath);
795 std::string filePath = importPath + "/bkpDB.bin";
796 EXPECT_EQ(g_nbBackupDelegate->Export(filePath, g_filePasswd1), OK);
797
798 /**
799 * @tc.steps: step1. register conflict notifier.
800 * @tc.expected: step1. register successfully.
801 */
802 ConflictNbCallback callback;
803 std::vector<ConflictData> conflictData;
804 auto notifier = bind(&ConflictNbCallback::NotifyCallBack, &callback, placeholders::_1, &conflictData);
805 EXPECT_EQ(g_nbBackupDelegate->SetConflictNotifier(CONFLICT_NATIVE_ALL, notifier), OK);
806 /**
807 * @tc.steps: step2. import the backup file with the password f1.
808 * @tc.expected: step2. import failed and returned BUSY.
809 */
810 EXPECT_EQ(g_nbBackupDelegate->Import(filePath, g_filePasswd1), BUSY);
811 EXPECT_EQ(g_nbBackupDelegate->SetConflictNotifier(CONFLICT_NATIVE_ALL, nullptr), OK);
812
813 /**
814 * @tc.steps: step3. call GetEntries to get resultSet.
815 * @tc.expected: step3. get successfully.
816 */
817 KvStoreResultSet *resultSet;
818 EXPECT_EQ(g_nbBackupDelegate->GetEntries(KEY_K, resultSet), OK);
819 /**
820 * @tc.steps: step4. import the backup file with the password f1.
821 * @tc.expected: step4. import failed and returned BUSY.
822 */
823 EXPECT_EQ(g_nbBackupDelegate->Import(filePath, g_filePasswd1), BUSY);
824 EXPECT_EQ(g_nbBackupDelegate->CloseResultSet(resultSet), OK);
825
826 RemoveDir(importPath);
827 }
828
829 #ifndef LOW_LEVEL_MEM_DEV
830 /*
831 * @tc.name: ImportTest 008
832 * @tc.desc: Verify that it will return busy when GetKvStore again or crud during it is importing.
833 * @tc.type: FUNC
834 * @tc.require: SR000D4878
835 * @tc.author: fengxiaoyun
836 */
837 HWTEST_F(DistributeddbNbBackupTest, ImportTest008, TestSize.Level3)
838 {
839 vector<Entry> entries;
840 std::vector<DistributedDB::Key> allKeys;
841 GenerateFixedRecords(entries, allKeys, FIFTY_RECORDS, KEY_SIX_BYTE, TWO_M_LONG_STRING);
842 for (auto iter = entries.begin(); iter != entries.end(); iter++) {
843 EXPECT_TRUE(g_nbBackupDelegate->Put(iter->key, iter->value) == OK);
844 }
845
846 const std::string importPath = DistributedDBConstant::NB_DIRECTOR + "export";
847 SetDir(importPath);
848 std::string filePath = importPath + "/bkpDB.bin";
849 EXPECT_EQ(g_nbBackupDelegate->Export(filePath, NULL_PASSWD), OK);
850
851 /**
852 * @tc.steps: step1. start subthread to import the backup file with empty password.
853 * @tc.expected: step1. start successfully if step1 running before step2, else return BUSY.
854 */
855 g_readyFlag.store(false);
__anonf63d79d80902() 856 thread subThread([&filePath]() {
857 DBStatus importStatus = g_nbBackupDelegate->Import(filePath, NULL_PASSWD);
858 EXPECT_TRUE(importStatus == OK || importStatus == BUSY);
859 g_readyFlag.store(true);
860 g_backupVar.notify_one();
861 });
862 subThread.detach();
863
864 /**
865 * @tc.steps: step2. GetKvStore again during the subthread is importing.
866 * @tc.expected: step2. GetKvStore failed and returned BUSY if step1 is running, else return OK.
867 */
868 std::this_thread::sleep_for(std::chrono::microseconds(WAIT_FOR_LONG_TIME));
869 KvStoreDelegateManager *manager = nullptr;
870 DBStatus statusReturn;
871 DistributedDBNbTestTools::GetNbDelegateStatus(manager, statusReturn, g_dbParameter1, g_option);
872 EXPECT_TRUE(statusReturn == BUSY || statusReturn == OK);
873 /**
874 * @tc.steps: step3. put (k1, v1) during the subthread is importing.
875 * @tc.expected: step3. put failed and returned BUSY if step1 is running, else return OK.
876 */
877 statusReturn = g_nbBackupDelegate->Put(KEY_1, VALUE_1);
878 EXPECT_TRUE(statusReturn == BUSY || statusReturn == OK);
879 std::mutex rekeyMtx;
880 std::unique_lock<std::mutex> lck(rekeyMtx);
__anonf63d79d80a02null881 g_backupVar.wait(lck, [&]{ return g_readyFlag.load(); });
882 RemoveDir(importPath);
883 }
884
885 #ifndef LOW_LEVEL_MEM_DEV
886 /*
887 * @tc.name: ImportTest 009
888 * @tc.desc: Verify that it will return busy when rekey during it is importing.
889 * @tc.type: FUNC
890 * @tc.require: SR000D4878
891 * @tc.author: fengxiaoyun
892 */
893 HWTEST_F(DistributeddbNbBackupTest, ImportTest009, TestSize.Level3)
894 {
895 vector<Entry> entriesRekey;
896 std::vector<DistributedDB::Key> allKeys;
897 GenerateFixedRecords(entriesRekey, allKeys, FIFTY_RECORDS, KEY_SIX_BYTE, FOUR_M_LONG_STRING);
898 for (auto iter = entriesRekey.begin(); iter != entriesRekey.end(); iter++) {
899 EXPECT_TRUE(g_nbBackupDelegate->Put(iter->key, iter->value) == OK);
900 }
901
902 const std::string importPath = DistributedDBConstant::NB_DIRECTOR + "export";
903 SetDir(importPath);
904 std::string filePath = importPath + "/bkpDB.bin";
905 EXPECT_EQ(g_nbBackupDelegate->Export(filePath, NULL_PASSWD), OK);
906
907 /**
908 * @tc.steps: step1. start subthread to import the backup file with empty password.
909 * @tc.expected: step1. start successfully if step1 running before step2, else return BUSY.
910 */
911 g_readyFlag.store(false);
__anonf63d79d80b02() 912 thread subThread([&filePath]() {
913 DBStatus importStatus = g_nbBackupDelegate->Import(filePath, NULL_PASSWD);
914 EXPECT_TRUE(importStatus == OK || importStatus == BUSY);
915 g_readyFlag.store(true);
916 g_backupVar.notify_one();
917 });
918 subThread.detach();
919 /**
920 * @tc.steps: step2. rekey during the subthread is importing.
921 * @tc.expected: step2. rekey failed and returned BUSY if step1 is running, else return OK.
922 */
923 std::this_thread::sleep_for(std::chrono::microseconds(WAIT_FOR_LAST_SYNC));
924 DBStatus status = g_nbBackupDelegate->Rekey(g_passwd1);
925 EXPECT_TRUE(status == BUSY || status == OK);
926
927 std::mutex rekeyMtx;
928 std::unique_lock<std::mutex> lck(rekeyMtx);
__anonf63d79d80c02null929 g_backupVar.wait(lck, [&]{ return g_readyFlag.load(); });
930 RemoveDir(importPath);
931 }
932 #endif
933
934 /*
935 * @tc.name: ImportTest 010
936 * @tc.desc: Verify that it will return busy when rekey during it is importing.
937 * @tc.type: FUNC
938 * @tc.require: SR000D4878
939 * @tc.author: fengxiaoyun
940 */
941 HWTEST_F(DistributeddbNbBackupTest, ImportTest010, TestSize.Level3)
942 {
943 vector<Entry> entriesRekey2;
944 std::vector<DistributedDB::Key> allKeys;
945 GenerateFixedRecords(entriesRekey2, allKeys, FIFTY_RECORDS, KEY_SIX_BYTE, TWO_M_LONG_STRING);
946 for (auto iter = entriesRekey2.begin(); iter != entriesRekey2.end(); iter++) {
947 EXPECT_TRUE(g_nbBackupDelegate->Put(iter->key, iter->value) == OK);
948 }
949
950 const std::string importPath = DistributedDBConstant::NB_DIRECTOR + "export";
951 SetDir(importPath);
952 std::string filePath = importPath + "/bkpDB.bin";
953 EXPECT_EQ(g_nbBackupDelegate->Export(filePath, NULL_PASSWD), OK);
954
955 /**
956 * @tc.steps: step1. start subthread to rekey DB with password 1.
957 * @tc.expected: step1. start successfully.
958 */
959 g_readyFlag.store(false);
__anonf63d79d80d02() 960 thread subThread([]() {
961 EXPECT_EQ(g_nbBackupDelegate->Rekey(g_passwd1), OK);
962 g_readyFlag.store(true);
963 g_backupVar.notify_one();
964 });
965 subThread.detach();
966 /**
967 * @tc.steps: step2. import the backup file during the subthread is rekeying.
968 * @tc.expected: step2. import failed and returned BUSY.
969 */
970 std::this_thread::sleep_for(std::chrono::microseconds(WAIT_FOR_LAST_SYNC));
971 EXPECT_EQ(g_nbBackupDelegate->Import(filePath, NULL_PASSWD), BUSY);
972
973 std::mutex rekeyMtx;
974 std::unique_lock<std::mutex> lck(rekeyMtx);
__anonf63d79d80e02null975 g_backupVar.wait(lck, [&]{ return g_readyFlag.load(); });
976 RemoveDir(importPath);
977 }
978 #endif
979
980 /*
981 * @tc.name: ImportTest 011
982 * @tc.desc: Verify that it will allow to import backup file again during it is importing.
983 * @tc.type: FUNC
984 * @tc.require: SR000D4878
985 * @tc.author: fengxiaoyun
986 */
987 HWTEST_F(DistributeddbNbBackupTest, ImportTest011, TestSize.Level3)
988 {
989 vector<Entry> entriesReImport;
990 std::vector<DistributedDB::Key> allKeys;
991 GenerateFixedRecords(entriesReImport, allKeys, TEN_RECORDS, KEY_SIX_BYTE, FOUR_M_LONG_STRING);
992 for (auto iter = entriesReImport.begin(); iter != entriesReImport.end(); iter++) {
993 EXPECT_TRUE(g_nbBackupDelegate->Put(iter->key, iter->value) == OK);
994 }
995
996 const std::string importPath = DistributedDBConstant::NB_DIRECTOR + "export";
997 SetDir(importPath);
998 std::string filePath = importPath + "/bkpDB.bin";
999 EXPECT_EQ(g_nbBackupDelegate->Export(filePath, NULL_PASSWD), OK);
1000
1001 /**
1002 * @tc.steps: step1. start subthread to import the backup file.
1003 * @tc.expected: step1. start successfully.
1004 */
1005 g_readyFlag.store(false);
__anonf63d79d80f02() 1006 thread subThread([&filePath]() {
1007 EXPECT_EQ(g_nbBackupDelegate->Import(filePath, NULL_PASSWD), OK);
1008 g_readyFlag.store(true);
1009 g_backupVar.notify_one();
1010 });
1011 subThread.detach();
1012 /**
1013 * @tc.steps: step2. import the backup file during the subthread is importing with empty password.
1014 * @tc.expected: step2. import successfully and return OK.
1015 */
1016 EXPECT_EQ(g_nbBackupDelegate->Import(filePath, NULL_PASSWD), OK);
1017
1018 std::mutex rekeyMtx;
1019 std::unique_lock<std::mutex> lck(rekeyMtx);
__anonf63d79d81002null1020 g_backupVar.wait(lck, [&]{ return g_readyFlag.load(); });
1021
1022 RemoveDir(importPath);
1023 }
1024
NbSubImportThread(int index,std::string importPath)1025 void NbSubImportThread(int index, std::string importPath)
1026 {
1027 vector<Entry> tenEntries;
1028 std::vector<DistributedDB::Key> allKeys;
1029 GenerateFixedRecords(tenEntries, allKeys, FIVE_RECORDS, KEY_SIX_BYTE, FOUR_M_LONG_STRING);
1030 /**
1031 * @tc.steps: step1. every thread create one DB put 10 entries into the DB.
1032 * @tc.expected: step1. put successfully.
1033 */
1034 KvStoreNbDelegate *delegate2 = nullptr;
1035 KvStoreDelegateManager *manager2 = nullptr;
1036 DBParameters parameter[] = {g_dbParameter2, g_dbParameter3, g_dbParameter4, g_dbParameter5, g_dbParameter6};
1037 Option option[] = {g_createDiskUnencrypted, g_createDiskUnencrypted, g_createDiskUnencrypted,
1038 g_createDiskEncrypted, g_createDiskEncrypted};
1039 delegate2 = DistributedDBNbTestTools::GetNbDelegateSuccess(manager2, parameter[index], option[index]);
1040 ASSERT_TRUE(manager2 != nullptr && delegate2 != nullptr);
1041
1042 for (auto iter = tenEntries.begin(); iter != tenEntries.end(); iter++) {
1043 EXPECT_TRUE(delegate2->Put(iter->key, iter->value) == OK);
1044 }
1045
1046 /**
1047 * @tc.steps: step2. every thread export DB to backup file.
1048 * @tc.expected: step2. export successfully.
1049 */
1050 DistributedDB::CipherPassword passwd[] = {NULL_PASSWD, NULL_PASSWD, NULL_PASSWD, g_filePasswd1, g_filePasswd2};
1051
1052 const std::string backupFile[] = {"/bkpDB1.bin", "/bkpDB2.bin", "/bkpDB3.bin", "/bkpDB4.bin", "/bkpDB5.bin"};
1053 std::string nbFilePath[] = {(importPath + backupFile[INDEX_ZEROTH]), (importPath + backupFile[INDEX_FIRST]),
1054 (importPath + backupFile[INDEX_SECOND]), (importPath + backupFile[INDEX_THIRD]),
1055 (importPath + backupFile[INDEX_FORTH])};
1056 delegate2->Export(nbFilePath[index], passwd[index]);
1057
1058 /**
1059 * @tc.steps: step3. every thread import backup file to DB.
1060 * @tc.expected: step3. import successfully.
1061 */
1062 EXPECT_EQ(delegate2->Import(nbFilePath[index], passwd[index]), OK);
1063 EXPECT_EQ(manager2->CloseKvStore(delegate2), OK);
1064 delegate2 = nullptr;
1065 std::string storeId[] = {STORE_ID_2, STORE_ID_3, STORE_ID_4, STORE_ID_5, STORE_ID_6};
1066 EXPECT_TRUE(manager2->DeleteKvStore(storeId[index]) == OK);
1067 delete manager2;
1068 manager2 = nullptr;
1069 }
1070
1071 /*
1072 * @tc.name: ImportTest 012
1073 * @tc.desc: Verify that different DB export and import in the same time won't affect each other.
1074 * @tc.type: FUNC
1075 * @tc.require: SR000D4878
1076 * @tc.author: fengxiaoyun
1077 */
1078 HWTEST_F(DistributeddbNbBackupTest, ImportTest012, TestSize.Level3)
1079 {
1080 std::vector<std::thread> threads;
1081 const std::string importPath = DistributedDBConstant::NB_DIRECTOR + "export";
1082 SetDir(importPath);
1083 for (int index = 0; index < FIVE_TIMES; ++index) {
1084 threads.push_back(std::thread(NbSubImportThread, index, std::ref(importPath)));
1085 }
1086
1087 for (auto& th : threads) {
1088 th.join();
1089 }
1090 RemoveDir(importPath);
1091 }
1092
1093 /*
1094 * @tc.name: Exchange 001
1095 * @tc.desc: whether current db is encrypted or not, import file need to use exported password(or NULL_PASSWD).
1096 * @tc.type: FUNC
1097 * @tc.require: SR000D4878
1098 * @tc.author: fengxiaoyun
1099 */
1100 HWTEST_F(DistributeddbNbBackupTest, Exchange001, TestSize.Level1)
1101 {
1102 const std::string exportPath = DistributedDBConstant::NB_DIRECTOR + "export";
1103 SetDir(exportPath);
1104 std::string filePath1 = exportPath + "/bkpDB1.bin";
1105 std::string filePath2 = exportPath + "/bkpDB2.bin";
1106 /**
1107 * @tc.steps: step1. export data as "bkpDB1.bin" with passwd g_filePasswd1 and "bkpDB2.bin" with NULL_PASSWD.
1108 * @tc.expected: step1. call successfully.
1109 */
1110 EXPECT_EQ(g_nbBackupDelegate->Export(filePath1, g_filePasswd1), OK);
1111 EXPECT_EQ(g_nbBackupDelegate->Export(filePath2, NULL_PASSWD), OK);
1112 /**
1113 * @tc.steps: step2. import "bkpDB1.bin" and "bkpDB2.bin" with NULL_PASSWD.
1114 * @tc.expected: step2. import "bkpDB1.bin" failed and import "bkpDB2.bin" succeeded.
1115 */
1116 EXPECT_EQ(g_nbBackupDelegate->Import(filePath1, NULL_PASSWD), INVALID_FILE);
1117 EXPECT_EQ(g_nbBackupDelegate->Import(filePath2, NULL_PASSWD), OK);
1118 /**
1119 * @tc.steps: step3. import "bkpDB1.bin" and "bkpDB2.bin" with g_filePasswd1.
1120 * @tc.expected: step3. import "bkpDB1.bin" succeeded and import "bkpDB2.bin" failed.
1121 */
1122 EXPECT_EQ(g_nbBackupDelegate->Import(filePath1, g_filePasswd1), OK);
1123 EXPECT_EQ(g_nbBackupDelegate->Import(filePath2, g_filePasswd1), INVALID_FILE);
1124 /**
1125 * @tc.steps: step4. rekey db1 with g_passwd1, and then import "bkpDB1.bin" and "bkpDB2.bin" with p1.
1126 * @tc.expected: step4. rekey succeeded and import failed.
1127 */
1128 EXPECT_EQ(g_nbBackupDelegate->Rekey(g_passwd1), OK);
1129 EXPECT_EQ(g_nbBackupDelegate->Import(filePath1, g_passwd1), INVALID_FILE);
1130 EXPECT_EQ(g_nbBackupDelegate->Import(filePath2, g_passwd1), INVALID_FILE);
1131 /**
1132 * @tc.steps: step5. import "bkpDB1.bin" and "bkpDB2.bin" with g_filePasswd1.
1133 * @tc.expected: step5. import "bkpDB1.bin" succeeded and import "bkpDB2.bin" failed.
1134 */
1135 EXPECT_EQ(g_nbBackupDelegate->Import(filePath1, g_filePasswd1), OK);
1136 EXPECT_EQ(g_nbBackupDelegate->Import(filePath2, g_filePasswd1), INVALID_FILE);
1137 /**
1138 * @tc.steps: step6. import "bkpDB1.bin" and "bkpDB2.bin" with NULL_PASSWD.
1139 * @tc.expected: step6. import "bkpDB1.bin" failed and import "bkpDB2.bin" succeeded.
1140 */
1141 EXPECT_EQ(g_nbBackupDelegate->Import(filePath1, NULL_PASSWD), INVALID_FILE);
1142 EXPECT_EQ(g_nbBackupDelegate->Import(filePath2, NULL_PASSWD), OK);
1143 RemoveDir(exportPath);
1144 }
1145
1146 /*
1147 * @tc.name: Exchange 002
1148 * @tc.desc: whether current db is encrypted or not, import file need to use exported password(or NULL_PASSWD).
1149 * @tc.type: FUNC
1150 * @tc.require: SR000D4878
1151 * @tc.author: fengxiaoyun
1152 */
1153 HWTEST_F(DistributeddbNbBackupTest, Exchange002, TestSize.Level1)
1154 {
1155 const std::string exportPath = DistributedDBConstant::NB_DIRECTOR + "export";
1156 SetDir(exportPath);
1157 std::string filePath1 = exportPath + "/bkpDB1.bin";
1158 std::string filePath2 = exportPath + "/bkpDB2.bin";
1159 /**
1160 * @tc.steps: step1. rekey db1 with g_passwd1,
1161 * export data as "bkpDB1.bin" with passwd g_filePasswd1 and "bkpDB2.bin" with NULL_PASSWD.
1162 * @tc.expected: step1. call successfully.
1163 */
1164 EXPECT_EQ(g_nbBackupDelegate->Rekey(g_passwd1), OK);
1165 EXPECT_EQ(g_nbBackupDelegate->Export(filePath1, g_filePasswd1), OK);
1166 EXPECT_EQ(g_nbBackupDelegate->Export(filePath2, NULL_PASSWD), OK);
1167 /**
1168 * @tc.steps: step2. import "bkpDB1.bin" and "bkpDB2.bin" with NULL_PASSWD.
1169 * @tc.expected: step2. import "bkpDB1.bin" failed and import "bkpDB2.bin" succeeded.
1170 */
1171 EXPECT_EQ(g_nbBackupDelegate->Import(filePath1, NULL_PASSWD), INVALID_FILE);
1172 EXPECT_EQ(g_nbBackupDelegate->Import(filePath2, NULL_PASSWD), OK);
1173 /**
1174 * @tc.steps: step3. import "bkpDB1.bin" and "bkpDB2.bin" with g_passwd1.
1175 * @tc.expected: step3. rekey succeeded and import failed.
1176 */
1177 EXPECT_EQ(g_nbBackupDelegate->Import(filePath1, g_passwd1), INVALID_FILE);
1178 EXPECT_EQ(g_nbBackupDelegate->Import(filePath2, g_passwd1), INVALID_FILE);
1179 /**
1180 * @tc.steps: step4. import "bkpDB1.bin" and "bkpDB2.bin" with g_filePasswd1.
1181 * @tc.expected: step4. import "bkpDB1.bin" succeeded and import "bkpDB2.bin" failed.
1182 */
1183 EXPECT_EQ(g_nbBackupDelegate->Import(filePath1, g_filePasswd1), OK);
1184 EXPECT_EQ(g_nbBackupDelegate->Import(filePath2, g_filePasswd1), INVALID_FILE);
1185 /**
1186 * @tc.steps: step5. rekey db1 with NULL_PASSWD,
1187 * import "bkpDB1.bin" and "bkpDB2.bin" with NULL_PASSWD.
1188 * @tc.expected: step5. import "bkpDB1.bin" failed and import "bkpDB2.bin" succeeded.
1189 */
1190 EXPECT_EQ(g_nbBackupDelegate->Rekey(NULL_PASSWD), OK);
1191 EXPECT_EQ(g_nbBackupDelegate->Import(filePath1, NULL_PASSWD), INVALID_FILE);
1192 EXPECT_EQ(g_nbBackupDelegate->Import(filePath2, NULL_PASSWD), OK);
1193 /**
1194 * @tc.steps: step6. import "bkpDB1.bin" and "bkpDB2.bin" with g_filePasswd1.
1195 * @tc.expected: step6. import "bkpDB1.bin" succeeded and import "bkpDB2.bin" failed.
1196 */
1197 EXPECT_EQ(g_nbBackupDelegate->Import(filePath1, g_filePasswd1), OK);
1198 EXPECT_EQ(g_nbBackupDelegate->Import(filePath2, g_filePasswd1), INVALID_FILE);
1199 RemoveDir(exportPath);
1200 }
1201
1202 /*
1203 * @tc.name: Exchange 003
1204 * @tc.desc: whether current db is encrypted or not, import file need to use exported password(or NULL_PASSWD).
1205 * @tc.type: FUNC
1206 * @tc.require: SR000D4878
1207 * @tc.author: fengxiaoyun
1208 */
1209 HWTEST_F(DistributeddbNbBackupTest, Exchange003, TestSize.Level1)
1210 {
1211 const std::string exportPath = DistributedDBConstant::NB_DIRECTOR + "export";
1212 SetDir(exportPath);
1213 std::string filePath1 = exportPath + "/bkpDB1.bin";
1214 std::string filePath2 = exportPath + "/bkpDB2.bin";
1215 /**
1216 * @tc.steps: step1. rekey db1 with g_passwd1,
1217 * export data as "bkpDB1.bin" with passwd g_filePasswd1 and "bkpDB2.bin" with NULL_PASSWD.
1218 * @tc.expected: step1. call successfully.
1219 */
1220 EXPECT_EQ(g_nbBackupDelegate->Rekey(g_passwd1), OK);
1221 EXPECT_EQ(g_nbBackupDelegate->Export(filePath1, g_filePasswd1), OK);
1222 EXPECT_EQ(g_nbBackupDelegate->Export(filePath2, NULL_PASSWD), OK);
1223 /**
1224 * @tc.steps: step2. rekey db1 with g_passwd2,
1225 * import "bkpDB1.bin" and "bkpDB2.bin" with NULL_PASSWD.
1226 * @tc.expected: step2. import "bkpDB1.bin" failed and import "bkpDB2.bin" succeeded.
1227 */
1228 EXPECT_EQ(g_nbBackupDelegate->Rekey(g_passwd2), OK);
1229 EXPECT_EQ(g_nbBackupDelegate->Import(filePath1, NULL_PASSWD), INVALID_FILE);
1230 EXPECT_EQ(g_nbBackupDelegate->Import(filePath2, NULL_PASSWD), OK);
1231 /**
1232 * @tc.steps: step3. Put (k1,v1), close db, open db with g_passwd2 and delete (k1,v1)
1233 * @tc.expected: step3. operate successfully.
1234 */
1235 EXPECT_EQ(g_nbBackupDelegate->Put(KEY_1, VALUE_1), OK);
1236 EXPECT_EQ((g_manager->CloseKvStore(g_nbBackupDelegate)), OK);
1237 g_nbBackupDelegate = nullptr;
1238 delete g_manager;
1239 g_manager = nullptr;
1240 Option encrypted(true, false, true, DistributedDB::CipherType::DEFAULT, PASSWD_VECTOR_2);
1241 g_nbBackupDelegate = DistributedDBNbTestTools::GetNbDelegateSuccess(g_manager, g_dbParameter1, encrypted);
1242 ASSERT_TRUE(g_manager != nullptr && g_nbBackupDelegate != nullptr);
1243 EXPECT_EQ(g_nbBackupDelegate->Delete(KEY_1), OK);
1244 /**
1245 * @tc.steps: step4. import "bkpDB1.bin" and "bkpDB2.bin" with g_passwd1.
1246 * @tc.expected: step4. import failed.
1247 */
1248 EXPECT_EQ(g_nbBackupDelegate->Import(filePath1, g_passwd1), INVALID_FILE);
1249 EXPECT_EQ(g_nbBackupDelegate->Import(filePath2, g_passwd1), INVALID_FILE);
1250 /**
1251 * @tc.steps: step5. import "bkpDB1.bin" and "bkpDB2.bin" with g_passwd2.
1252 * @tc.expected: step5. import failed.
1253 */
1254 EXPECT_EQ(g_nbBackupDelegate->Import(filePath1, g_passwd2), INVALID_FILE);
1255 EXPECT_EQ(g_nbBackupDelegate->Import(filePath2, g_passwd2), INVALID_FILE);
1256 /**
1257 * @tc.steps: step6. import "bkpDB1.bin" and "bkpDB2.bin" with g_filePasswd1.
1258 * @tc.expected: step6. import "bkpDB1.bin" succeeded and import "bkpDB2.bin" failed.
1259 */
1260 EXPECT_EQ(g_nbBackupDelegate->Import(filePath1, g_filePasswd1), OK);
1261 EXPECT_EQ(g_nbBackupDelegate->Import(filePath2, g_filePasswd1), INVALID_FILE);
1262 /**
1263 * @tc.steps: step7. Put (k2,v2), close db, open db with g_passwd2 and delete (k2,v2)
1264 * @tc.expected: step7. operate successfully.
1265 */
1266 EXPECT_EQ(g_nbBackupDelegate->Put(KEY_2, VALUE_2), OK);
1267 EXPECT_EQ((g_manager->CloseKvStore(g_nbBackupDelegate)), OK);
1268 g_nbBackupDelegate = nullptr;
1269 delete g_manager;
1270 g_manager = nullptr;
1271 g_nbBackupDelegate = DistributedDBNbTestTools::GetNbDelegateSuccess(g_manager, g_dbParameter1, encrypted);
1272 ASSERT_TRUE(g_manager != nullptr && g_nbBackupDelegate != nullptr);
1273 EXPECT_EQ(g_nbBackupDelegate->Delete(KEY_2), OK);
1274 RemoveDir(exportPath);
1275 }
1276
1277 /*
1278 * @tc.name: CorruptionHandler 001
1279 * @tc.desc: Verify that the Corruption Handler can be set only one, if set many times, the last one is valid.
1280 * @tc.type: FUNC
1281 * @tc.require: SR000D4878
1282 * @tc.author: fengxiaoyun
1283 */
1284 HWTEST_F(DistributeddbNbBackupTest, CorruptionHandler001, TestSize.Level1)
1285 {
1286 EXPECT_TRUE(g_nbBackupDelegate->Put(KEY_1, VALUE_1) == OK);
1287 const std::string exportPath = DistributedDBConstant::NB_DIRECTOR + "export";
1288 SetDir(exportPath);
1289 std::string filePath = exportPath + "/bkpDB.bin";
1290 EXPECT_TRUE(g_nbBackupDelegate->Export(filePath, NULL_PASSWD) == OK);
1291 EXPECT_TRUE(g_nbBackupDelegate->Delete(KEY_1) == OK);
1292
1293 /**
1294 * @tc.steps: step1. device A call SetKvStoreCorruptionHandler.
1295 * @tc.expected: step1. call successfully.
1296 */
1297 KvStoreNbCorruptInfo corruptInfo;
1298 KvStoreNbCorruptInfo corruptInfoNew;
1299 bool isCalled = false;
1300 auto notifier = bind(&KvStoreNbCorruptInfo::CorruptCallBack, &corruptInfo,
1301 placeholders::_1, placeholders::_2, placeholders::_3, std::ref(isCalled));
1302 g_manager->SetKvStoreCorruptionHandler(notifier);
1303 /**
1304 * @tc.steps: step2. device A call SetKvStoreCorruptionHandler the second time.
1305 * @tc.expected: step2. call successfully.
1306 */
1307 CallBackParam pathResult = {filePath, true};
1308 auto notifierNew = bind(&KvStoreNbCorruptInfo::CorruptNewCallBack, &corruptInfoNew,
1309 placeholders::_1, placeholders::_2, placeholders::_3, std::ref(g_manager), pathResult);
1310 g_manager->SetKvStoreCorruptionHandler(notifierNew);
1311 EXPECT_TRUE(pathResult.result);
1312 /**
1313 * @tc.steps: step3. make file corrupted and call GetKvStore to trigger callback function.
1314 * @tc.expected: step3. call successfully.
1315 */
1316 EXPECT_EQ((g_manager->CloseKvStore(g_nbBackupDelegate)), OK);
1317 g_nbBackupDelegate = nullptr;
1318 std::string dbFliePath = DistributedDBNbTestTools::GetKvNbStoreDirectory(g_dbParameter1);
1319 EXPECT_TRUE(DistributedDBNbTestTools::ModifyDatabaseFile(dbFliePath));
1320 DBStatus status;
1321 KvStoreDelegateManager *manager = nullptr;
1322 EXPECT_EQ(DistributedDBNbTestTools::GetNbDelegateStatus(manager, status, g_dbParameter1, g_option), nullptr);
1323 EXPECT_EQ(status, INVALID_PASSWD_OR_CORRUPTED_DB);
1324 /**
1325 * @tc.steps: step4. open db and Get(k1) to verify importing in callback is successful.
1326 * @tc.expected: step4. Get(k1)=v1.
1327 */
1328 g_nbBackupDelegate = DistributedDBNbTestTools::GetNbDelegateSuccess(g_manager, g_dbParameter1, g_option);
1329 ASSERT_TRUE(g_manager != nullptr && g_nbBackupDelegate != nullptr);
1330 Value valueResult;
1331 EXPECT_TRUE(g_nbBackupDelegate->Get(KEY_1, valueResult) == OK);
1332 EXPECT_EQ(valueResult, VALUE_1);
1333 g_manager->SetKvStoreCorruptionHandler(nullptr);
1334 RemoveDir(exportPath);
1335 }
1336
1337 /*
1338 * @tc.name: CorruptionHandler 002
1339 * @tc.desc: Verify that can import db files and can't export in the Corruption Handler callback when db files
1340 * are corrupted in using.
1341 * @tc.type: FUNC
1342 * @tc.require: SR000D4878
1343 * @tc.author: fengxiaoyun
1344 */
1345 HWTEST_F(DistributeddbNbBackupTest, CorruptionHandler002, TestSize.Level2)
1346 {
1347 EXPECT_TRUE(g_nbBackupDelegate->Put(KEY_1, VALUE_1) == OK);
1348 const std::string exportPath = DistributedDBConstant::NB_DIRECTOR + "export";
1349 SetDir(exportPath);
1350 std::string filePath = exportPath + "/bkpDB.bin";
1351 EXPECT_TRUE(g_nbBackupDelegate->Export(filePath, g_filePasswd1) == OK);
1352
1353 /**
1354 * @tc.steps: step1. device A call SetKvStoreCorruptionHandler to register CorruptCallBackOfImport.
1355 * @tc.expected: step1. call successfully.
1356 */
1357 KvStoreNbCorruptInfo corruptInfo;
1358 CallBackParam pathResult = {filePath, true};
1359 auto notifier = bind(&KvStoreNbCorruptInfo::CorruptCallBackOfImport, &corruptInfo,
1360 placeholders::_1, placeholders::_2, placeholders::_3, g_nbBackupDelegate, pathResult);
1361 g_manager->SetKvStoreCorruptionHandler(notifier);
1362 EXPECT_TRUE(pathResult.result);
1363 /**
1364 * @tc.steps: step2. device A modify the db files to trigger the CorruptCallBackOfImport and check.
1365 * @tc.expected: step2. operate successfully and import the recover db files in callback successfully.
1366 */
1367 EXPECT_TRUE(g_nbBackupDelegate->Delete(KEY_1) == OK);
1368 std::string dbFliePath = DistributedDBNbTestTools::GetKvNbStoreDirectory(g_dbParameter1);
1369 EXPECT_TRUE(DistributedDBNbTestTools::ModifyDatabaseFile(dbFliePath));
1370 EXPECT_TRUE(DistributedDBNbTestTools::ModifyDatabaseFile(dbFliePath + "-wal"));
1371 EXPECT_EQ(g_nbBackupDelegate->Put(KEY_1, VALUE_1), INVALID_PASSWD_OR_CORRUPTED_DB);
1372 std::this_thread::sleep_for(std::chrono::seconds(UNIQUE_SECOND)); // wait for callback complete for 1 second.
1373 Value valueResult;
1374 EXPECT_TRUE(g_nbBackupDelegate->Get(KEY_1, valueResult) == OK);
1375 EXPECT_EQ(valueResult, VALUE_1);
1376
1377 /**
1378 * @tc.steps: step3. device A call SetKvStoreCorruptionHandler again to register CorruptCallBackOfExport.
1379 * @tc.expected: step3. call successfully.
1380 */
1381 filePath = exportPath + "/bkpDB1.bin";
1382 auto notifierNew = bind(&KvStoreNbCorruptInfo::CorruptCallBackOfExport, &corruptInfo,
1383 placeholders::_1, placeholders::_2, placeholders::_3, g_nbBackupDelegate, pathResult);
1384 g_manager->SetKvStoreCorruptionHandler(notifierNew);
1385 EXPECT_TRUE(pathResult.result);
1386
1387 /**
1388 * @tc.steps: step4. device A modify the db files to trigger the CorruptCallBackOfExport and check.
1389 * @tc.expected: step4. operate successfully and export the recover db data in callback failed.
1390 */
1391 EXPECT_TRUE(DistributedDBNbTestTools::ModifyDatabaseFile(dbFliePath));
1392 EXPECT_EQ(g_nbBackupDelegate->Put(KEY_1, VALUE_1), INVALID_PASSWD_OR_CORRUPTED_DB);
1393 g_manager->SetKvStoreCorruptionHandler(nullptr);
1394 RemoveDir(exportPath);
1395 }
1396
1397 /*
1398 * @tc.name: CorruptionHandler 003
1399 * @tc.desc: Verify that if call SetKvStoreCorruptionHandler(nullptr) will unregister the Corruption Handler.
1400 * @tc.type: FUNC
1401 * @tc.require: SR000D4878
1402 * @tc.author: fengxiaoyun
1403 */
1404 HWTEST_F(DistributeddbNbBackupTest, CorruptionHandler003, TestSize.Level2)
1405 {
1406 EXPECT_TRUE(g_nbBackupDelegate->Put(KEY_1, VALUE_1) == OK);
1407 const std::string exportPath = DistributedDBConstant::NB_DIRECTOR + "export";
1408 SetDir(exportPath);
1409 std::string filePath = exportPath + "/bkpDB.bin";
1410 EXPECT_TRUE(g_nbBackupDelegate->Export(filePath, g_filePasswd1) == OK);
1411
1412 /**
1413 * @tc.steps: step1. device A's db1 call SetKvStoreCorruptionHandler to register CorruptCallBack.
1414 * @tc.expected: step1. call successfully.
1415 */
1416 KvStoreNbCorruptInfo corruptInfo;
1417 bool isCalled = false;
1418 auto notifier = bind(&KvStoreNbCorruptInfo::CorruptCallBack, &corruptInfo,
1419 placeholders::_1, placeholders::_2, placeholders::_3, std::ref(isCalled));
1420 g_manager->SetKvStoreCorruptionHandler(notifier);
1421
1422 /**
1423 * @tc.steps: step2. device A's db2 call SetKvStoreCorruptionHandler to register CorruptCallBackOfImport.
1424 * @tc.expected: step2. call successfully.
1425 */
1426 KvStoreDelegateManager *manager = nullptr;
1427 KvStoreNbDelegate *delegate = nullptr;
1428 delegate = DistributedDBNbTestTools::GetNbDelegateSuccess(manager, g_dbParameter2, g_option);
1429 ASSERT_TRUE(manager != nullptr && delegate != nullptr);
1430 KvStoreNbCorruptInfo corruptInfoNew;
1431 CallBackParam pathResult = {filePath, true};
1432 auto notifierNew = bind(&KvStoreNbCorruptInfo::CorruptCallBackOfImport, &corruptInfoNew,
1433 placeholders::_1, placeholders::_2, placeholders::_3, g_nbBackupDelegate, pathResult);
1434 manager->SetKvStoreCorruptionHandler(notifierNew);
1435 EXPECT_TRUE(pathResult.result);
1436
1437 /**
1438 * @tc.steps: step3. device A modify the db files to trigger the CorruptCallBackOfImport and check.
1439 * @tc.expected: step3. operate successfully and import the recover db files in callback successfully.
1440 */
1441 std::string dbFliePath = DistributedDBNbTestTools::GetKvNbStoreDirectory(g_dbParameter1);
1442 EXPECT_TRUE(DistributedDBNbTestTools::ModifyDatabaseFile(dbFliePath));
1443 EXPECT_TRUE(DistributedDBNbTestTools::ModifyDatabaseFile(dbFliePath + "-wal"));
1444 EXPECT_EQ(g_nbBackupDelegate->Put(KEY_1, VALUE_1), INVALID_PASSWD_OR_CORRUPTED_DB);
1445 std::this_thread::sleep_for(std::chrono::seconds(TWO_SECONDS)); // wait for callback complete for 1 second.
1446 Value valueResult;
1447 EXPECT_EQ(g_nbBackupDelegate->Get(KEY_1, valueResult), OK);
1448 EXPECT_EQ(valueResult, VALUE_1);
1449
1450 /**
1451 * @tc.steps: step4. device A call SetKvStoreCorruptionHandler again to register nullptr.
1452 * @tc.expected: step4. call successfully.
1453 */
1454 manager->SetKvStoreCorruptionHandler(nullptr);
1455
1456 /**
1457 * @tc.steps: step5. device A modify the db files to trigger the CorruptCallBack and check.
1458 * @tc.expected: step5. put return error but trigger the CorruptCallBack failed.
1459 */
1460 EXPECT_TRUE(delegate->Put(KEY_1, VALUE_1) == OK);
1461 dbFliePath = DistributedDBNbTestTools::GetKvNbStoreDirectory(g_dbParameter2);
1462 EXPECT_TRUE(DistributedDBNbTestTools::ModifyDatabaseFile(dbFliePath));
1463 EXPECT_TRUE(DistributedDBNbTestTools::ModifyDatabaseFile(dbFliePath + "-wal"));
1464 EXPECT_EQ(delegate->Put(KEY_1, VALUE_1), INVALID_PASSWD_OR_CORRUPTED_DB);
1465 std::this_thread::sleep_for(std::chrono::seconds(UNIQUE_SECOND)); // wait for callback complete for 1 second.
1466 EXPECT_EQ(delegate->Get(KEY_1, valueResult), INVALID_PASSWD_OR_CORRUPTED_DB);
1467
1468 EXPECT_EQ((manager->CloseKvStore(delegate)), OK);
1469 delegate = nullptr;
1470 manager->DeleteKvStore(STORE_ID_2);
1471 delete manager;
1472 manager = nullptr;
1473 RemoveDir(exportPath);
1474 }
1475 #ifndef DB_DEBUG_ENV
1476 /*
1477 * @tc.name: CompatibilityTest 001
1478 * @tc.desc: test that use RELEASE_VERSION11.0.0 can import the export file by RELEASE_VERSION10.1.0.
1479 * @tc.type: Compatibility
1480 * @tc.require: SR000EPA24
1481 * @tc.author: fengxiaoyun
1482 */
1483 #ifdef NB_BACKUP
1484 HWTEST_F(DistributeddbNbBackupTest, CompatibilityTest001, TestSize.Level3)
1485 {
1486 const std::string exportPath = "/data/";
1487 std::string filePath = exportPath + "/RELEASE_VERSION1010.bin";
1488 #define COMPATIBILITYTEST_001
1489 #ifndef COMPATIBILITYTEST_001
1490 /**
1491 * @tc.steps: step1. create the db and put some data then export in RELEASE_VERSION10.1.0.
1492 * @tc.expected: step1. operate successfully.
1493 */
1494 EXPECT_TRUE(g_nbBackupDelegate->PutLocal(KEY_1, VALUE_1) == OK);
1495 EXPECT_TRUE(g_nbBackupDelegate->Put(KEY_1, VALUE_1) == OK);
1496 EXPECT_TRUE(g_nbBackupDelegate->PutLocal(KEY_2, VALUE_1) == OK);
1497 EXPECT_TRUE(g_nbBackupDelegate->Put(KEY_2, VALUE_2) == OK);
1498 EXPECT_TRUE(g_nbBackupDelegate->Delete(KEY_2) == OK);
1499 EXPECT_TRUE(g_nbBackupDelegate->Export(filePath, NULL_PASSWD) == OK);
1500 #else
1501 /**
1502 * @tc.steps: step2. import the export file by step1 and check data.
1503 * @tc.expected: step2. import successfully.
1504 */
1505 EXPECT_TRUE(g_nbBackupDelegate->Import(filePath, NULL_PASSWD) == OK);
1506 Value resultValue;
1507 EXPECT_TRUE(g_nbBackupDelegate->GetLocal(KEY_1, resultValue) == OK);
1508 EXPECT_TRUE(resultValue == VALUE_1);
1509 EXPECT_TRUE(g_nbBackupDelegate->GetLocal(KEY_2, resultValue) == OK);
1510 EXPECT_TRUE(resultValue == VALUE_1);
1511 EXPECT_TRUE(g_nbBackupDelegate->Get(KEY_1, resultValue) == OK);
1512 EXPECT_TRUE(resultValue == VALUE_1);
1513 EXPECT_TRUE(g_nbBackupDelegate->Get(KEY_2, resultValue) == NOT_FOUND);
1514 #endif
1515 }
1516 #endif
1517 #endif
1518 }