• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include <gtest/gtest.h>
17 
18 #include "db_errno.h"
19 #include "db_common.h"
20 #include "distributeddb_data_generate_unit_test.h"
21 #include "lock_status_observer.h"
22 #include "log_print.h"
23 #include "platform_specific.h"
24 #include "task_queue.h"
25 #include "time_tick_monitor.h"
26 #include "user_change_monitor.h"
27 #include "runtime_context_impl.h"
28 
29 using namespace testing::ext;
30 using namespace DistributedDB;
31 using namespace DistributedDBUnitTest;
32 
33 namespace {
34     std::string g_testDir;
35 
36     // define some variables to init a KvStoreDelegateManager object.
37     KvStoreDelegateManager g_mgr(APP_ID, USER_ID);
38     KvStoreConfig g_config;
39 
40     // define the g_kvDelegateCallback, used to get some information when open a kv store.
41     DBStatus g_kvDelegateStatus = INVALID_ARGS;
42 
43     KvStoreNbDelegate *g_kvNbDelegatePtr = nullptr;
44     auto g_kvNbDelegateCallback = bind(&DistributedDBToolsUnitTest::KvStoreNbDelegateCallback,
45         std::placeholders::_1, std::placeholders::_2, std::ref(g_kvDelegateStatus), std::ref(g_kvNbDelegatePtr));
46 
47 class DistributedDBCommonTest : public testing::Test {
48 public:
49     static void SetUpTestCase(void);
50     static void TearDownTestCase(void);
51     void SetUp();
52     void TearDown();
53 };
54 
SetUpTestCase(void)55 void DistributedDBCommonTest::SetUpTestCase(void)
56 {
57     DistributedDBToolsUnitTest::TestDirInit(g_testDir);
58     g_config.dataDir = g_testDir;
59     g_mgr.SetKvStoreConfig(g_config);
60 }
61 
TearDownTestCase(void)62 void DistributedDBCommonTest::TearDownTestCase(void) {}
63 
SetUp(void)64 void DistributedDBCommonTest::SetUp(void)
65 {
66     DistributedDBToolsUnitTest::PrintTestCaseInfo();
67     DistributedDBToolsUnitTest::TestDirInit(g_testDir);
68 }
69 
TearDown(void)70 void DistributedDBCommonTest::TearDown(void)
71 {
72     if (DistributedDBToolsUnitTest::RemoveTestDbFiles(g_testDir) != 0) {
73         LOGI("rm test db files error!");
74     }
75 }
76 
77 /**
78  * @tc.name: RemoveAllFilesOfDirectory
79  * @tc.desc: Test delete all file and dir.
80  * @tc.type: FUNC
81  * @tc.require:
82  * @tc.author: sunpeng
83  */
84 HWTEST_F(DistributedDBCommonTest, RemoveAllFilesOfDirectory, TestSize.Level1)
85 {
86     EXPECT_EQ(DBCommon::CreateDirectory(g_testDir + "/dirLevel1_1/"), E_OK);
87     EXPECT_EQ(DBCommon::CreateDirectory(g_testDir + "/dirLevel1_1/" + "/dirLevel2_1/"), E_OK);
88     EXPECT_EQ(DBCommon::CreateDirectory(g_testDir + "/dirLevel1_1/" + "/dirLevel2_2/"), E_OK);
89     EXPECT_EQ(DBCommon::CreateDirectory(g_testDir + "/dirLevel1_1/" + "/dirLevel2_2/" + "/dirLevel3_1/"), E_OK);
90 
91     EXPECT_EQ(OS::CreateFileByFileName(g_testDir + "/fileLevel1_1"), E_OK);
92     EXPECT_EQ(OS::CreateFileByFileName(g_testDir + "/dirLevel1_1/" + "/fileLevel2_1"), E_OK);
93     EXPECT_EQ(DBCommon::CreateDirectory(g_testDir + "/dirLevel1_1/" + "/dirLevel2_2/" +
94         "/dirLevel3_1/"+ "/fileLevel4_1/"), E_OK);
95 
96     EXPECT_EQ(DBCommon::RemoveAllFilesOfDirectory(g_testDir), E_OK);
97 
98     EXPECT_EQ(OS::CheckPathExistence(g_testDir), false);
99 }
100 
101 #ifdef RUNNING_ON_LINUX
102 /**
103  * @tc.name: InvalidArgsTest001
104  * @tc.desc: Test invalid args for file operation.
105  * @tc.type: FUNC
106  * @tc.require:
107  * @tc.author: zhangshijie
108  */
109 HWTEST_F(DistributedDBCommonTest, InvalidArgsTest001, TestSize.Level1)
110 {
111     EXPECT_EQ(OS::CloseFile(nullptr), -E_INVALID_ARGS);
112     EXPECT_EQ(OS::FileLock(nullptr, false), -E_INVALID_ARGS);
113     // unlock nullptr will return E_OK
114     EXPECT_EQ(OS::FileUnlock(nullptr), E_OK);
115 }
116 
117 /**
118  * @tc.name: SameProcessReLockFile
119  * @tc.desc: Test same process repeat lock same file.
120  * @tc.type: FUNC
121  * @tc.require:
122  * @tc.author: sunpeng
123  */
124 HWTEST_F(DistributedDBCommonTest, SameProcessReLockFile, TestSize.Level1)
125 {
126     // block mode
127     EXPECT_EQ(OS::CreateFileByFileName(g_testDir + "/blockmode"), E_OK);
128     OS::FileHandle *fd = nullptr;
129     EXPECT_EQ(OS::OpenFile(g_testDir + "/blockmode", fd), E_OK);
130 
131     EXPECT_EQ(OS::FileLock(fd, true), E_OK);
132     EXPECT_EQ(OS::FileLock(fd, true), E_OK);
133 
134     // normal mode
135     OS::FileHandle *fd2 = nullptr;
136     EXPECT_EQ(OS::CreateFileByFileName(g_testDir + "/normalmode"), E_OK);
137     EXPECT_EQ(OS::OpenFile(g_testDir + "/normalmode", fd2), E_OK);
138     EXPECT_EQ(OS::FileLock(fd2, true), E_OK);
139     EXPECT_EQ(OS::FileLock(fd2, true), E_OK);
140 
141     // unlock
142     EXPECT_EQ(OS::FileUnlock(fd), E_OK);
143     EXPECT_EQ(OS::CloseFile(fd), E_OK);
144     EXPECT_EQ(OS::FileUnlock(fd2), E_OK);
145     EXPECT_EQ(OS::CloseFile(fd2), E_OK);
146 }
147 
148 /**
149  * @tc.name: SameProcessReUnLockFile
150  * @tc.desc: Test same process repeat lock same file.
151  * @tc.type: FUNC
152  * @tc.require:
153  * @tc.author: sunpeng
154  */
155 HWTEST_F(DistributedDBCommonTest, SameProcessReUnLockFile, TestSize.Level1)
156 {
157     // unlock normal file twice
158     EXPECT_EQ(OS::CreateFileByFileName(g_testDir + "/normalmode"), E_OK);
159     OS::FileHandle *fd = nullptr;
160     EXPECT_EQ(OS::OpenFile(g_testDir + "/normalmode", fd), E_OK);
161     EXPECT_EQ(OS::FileUnlock(fd), E_OK);
162     EXPECT_EQ(OS::CloseFile(fd), E_OK);
163 
164     // block mode
165     EXPECT_EQ(OS::CreateFileByFileName(g_testDir + "/blockmode"), E_OK);
166     EXPECT_EQ(OS::OpenFile(g_testDir + "/blockmode", fd), E_OK);
167 
168     EXPECT_EQ(OS::FileLock(fd, false), E_OK);
169     EXPECT_EQ(OS::FileLock(fd, false), E_OK);
170     EXPECT_EQ(OS::FileUnlock(fd), E_OK);
171     EXPECT_EQ(OS::CloseFile(fd), E_OK);
172 }
173 
174 /**
175  * @tc.name: CalcFileSizeTest
176  * @tc.desc: Test the file size for function test and the performance test.
177  * @tc.type: FUNC
178  * @tc.require:
179  * @tc.author: wangbingquan
180  */
181 HWTEST_F(DistributedDBCommonTest, CalcFileSizeTest, TestSize.Level1)
182 {
183     std::string filePath = g_testDir + "/testFileSize";
184     std::ofstream ofs(filePath, std::ofstream::out);
185     ASSERT_TRUE(ofs.good());
186     ofs << "test file size";
187     ofs.close();
188     uint64_t fileSize = 0;
189     EXPECT_EQ(OS::CalFileSize(filePath, fileSize), E_OK);
190     EXPECT_GT(fileSize, 0ULL);
191     EXPECT_EQ(OS::RemoveFile(filePath), E_OK);
192 }
193 
194 // Distributed db is not recommended to use multiple processes to access
195 // This testcase only guard for some wrong use on current product
196 #if defined(RUN_MULTI_PROCESS_TEST)
197 namespace {
198 // use file sync diff process information
waitForStep(int step,int retryTimes)199 bool waitForStep(int step, int retryTimes)
200 {
201     std::this_thread::sleep_for(std::chrono::milliseconds(1));
202     while (retryTimes >= 0 && !OS::CheckPathExistence(g_testDir + "/LOCK_step_" + std::to_string(step))) {
203         retryTimes = retryTimes - 1; // wait 10ms one times
204         std::this_thread::sleep_for(std::chrono::milliseconds(10)); // once 10 ms
205     }
206     return (retryTimes > 0);
207 }
208 
createStepFlag(int step)209 void createStepFlag(int step)
210 {
211     EXPECT_EQ(OS::CreateFileByFileName(g_testDir + "/LOCK_step_" + std::to_string(step)), E_OK);
212 }
213 }
214 
215 /**
216  * @tc.name: DiffProcessLockFile
217  * @tc.desc: Test different process repeat lock same file.
218  * @tc.type: FUNC
219  * @tc.require:
220  * @tc.author: sunpeng
221  */
222 HWTEST_F(DistributedDBCommonTest, DiffProcessLockFile, TestSize.Level1)
223 {
224     OS::FileHandle *fd = nullptr;
225     EXPECT_EQ(OS::OpenFile(g_testDir + DBConstant::DB_LOCK_POSTFIX, fd), E_OK);
226     EXPECT_EQ(OS::FileLock(fd, false), E_OK);
227     sleep(1);
228     LOGI("begin fork new process!!");
229     pid_t pid = fork();
230     ASSERT_TRUE(pid >= 0);
231     if (pid == 0) {
232         LOGI("child process begin!");
233         OS::FileHandle ChildFd;
234         EXPECT_EQ(OS::OpenFile(g_testDir + DBConstant::DB_LOCK_POSTFIX, ChildFd), E_OK);
235         ASSERT_TRUE(waitForStep(1, 10));
236         EXPECT_EQ(OS::FileLock(ChildFd, false), -E_BUSY);
237         createStepFlag(2);
238         EXPECT_EQ(OS::CloseFile(ChildFd), E_OK);
239         exit(0);
240     } else {
241         LOGI("main process begin!");
242         EXPECT_EQ(OS::FileLock(fd, false), E_OK);
243         createStepFlag(1);
244 
245         ASSERT_TRUE(waitForStep(2, 100));
246         EXPECT_EQ(OS::CloseFile(fd), E_OK); // fd close, lock invalid
247     }
248 }
249 
250 /**
251  * @tc.name: DiffProcessLockFileBlocked
252  * @tc.desc: Test different process repeat lock same file.
253  * @tc.type: FUNC
254  * @tc.require:
255  * @tc.author: sunpeng
256  */
257 HWTEST_F(DistributedDBCommonTest, DiffProcessLockFileBlocked, TestSize.Level1)
258 {
259     EXPECT_EQ(OS::CreateFileByFileName(g_testDir + DBConstant::DB_LOCK_POSTFIX), E_OK);
260     OS::FileHandle fd;
261     EXPECT_EQ(OS::OpenFile(g_testDir + DBConstant::DB_LOCK_POSTFIX, fd), E_OK);
262     EXPECT_EQ(OS::FileLock(fd, true), E_OK);
263     sleep(1);
264     LOGI("begin fork new process!!");
265     int count = 10; // wait 10 times 10 ms for block wait
266     pid_t pid = fork();
267     ASSERT_TRUE(pid >= 0);
268     if (pid == 0) {
269         LOGI("child process begin!");
270         EXPECT_FALSE(OS::CheckPathExistence(g_testDir + "/LOCK_step_1"));
271         OS::FileHandle ChildFd;
272         EXPECT_EQ(OS::OpenFile(g_testDir + DBConstant::DB_LOCK_POSTFIX, ChildFd), E_OK);
273         EXPECT_EQ(OS::FileLock(ChildFd, true), E_OK);
274         createStepFlag(1);
275         EXPECT_EQ(OS::FileUnlock(ChildFd), E_OK);
276         EXPECT_EQ(OS::CloseFile(ChildFd), E_OK);
277         LOGI("child process finish!");
278         exit(0);
279     } else {
280         LOGI("main process begin!");
281         while (count--) {
282             LOGI("main process waiting!");
283             std::this_thread::sleep_for(std::chrono::milliseconds(10)); // once 10 ms
284         }
285         ASSERT_FALSE(waitForStep(1, 10));
286         EXPECT_EQ(OS::FileUnlock(fd), E_OK);
287         EXPECT_EQ(OS::CloseFile(fd), E_OK);
288         ASSERT_TRUE(waitForStep(1, 10));
289     }
290 }
291 
292 /**
293   * @tc.name: DiffProcessGetDBBlocked
294   * @tc.desc: Test block other process get kvstore when db locked.
295   * @tc.type: FUNC
296   * @tc.require:
297   * @tc.author: sunpeng
298   */
299 HWTEST_F(DistributedDBCommonTest, DiffProcessGetDBBlocked, TestSize.Level1)
300 {
301     std::string storeId = "DiffProcessGetDBBlocked";
302     std::string origId = USER_ID + "-" + APP_ID + "-" + storeId;
303     std::string identifier = DBCommon::TransferHashString(origId);
304     std::string hexDir = DBCommon::TransferStringToHex(identifier);
305     std::string lockFile = g_testDir + "/" + hexDir + DBConstant::DB_LOCK_POSTFIX;
306     EXPECT_EQ(DBCommon::CreateDirectory(g_testDir + "/" + hexDir), E_OK);
307     EXPECT_EQ(OS::CreateFileByFileName(lockFile), E_OK);
308     LOGI("Create lock file[%s]", lockFile.c_str());
309 
310     LOGI("begin fork new process!!");
311     pid_t pid = fork();
312     OS::FileHandle fd;
313     ASSERT_TRUE(pid >= 0);
314     if (pid == 0) {
315         LOGI("child process begin!");
316         ASSERT_TRUE(waitForStep(1, 10));
317         KvStoreNbDelegate::Option option = {true, false, false};
318         option.isNeedIntegrityCheck = true;
319         g_mgr.GetKvStore(storeId, option, g_kvNbDelegateCallback);
320         EXPECT_TRUE(g_kvDelegateStatus == BUSY);
321         ASSERT_TRUE(g_kvNbDelegatePtr == nullptr);
322         createStepFlag(2);
323         exit(0);
324     } else {
325         LOGI("main process begin!");
326         EXPECT_EQ(OS::OpenFile(lockFile, fd), E_OK);
327         EXPECT_EQ(OS::FileLock(fd, false), E_OK);
328         createStepFlag(1);
329     }
330 
331     // Prevent the child process from not being completed, the main process ends to clean up resources
332     EXPECT_TRUE(waitForStep(2, 1000));
333     EXPECT_EQ(OS::FileUnlock(fd), E_OK);
334     EXPECT_EQ(OS::CloseFile(fd), E_OK);
335 }
336 
337 /**
338   * @tc.name: DiffProcessDeleteDBBlocked
339   * @tc.desc: Test block other process delete kvstore when db locked.
340   * @tc.type: FUNC
341   * @tc.require:
342   * @tc.author: sunpeng
343   */
344 HWTEST_F(DistributedDBCommonTest, DiffProcessDeleteDBBlocked, TestSize.Level1)
345 {
346     std::string storeId = "DiffProcessDeleteDBBlocked";
347     std::string origId = USER_ID + "-" + APP_ID + "-" + storeId;
348     std::string identifier = DBCommon::TransferHashString(origId);
349     std::string hexDir = DBCommon::TransferStringToHex(identifier);
350     std::string lockFile = g_testDir + "/" + hexDir + DBConstant::DB_LOCK_POSTFIX;
351     EXPECT_EQ(DBCommon::CreateDirectory(g_testDir + "/" + hexDir), E_OK);
352     EXPECT_EQ(OS::CreateFileByFileName(lockFile), E_OK);
353     LOGI("Create lock file[%s]", lockFile.c_str());
354 
355     KvStoreNbDelegate::Option option = {true, false, false};
356     option.isNeedIntegrityCheck = true;
357     g_mgr.GetKvStore(storeId, option, g_kvNbDelegateCallback);
358     ASSERT_TRUE(g_kvNbDelegatePtr != nullptr);
359     EXPECT_TRUE(g_kvDelegateStatus == OK);
360 
361     LOGI("begin fork new process!!");
362     pid_t pid = fork();
363     OS::FileHandle fd;
364     ASSERT_TRUE(pid >= 0);
365     if (pid == 0) {
366         LOGI("child process begin!");
367         ASSERT_TRUE(waitForStep(1, 10));
368         EXPECT_EQ(g_mgr.DeleteKvStore(storeId), BUSY);
369         createStepFlag(2);
370         exit(0);
371     } else {
372         LOGI("main process begin!");
373         EXPECT_EQ(OS::OpenFile(lockFile, fd), E_OK);
374         EXPECT_EQ(OS::FileLock(fd, false), E_OK);
375         createStepFlag(1);
376     }
377 
378     // Prevent the child process from not being completed, the main process ends to clean up resources
379     EXPECT_TRUE(waitForStep(2, 1000));
380     EXPECT_EQ(OS::FileUnlock(fd), E_OK);
381     EXPECT_EQ(OS::CloseFile(fd), E_OK);
382     g_mgr.CloseKvStore(g_kvNbDelegatePtr);
383 }
384 
385 /**
386   * @tc.name: DiffProcessGetDBBlocked001
387   * @tc.desc: Test block other process get kvstore when db locked.
388   * @tc.type: FUNC
389   * @tc.require:
390   * @tc.author: sunpeng
391   */
392 HWTEST_F(DistributedDBCommonTest, DiffProcessGetDBBlocked001, TestSize.Level1)
393 {
394     std::string storeId = "DiffProcessGetDBBlocked001";
395     std::string origId = USER_ID + "-" + APP_ID + "-" + storeId;
396     std::string identifier = DBCommon::TransferHashString(origId);
397     std::string hexDir = DBCommon::TransferStringToHex(identifier);
398     std::string lockFile = g_testDir + "/" + hexDir + DBConstant::DB_LOCK_POSTFIX;
399     EXPECT_EQ(DBCommon::CreateDirectory(g_testDir + "/" + hexDir), E_OK);
400     EXPECT_EQ(OS::CreateFileByFileName(lockFile), E_OK);
401     LOGI("Create lock file[%s]", lockFile.c_str());
402 
403     LOGI("begin fork new process!!");
404     pid_t pid = fork();
405     OS::FileHandle fd;
406     ASSERT_TRUE(pid >= 0);
407     if (pid == 0) {
408         LOGI("child process begin!");
409         ASSERT_TRUE(waitForStep(1, 10));
410         KvStoreNbDelegate::Option option = {true, false, false};
411         option.isNeedIntegrityCheck = true;
412         g_mgr.GetKvStore(storeId, option, g_kvNbDelegateCallback);
413         ASSERT_TRUE(g_kvNbDelegatePtr != nullptr);
414         EXPECT_TRUE(g_kvDelegateStatus == OK);
415         createStepFlag(2);
416         exit(0);
417     } else {
418         LOGI("main process begin!");
419         EXPECT_EQ(OS::OpenFile(lockFile, fd), E_OK);
420         EXPECT_EQ(OS::FileLock(fd, false), E_OK);
421         createStepFlag(1);
422     }
423     ASSERT_TRUE(waitForStep(1, 100));
424 
425     EXPECT_EQ(OS::FileUnlock(fd), E_OK);
426     EXPECT_EQ(OS::CloseFile(fd), E_OK);
427 
428     ASSERT_TRUE(waitForStep(2, 100));
429 }
430 
431 /**
432   * @tc.name: DiffProcessGetDB
433   * @tc.desc: Test block other process get kvstore.
434   * @tc.type: FUNC
435   * @tc.require:
436   * @tc.author: sunpeng
437   */
438 HWTEST_F(DistributedDBCommonTest, DiffProcessGetDB, TestSize.Level1)
439 {
440     std::string storeId = "DiffProcessGetDB";
441     KvStoreNbDelegate::Option option = {true, false, false};
442     option.isNeedIntegrityCheck = true;
443     LOGI("begin fork new process!!");
444     pid_t pid = fork();
445     ASSERT_TRUE(pid >= 0);
446     if (pid == 0) {
447         LOGI("child process begin!");
448         g_mgr.GetKvStore(storeId, option, g_kvNbDelegateCallback);
449         ASSERT_TRUE(g_kvNbDelegatePtr != nullptr);
450         EXPECT_TRUE(g_kvDelegateStatus == OK);
451         createStepFlag(2);
452         EXPECT_TRUE(waitForStep(1, 1000));
453         exit(0);
454     } else {
455         LOGI("main process begin!");
456         g_mgr.GetKvStore(storeId, option, g_kvNbDelegateCallback);
457         ASSERT_TRUE(g_kvNbDelegatePtr != nullptr);
458         EXPECT_TRUE(g_kvDelegateStatus == OK);
459         createStepFlag(1);
460     }
461     EXPECT_TRUE(waitForStep(2, 100));
462     // Prevent the child process from not being completed, the main process ends to clean up resources
463     g_mgr.CloseKvStore(g_kvNbDelegatePtr);
464 }
465 
466 /**
467   * @tc.name: DiffProcessDeleteDB
468   * @tc.desc: Test block other process delete kvstore.
469   * @tc.type: FUNC
470   * @tc.require:
471   * @tc.author: sunpeng
472   */
473 HWTEST_F(DistributedDBCommonTest, DiffProcessDeleteDB, TestSize.Level1)
474 {
475     std::string storeId = "DiffProcessGetDB";
476     KvStoreNbDelegate::Option option = {true, false, false};
477     option.isNeedIntegrityCheck = true;
478     g_mgr.GetKvStore(storeId, option, g_kvNbDelegateCallback);
479     ASSERT_TRUE(g_kvNbDelegatePtr != nullptr);
480     EXPECT_TRUE(g_kvDelegateStatus == OK);
481     g_mgr.CloseKvStore(g_kvNbDelegatePtr);
482     LOGI("begin fork new process!!");
483     pid_t pid = fork();
484     ASSERT_TRUE(pid >= 0);
485     if (pid == 0) {
486         LOGI("child process begin!");
487         g_mgr.GetKvStore(storeId, option, g_kvNbDelegateCallback);
488         ASSERT_TRUE(g_kvNbDelegatePtr != nullptr);
489         EXPECT_TRUE(g_kvDelegateStatus == OK);
490         createStepFlag(2);
491         EXPECT_TRUE(waitForStep(1, 1000));
492         exit(0);
493     } else {
494         LOGI("main process begin!");
495         g_mgr.DeleteKvStore(storeId);
496         createStepFlag(1);
497     }
498     EXPECT_TRUE(waitForStep(2, 100));
499 
500     // Prevent the child process from not being completed, the main process ends to clean up resources
501     EXPECT_TRUE(waitForStep(1, 100));
502 }
503 
504 /**
505   * @tc.name: DiffProcessGetAndDeleteDB
506   * @tc.desc: Test block other process delete kvstore.
507   * @tc.type: FUNC
508   * @tc.require:
509   * @tc.author: sunpeng
510   */
511 HWTEST_F(DistributedDBCommonTest, DiffProcessGetAndDeleteDB, TestSize.Level1)
512 {
513     std::string storeId = "DiffProcessGetAndDeleteDB";
514     KvStoreNbDelegate::Option option = {true, false, false};
515     option.isNeedIntegrityCheck = true;
516     g_mgr.GetKvStore(storeId, option, g_kvNbDelegateCallback);
517     ASSERT_TRUE(g_kvNbDelegatePtr != nullptr);
518     EXPECT_TRUE(g_kvDelegateStatus == OK);
519     g_mgr.CloseKvStore(g_kvNbDelegatePtr);
520     LOGI("begin fork new process!!");
521     pid_t pid = fork();
522     ASSERT_TRUE(pid >= 0);
523     if (pid == 0) {
524         LOGI("child process begin!");
525         g_mgr.DeleteKvStore(storeId); // one process OK, one process NOT_FOUND
526         createStepFlag(2);
527         EXPECT_TRUE(waitForStep(1, 1000));
528         exit(0);
529     } else {
530         LOGI("main process begin!");
531         g_mgr.DeleteKvStore(storeId);
532         createStepFlag(1);
533     }
534     EXPECT_TRUE(waitForStep(2, 100));
535 
536     // Prevent the child process from not being completed, the main process ends to clean up resources
537     EXPECT_TRUE(waitForStep(1, 1000));
538 }
539 #endif
540 #endif
541 
542 HWTEST_F(DistributedDBCommonTest, StringCaseTest002, TestSize.Level0)
543 {
544     EXPECT_TRUE(DBCommon::CaseInsensitiveCompare("HELLO WORLD.", "hello world."));
545     EXPECT_TRUE(DBCommon::CaseInsensitiveCompare("ABCDEFGHIJKLMN", "abcdefghijklmn"));
546     EXPECT_TRUE(DBCommon::CaseInsensitiveCompare("OPQRSTUVWXYZ", "opqrstuvwxyz"));
547     EXPECT_FALSE(DBCommon::CaseInsensitiveCompare("sqlite", "sqlite3"));
548     EXPECT_FALSE(DBCommon::CaseInsensitiveCompare("gitee", "git"));
549 }
550 
551 HWTEST_F(DistributedDBCommonTest, PerformanceAnalysisTest001, TestSize.Level1)
552 {
553     int threadCount = 1000;
554     int count1 = 0;
555     int count2 = 0;
556     for (int i = 0; i < threadCount; i++) {
__anon5e0581ef0302null557         std::thread t1([&count1] {
558             PerformanceAnalysis::GetInstance(20); // 20 is stepNum
559             count1++;
560         });
561 
__anon5e0581ef0402null562         std::thread t2([&count2] {
563             PerformanceAnalysis::GetInstance(20); // 20 is stepNum
564             count2++;
565         });
566 
567         t1.join();
568         t2.join();
569     }
570     EXPECT_EQ(count2, threadCount);
571     EXPECT_EQ(count1, threadCount);
572 }
573 
574 /**
575  * @tc.name: PerformanceAnalysisTest002
576  * @tc.desc: Test PerformanceAnalysis interfaces.
577  * @tc.type: FUNC
578  * @tc.require:
579  * @tc.author: suyue
580  */
581 HWTEST_F(DistributedDBCommonTest, PerformanceAnalysisTest002, TestSize.Level1)
582 {
583     /**
584      * @tc.steps: step1. Get PerformanceAnalysis instance and call interfaces.
585      * @tc.expected: step1. success.
586      */
587     PerformanceAnalysis *performance = PerformanceAnalysis::GetInstance(5); // 5 is stepNum
588     ASSERT_NE(performance, nullptr);
589     performance->SetFileName("test");
590     performance->OpenPerformanceAnalysis();
591     performance->TimeRecordStart();
592     performance->TimeRecordEnd();
593 
594     /**
595      * @tc.steps: step2. Call interfaces with the para is greater than stepNum.
596      * @tc.expected: step2. success.
597      */
598     performance->StepTimeRecordStart(RECORD_ACK_RECV_TO_USER_CALL_BACK);
599     performance->StepTimeRecordEnd(RECORD_ACK_RECV_TO_USER_CALL_BACK);
600     performance->ClosePerformanceAnalysis();
601     performance->GetStatistics();
602 }
603 
604 /**
605  * @tc.name: UserChangeMonitorTest
606  * @tc.desc: Test UserChangeMonitor interfaces.
607  * @tc.type: FUNC
608  * @tc.require:
609  * @tc.author: suyue
610  */
611 HWTEST_F(DistributedDBCommonTest, UserChangeMonitorTest, TestSize.Level1)
612 {
613     /**
614      * @tc.steps: step1. Start UserChangeMonitor.
615      * @tc.expected: step1. success.
616      */
617     UserChangeMonitor monitor;
618     EXPECT_EQ(monitor.Start(), E_OK);
619     monitor.NotifyUserChanged();
620 
621     /**
622      * @tc.steps: step2. Call RegisterUserChangedListener with null action.
623      * @tc.expected: step2. -E_INVALID_ARGS.
624      */
625     int errCode = E_OK;
626     DistributedDB::UserChangedAction action = nullptr;
627     NotificationChain::Listener *ptr = monitor.RegisterUserChangedListener(action,
628         monitor.USER_ACTIVE_TO_NON_ACTIVE_EVENT, errCode);
629     ASSERT_EQ(ptr, nullptr);
630     EXPECT_EQ(errCode, -E_INVALID_ARGS);
631 
632     /**
633      * @tc.steps: step3. Second start UserChangeMonitor.
634      * @tc.expected: step3. success.
635      */
636     EXPECT_EQ(monitor.Start(), E_OK);
637     monitor.Stop();
638     monitor.NotifyUserChanged();
639 }
640 
641 /**
642  * @tc.name: ValueObjectConstructorTest
643  * @tc.desc: Test ValueObjectTest.
644  * @tc.type: FUNC
645  * @tc.require:
646  * @tc.author: suyue
647  */
648 HWTEST_F(DistributedDBCommonTest, ValueObjectConstructorTest, TestSize.Level1)
649 {
650     /**
651      * @tc.steps: step1. Call the default constructor of ValueObject.
652      * @tc.expected: step1. success.
653      */
654     ValueObject valueObj;
655     EXPECT_EQ(valueObj.IsValid(), false);
656 
657     /**
658      * @tc.steps: step2. Call constructor of ValueObject.
659      * @tc.expected: step2. success.
660      */
661     ValueObject valueObj1(valueObj);
662     EXPECT_EQ(valueObj1.IsValid(), false);
663     valueObj = valueObj1;
664 }
665 
666 /**
667  * @tc.name: TimeTickMonitorTest
668  * @tc.desc: Test TimeTickMonitor interfaces.
669  * @tc.type: FUNC
670  * @tc.require:
671  * @tc.author: suyue
672  */
673 HWTEST_F(DistributedDBCommonTest, TimeTickMonitorTest, TestSize.Level1)
674 {
675     /**
676      * @tc.steps: step1. Start TimeTickMonitor.
677      * @tc.expected: step1. success.
678      */
679     TimeTickMonitor monitor;
680     EXPECT_EQ(monitor.StartTimeTickMonitor(), E_OK);
681 
682     /**
683      * @tc.steps: step2. Call RegisterTimeChangedLister with null para.
684      * @tc.expected: step2. -E_INVALID_ARGS.
685      */
686     int errCode = E_OK;
687     DistributedDB::UserChangedAction action = nullptr;
688     TimeFinalizeAction finalize = nullptr;
689     NotificationChain::Listener *ptr = monitor.RegisterTimeChangedLister(action, finalize, errCode);
690     ASSERT_EQ(ptr, nullptr);
691     EXPECT_EQ(errCode, -E_INVALID_ARGS);
692 
693     /**
694      * @tc.steps: step3. Call RegisterTimeChangedLister after Stop TimeTickMonitor.
695      * @tc.expected: step3. success.
696      */
697     EXPECT_EQ(monitor.StartTimeTickMonitor(), E_OK);
698     monitor.StopTimeTickMonitor();
699     monitor.NotifyTimeChange(0);
700 
701     ptr = monitor.RegisterTimeChangedLister(action, finalize, errCode);
702     ASSERT_EQ(ptr, nullptr);
703     EXPECT_EQ(errCode, -E_NOT_INIT);
704 }
705 
706 /**
707  * @tc.name: LockStatusObserverTest
708  * @tc.desc: Test LockStatusObserver interfaces.
709  * @tc.type: FUNC
710  * @tc.require:
711  * @tc.author: suyue
712  */
713 HWTEST_F(DistributedDBCommonTest, LockStatusObserverTest, TestSize.Level1)
714 {
715     /**
716      * @tc.steps: step1. Call RegisterLockStatusChangedLister with null para.
717      * @tc.expected: step1. return -E_INVALID_ARGS.
718      */
719     LockStatusObserver observer;
720     EXPECT_EQ(observer.Start(), E_OK);
721 
722     int errCode = E_OK;
723     DistributedDB::UserChangedAction action = nullptr;
724     NotificationChain::Listener *ptr = observer.RegisterLockStatusChangedLister(action, errCode);
725     ASSERT_EQ(ptr, nullptr);
726     EXPECT_EQ(errCode, -E_INVALID_ARGS);
727 
728     /**
729      * @tc.steps: step2. Call RegisterLockStatusChangedLister after stop observer.
730      * @tc.expected: step2. return -E_NOT_INIT.
731      */
732     EXPECT_EQ(observer.Start(), E_OK);
733     observer.Stop();
734     observer.OnStatusChange(true);
735 
736     ptr = observer.RegisterLockStatusChangedLister(action, errCode);
737     ASSERT_EQ(ptr, nullptr);
738     EXPECT_EQ(errCode, -E_NOT_INIT);
739 }
740 
741 /**
742  * @tc.name: TaskQueueTest
743  * @tc.desc: Test TaskQueue interfaces.
744  * @tc.type: FUNC
745  * @tc.require:
746  * @tc.author: suyue
747  */
748 HWTEST_F(DistributedDBCommonTest, TaskQueueTest, TestSize.Level1)
749 {
750     /**
751      * @tc.steps: step1. Create TaskQueue object whose para is true.
752      * @tc.expected: step1. Create success.
753      */
754     TaskQueue taskObj1(true);
755     const Task task1;
756     taskObj1.PutTask(task1);
757     EXPECT_EQ(taskObj1.IsEmptyAndUnlocked(), true);
758     EXPECT_EQ(taskObj1.CanGetTask(), false);
759 
760     /**
761      * @tc.steps: step2. Create TaskQueue object whose para is false.
762      * @tc.expected: step2. Create success.
763      */
764     TaskQueue taskObj2(false);
765     EXPECT_EQ(taskObj2.IsEmptyAndUnlocked(), true);
766     EXPECT_EQ(taskObj2.CanGetTask(), false);
767 }
768 
769 /**
770  * @tc.name: AbnormalTrackerTableTest
771  * @tc.desc: Test LockStatusObserver interfaces.
772  * @tc.type: FUNC
773  * @tc.require:
774  * @tc.author: suyue
775  */
776 HWTEST_F(DistributedDBCommonTest, AbnormalTrackerTableTest, TestSize.Level1)
777 {
778     /**
779      * @tc.steps: step1. Call GetDiffIncCursorSql interface when TrackerTable is not init.
780      * @tc.expected: step1. return empty string.
781      */
782     TrackerTable trackerObj1;
783     std::string str = trackerObj1.GetDiffIncCursorSql("test1");
784     const std::string emptyStr = "";
785     EXPECT_TRUE(str.compare(0, str.length(), emptyStr) == 0);
786 
787     /**
788      * @tc.steps: step2. Call GetCreateTempTriggerSql interface when para is NONE.
789      * @tc.expected: step2. return empty string.
790      */
791     std::string str1 = trackerObj1.GetCreateTempTriggerSql(TriggerMode::TriggerModeEnum::DELETE);
792     EXPECT_TRUE(str1.compare(0, str1.length(), emptyStr) != 0);
793     std::string str2 = trackerObj1.GetCreateTempTriggerSql(TriggerMode::TriggerModeEnum::NONE);
794     EXPECT_TRUE(str2.compare(0, str2.length(), emptyStr) == 0);
795 
796     /**
797      * @tc.steps: step3. Call ReBuildTempTrigger interface when db is nullptr.
798      * @tc.expected: step3. return -E_INVALID_DB.
799      */
800     int ret = trackerObj1.ReBuildTempTrigger(nullptr, TriggerMode::TriggerModeEnum::NONE, nullptr);
801     EXPECT_EQ(ret, -E_INVALID_DB);
802 
803     /**
804      * @tc.steps: step4. Test IsChanging interface after setting schema info.
805      * @tc.expected: step4. return true.
806      */
807     const TrackerSchema schema = {
808         .tableName = "table1",
809         .extendColNames = {"extendCol1"},
810         .trackerColNames = {"trackerCol1"},
811     };
812     trackerObj1.Init(schema);
813     EXPECT_EQ(trackerObj1.IsChanging(schema), false);
814 
815     const std::set<std::string> trackerNames = {"trackerCol"};
816     trackerObj1.SetTrackerNames(trackerNames);
817     EXPECT_EQ(trackerObj1.IsChanging(schema), true);
818     const std::string colName = "col";
819     trackerObj1.SetExtendNames({colName});
820     std::set<std::string> extendNames = trackerObj1.GetExtendNames();
821     std::string str3 = *extendNames.begin();
822     EXPECT_TRUE(str3.compare(0, str3.length(), colName) == 0);
823     EXPECT_EQ(trackerObj1.IsChanging(schema), true);
824 }
825 }