• 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: AR000FN6G9
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: AR000FN6G9
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: AR000FN6G9
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: AR000FN6G9
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: AR000FN6G9
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         return;
233     }
234     else if (pid == 0) {
235         LOGI("child process begin!");
236         OS::FileHandle ChildFd;
237         EXPECT_EQ(OS::OpenFile(g_testDir + DBConstant::DB_LOCK_POSTFIX, ChildFd), E_OK);
238         ASSERT_TRUE(waitForStep(1, 10));
239         EXPECT_EQ(OS::FileLock(ChildFd, false), -E_BUSY);
240         createStepFlag(2);
241         EXPECT_EQ(OS::CloseFile(ChildFd), E_OK);
242         exit(0);
243     } else {
244         LOGI("main process begin!");
245         EXPECT_EQ(OS::FileLock(fd, false), E_OK);
246         createStepFlag(1);
247 
248         ASSERT_TRUE(waitForStep(2, 100));
249         EXPECT_EQ(OS::CloseFile(fd), E_OK); // fd close, lock invalid
250     }
251 }
252 
253 /**
254  * @tc.name: DiffProcessLockFileBlocked
255  * @tc.desc: Test different process repeat lock same file.
256  * @tc.type: FUNC
257  * @tc.require: AR000FN6G9
258  * @tc.author: sunpeng
259  */
260 HWTEST_F(DistributedDBCommonTest, DiffProcessLockFileBlocked, TestSize.Level1)
261 {
262     EXPECT_EQ(OS::CreateFileByFileName(g_testDir + DBConstant::DB_LOCK_POSTFIX), E_OK);
263     OS::FileHandle fd;
264     EXPECT_EQ(OS::OpenFile(g_testDir + DBConstant::DB_LOCK_POSTFIX, fd), E_OK);
265     EXPECT_EQ(OS::FileLock(fd, true), E_OK);
266     sleep(1);
267     LOGI("begin fork new process!!");
268     int count = 10; // wait 10 times 10 ms for block wait
269     pid_t pid = fork();
270     ASSERT_TRUE(pid >= 0);
271     if (pid < 0) {
272         return;
273     }
274     else if (pid == 0) {
275         LOGI("child process begin!");
276         EXPECT_FALSE(OS::CheckPathExistence(g_testDir + "/LOCK_step_1"));
277         OS::FileHandle ChildFd;
278         EXPECT_EQ(OS::OpenFile(g_testDir + DBConstant::DB_LOCK_POSTFIX, ChildFd), E_OK);
279         EXPECT_EQ(OS::FileLock(ChildFd, true), E_OK);
280         createStepFlag(1);
281         EXPECT_EQ(OS::FileUnlock(ChildFd), E_OK);
282         EXPECT_EQ(OS::CloseFile(ChildFd), E_OK);
283         LOGI("child process finish!");
284         exit(0);
285     } else {
286         LOGI("main process begin!");
287         while (count--) {
288             LOGI("main process waiting!");
289             std::this_thread::sleep_for(std::chrono::milliseconds(10)); // once 10 ms
290         }
291         ASSERT_FALSE(waitForStep(1, 10));
292         EXPECT_EQ(OS::FileUnlock(fd), E_OK);
293         EXPECT_EQ(OS::CloseFile(fd), E_OK);
294         ASSERT_TRUE(waitForStep(1, 10));
295     }
296 }
297 
298 /**
299   * @tc.name: DiffProcessGetDBBlocked
300   * @tc.desc: Test block other process get kvstore when db locked.
301   * @tc.type: FUNC
302   * @tc.require: AR000CQDV7
303   * @tc.author: sunpeng
304   */
305 HWTEST_F(DistributedDBCommonTest, DiffProcessGetDBBlocked, TestSize.Level1)
306 {
307     std::string storeId = "DiffProcessGetDBBlocked";
308     std::string origId = USER_ID + "-" + APP_ID + "-" + storeId;
309     std::string identifier = DBCommon::TransferHashString(origId);
310     std::string hexDir = DBCommon::TransferStringToHex(identifier);
311     std::string lockFile = g_testDir + "/" + hexDir + DBConstant::DB_LOCK_POSTFIX;
312     EXPECT_EQ(DBCommon::CreateDirectory(g_testDir + "/" + hexDir), E_OK);
313     EXPECT_EQ(OS::CreateFileByFileName(lockFile), E_OK);
314     LOGI("Create lock file[%s]", lockFile.c_str());
315 
316     LOGI("begin fork new process!!");
317     pid_t pid = fork();
318     OS::FileHandle fd;
319     ASSERT_TRUE(pid >= 0);
320     if (pid == 0) {
321         LOGI("child process begin!");
322         ASSERT_TRUE(waitForStep(1, 10));
323         KvStoreNbDelegate::Option option = {true, false, false};
324         option.isNeedIntegrityCheck = true;
325         g_mgr.GetKvStore(storeId, option, g_kvNbDelegateCallback);
326         EXPECT_TRUE(g_kvDelegateStatus == BUSY);
327         ASSERT_TRUE(g_kvNbDelegatePtr == nullptr);
328         createStepFlag(2);
329         exit(0);
330     } else {
331         LOGI("main process begin!");
332         EXPECT_EQ(OS::OpenFile(lockFile, fd), E_OK);
333         EXPECT_EQ(OS::FileLock(fd, false), E_OK);
334         createStepFlag(1);
335     }
336 
337     // Prevent the child process from not being completed, the main process ends to clean up resources
338     EXPECT_TRUE(waitForStep(2, 1000));
339     EXPECT_EQ(OS::FileUnlock(fd), E_OK);
340     EXPECT_EQ(OS::CloseFile(fd), E_OK);
341 }
342 
343 /**
344   * @tc.name: DiffProcessDeleteDBBlocked
345   * @tc.desc: Test block other process delete kvstore when db locked.
346   * @tc.type: FUNC
347   * @tc.require: AR000CQDV7
348   * @tc.author: sunpeng
349   */
350 HWTEST_F(DistributedDBCommonTest, DiffProcessDeleteDBBlocked, TestSize.Level1)
351 {
352     std::string storeId = "DiffProcessDeleteDBBlocked";
353     std::string origId = USER_ID + "-" + APP_ID + "-" + storeId;
354     std::string identifier = DBCommon::TransferHashString(origId);
355     std::string hexDir = DBCommon::TransferStringToHex(identifier);
356     std::string lockFile = g_testDir + "/" + hexDir + DBConstant::DB_LOCK_POSTFIX;
357     EXPECT_EQ(DBCommon::CreateDirectory(g_testDir + "/" + hexDir), E_OK);
358     EXPECT_EQ(OS::CreateFileByFileName(lockFile), E_OK);
359     LOGI("Create lock file[%s]", lockFile.c_str());
360 
361     KvStoreNbDelegate::Option option = {true, false, false};
362     option.isNeedIntegrityCheck = true;
363     g_mgr.GetKvStore(storeId, option, g_kvNbDelegateCallback);
364     ASSERT_TRUE(g_kvNbDelegatePtr != nullptr);
365     EXPECT_TRUE(g_kvDelegateStatus == OK);
366 
367     LOGI("begin fork new process!!");
368     pid_t pid = fork();
369     OS::FileHandle fd;
370     ASSERT_TRUE(pid >= 0);
371     if (pid == 0) {
372         LOGI("child process begin!");
373         ASSERT_TRUE(waitForStep(1, 10));
374         EXPECT_EQ(g_mgr.DeleteKvStore(storeId), BUSY);
375         createStepFlag(2);
376         exit(0);
377     } else {
378         LOGI("main process begin!");
379         EXPECT_EQ(OS::OpenFile(lockFile, fd), E_OK);
380         EXPECT_EQ(OS::FileLock(fd, false), E_OK);
381         createStepFlag(1);
382     }
383 
384     // Prevent the child process from not being completed, the main process ends to clean up resources
385     EXPECT_TRUE(waitForStep(2, 1000));
386     EXPECT_EQ(OS::FileUnlock(fd), E_OK);
387     EXPECT_EQ(OS::CloseFile(fd), E_OK);
388     g_mgr.CloseKvStore(g_kvNbDelegatePtr);
389 }
390 
391 /**
392   * @tc.name: DiffProcessGetDBBlocked001
393   * @tc.desc: Test block other process get kvstore when db locked.
394   * @tc.type: FUNC
395   * @tc.require: AR000CQDV7
396   * @tc.author: sunpeng
397   */
398 HWTEST_F(DistributedDBCommonTest, DiffProcessGetDBBlocked001, TestSize.Level1)
399 {
400     std::string storeId = "DiffProcessGetDBBlocked001";
401     std::string origId = USER_ID + "-" + APP_ID + "-" + storeId;
402     std::string identifier = DBCommon::TransferHashString(origId);
403     std::string hexDir = DBCommon::TransferStringToHex(identifier);
404     std::string lockFile = g_testDir + "/" + hexDir + DBConstant::DB_LOCK_POSTFIX;
405     EXPECT_EQ(DBCommon::CreateDirectory(g_testDir + "/" + hexDir), E_OK);
406     EXPECT_EQ(OS::CreateFileByFileName(lockFile), E_OK);
407     LOGI("Create lock file[%s]", lockFile.c_str());
408 
409     LOGI("begin fork new process!!");
410     pid_t pid = fork();
411     OS::FileHandle fd;
412     ASSERT_TRUE(pid >= 0);
413     if (pid == 0) {
414         LOGI("child process begin!");
415         ASSERT_TRUE(waitForStep(1, 10));
416         KvStoreNbDelegate::Option option = {true, false, false};
417         option.isNeedIntegrityCheck = true;
418         g_mgr.GetKvStore(storeId, option, g_kvNbDelegateCallback);
419         ASSERT_TRUE(g_kvNbDelegatePtr != nullptr);
420         EXPECT_TRUE(g_kvDelegateStatus == OK);
421         createStepFlag(2);
422         exit(0);
423     } else {
424         LOGI("main process begin!");
425         EXPECT_EQ(OS::OpenFile(lockFile, fd), E_OK);
426         EXPECT_EQ(OS::FileLock(fd, false), E_OK);
427         createStepFlag(1);
428     }
429     ASSERT_TRUE(waitForStep(1, 100));
430 
431     EXPECT_EQ(OS::FileUnlock(fd), E_OK);
432     EXPECT_EQ(OS::CloseFile(fd), E_OK);
433 
434     ASSERT_TRUE(waitForStep(2, 100));
435 }
436 
437 /**
438   * @tc.name: DiffProcessGetDB
439   * @tc.desc: Test block other process get kvstore.
440   * @tc.type: FUNC
441   * @tc.require: AR000CQDV7
442   * @tc.author: sunpeng
443   */
444 HWTEST_F(DistributedDBCommonTest, DiffProcessGetDB, TestSize.Level1)
445 {
446     std::string storeId = "DiffProcessGetDB";
447     KvStoreNbDelegate::Option option = {true, false, false};
448     option.isNeedIntegrityCheck = true;
449     LOGI("begin fork new process!!");
450     pid_t pid = fork();
451     ASSERT_TRUE(pid >= 0);
452     if (pid == 0) {
453         LOGI("child process begin!");
454         g_mgr.GetKvStore(storeId, option, g_kvNbDelegateCallback);
455         ASSERT_TRUE(g_kvNbDelegatePtr != nullptr);
456         EXPECT_TRUE(g_kvDelegateStatus == OK);
457         createStepFlag(2);
458         EXPECT_TRUE(waitForStep(1, 1000));
459         exit(0);
460     } else {
461         LOGI("main process begin!");
462         g_mgr.GetKvStore(storeId, option, g_kvNbDelegateCallback);
463         ASSERT_TRUE(g_kvNbDelegatePtr != nullptr);
464         EXPECT_TRUE(g_kvDelegateStatus == OK);
465         createStepFlag(1);
466     }
467     EXPECT_TRUE(waitForStep(2, 100));
468     // Prevent the child process from not being completed, the main process ends to clean up resources
469     g_mgr.CloseKvStore(g_kvNbDelegatePtr);
470 }
471 
472 /**
473   * @tc.name: DiffProcessDeleteDB
474   * @tc.desc: Test block other process delete kvstore.
475   * @tc.type: FUNC
476   * @tc.require: AR000CQDV7
477   * @tc.author: sunpeng
478   */
479 HWTEST_F(DistributedDBCommonTest, DiffProcessDeleteDB, TestSize.Level1)
480 {
481     std::string storeId = "DiffProcessGetDB";
482     KvStoreNbDelegate::Option option = {true, false, false};
483     option.isNeedIntegrityCheck = true;
484     g_mgr.GetKvStore(storeId, option, g_kvNbDelegateCallback);
485     ASSERT_TRUE(g_kvNbDelegatePtr != nullptr);
486     EXPECT_TRUE(g_kvDelegateStatus == OK);
487     g_mgr.CloseKvStore(g_kvNbDelegatePtr);
488     LOGI("begin fork new process!!");
489     pid_t pid = fork();
490     ASSERT_TRUE(pid >= 0);
491     if (pid == 0) {
492         LOGI("child process begin!");
493         g_mgr.GetKvStore(storeId, option, g_kvNbDelegateCallback);
494         ASSERT_TRUE(g_kvNbDelegatePtr != nullptr);
495         EXPECT_TRUE(g_kvDelegateStatus == OK);
496         createStepFlag(2);
497         EXPECT_TRUE(waitForStep(1, 1000));
498         exit(0);
499     } else {
500         LOGI("main process begin!");
501         g_mgr.DeleteKvStore(storeId);
502         createStepFlag(1);
503     }
504     EXPECT_TRUE(waitForStep(2, 100));
505 
506     // Prevent the child process from not being completed, the main process ends to clean up resources
507     EXPECT_TRUE(waitForStep(1, 100));
508 }
509 
510 /**
511   * @tc.name: DiffProcessGetAndDeleteDB
512   * @tc.desc: Test block other process delete kvstore.
513   * @tc.type: FUNC
514   * @tc.require: AR000CQDV7
515   * @tc.author: sunpeng
516   */
517 HWTEST_F(DistributedDBCommonTest, DiffProcessGetAndDeleteDB, TestSize.Level1)
518 {
519     std::string storeId = "DiffProcessGetAndDeleteDB";
520     KvStoreNbDelegate::Option option = {true, false, false};
521     option.isNeedIntegrityCheck = true;
522     g_mgr.GetKvStore(storeId, option, g_kvNbDelegateCallback);
523     ASSERT_TRUE(g_kvNbDelegatePtr != nullptr);
524     EXPECT_TRUE(g_kvDelegateStatus == OK);
525     g_mgr.CloseKvStore(g_kvNbDelegatePtr);
526     LOGI("begin fork new process!!");
527     pid_t pid = fork();
528     ASSERT_TRUE(pid >= 0);
529     if (pid == 0) {
530         LOGI("child process begin!");
531         g_mgr.DeleteKvStore(storeId); // one process OK, one process NOT_FOUND
532         createStepFlag(2);
533         EXPECT_TRUE(waitForStep(1, 1000));
534         exit(0);
535     } else {
536         LOGI("main process begin!");
537         g_mgr.DeleteKvStore(storeId);
538         createStepFlag(1);
539     }
540     EXPECT_TRUE(waitForStep(2, 100));
541 
542     // Prevent the child process from not being completed, the main process ends to clean up resources
543     EXPECT_TRUE(waitForStep(1, 1000));
544 }
545 #endif
546 #endif
547 
548 HWTEST_F(DistributedDBCommonTest, StringCaseTest002, TestSize.Level0)
549 {
550     EXPECT_TRUE(DBCommon::CaseInsensitiveCompare("HELLO WORLD.", "hello world."));
551     EXPECT_TRUE(DBCommon::CaseInsensitiveCompare("ABCDEFGHIJKLMN", "abcdefghijklmn"));
552     EXPECT_TRUE(DBCommon::CaseInsensitiveCompare("OPQRSTUVWXYZ", "opqrstuvwxyz"));
553     EXPECT_FALSE(DBCommon::CaseInsensitiveCompare("sqlite", "sqlite3"));
554     EXPECT_FALSE(DBCommon::CaseInsensitiveCompare("gitee", "git"));
555 }
556 
557 HWTEST_F(DistributedDBCommonTest, PerformanceAnalysisTest001, TestSize.Level1)
558 {
559     int threadCount = 1000;
560     int count1 = 0;
561     int count2 = 0;
562     for (int i = 0; i < threadCount; i++) {
__anonff2b654d0302null563         std::thread t1([&count1] {
564             PerformanceAnalysis::GetInstance(20); // 20 is stepNum
565             count1++;
566         });
567 
__anonff2b654d0402null568         std::thread t2([&count2] {
569             PerformanceAnalysis::GetInstance(20); // 20 is stepNum
570             count2++;
571         });
572 
573         t1.join();
574         t2.join();
575     }
576     EXPECT_EQ(count1, count1);
577     EXPECT_EQ(count1, threadCount);
578 }
579 
580 /**
581  * @tc.name: PerformanceAnalysisTest002
582  * @tc.desc: Test PerformanceAnalysis interfaces.
583  * @tc.type: FUNC
584  * @tc.require: DTS2024073106613
585  * @tc.author: suyue
586  */
587 HWTEST_F(DistributedDBCommonTest, PerformanceAnalysisTest002, TestSize.Level1)
588 {
589     /**
590      * @tc.steps: step1. Get PerformanceAnalysis instance and call interfaces.
591      * @tc.expected: step1. success.
592      */
593     PerformanceAnalysis *performance = PerformanceAnalysis::GetInstance(5); // 5 is stepNum
594     ASSERT_NE(performance, nullptr);
595     performance->SetFileName("test");
596     performance->OpenPerformanceAnalysis();
597     performance->TimeRecordStart();
598     performance->TimeRecordEnd();
599 
600     /**
601      * @tc.steps: step2. Call interfaces with the para is greater than stepNum.
602      * @tc.expected: step2. success;
603      */
604     performance->StepTimeRecordStart(RECORD_ACK_RECV_TO_USER_CALL_BACK);
605     performance->StepTimeRecordEnd(RECORD_ACK_RECV_TO_USER_CALL_BACK);
606     performance->ClosePerformanceAnalysis();
607     performance->GetStatistics();
608 }
609 
610 /**
611  * @tc.name: UserChangeMonitorTest
612  * @tc.desc: Test UserChangeMonitor interfaces.
613  * @tc.type: FUNC
614  * @tc.require: DTS2024073106613
615  * @tc.author: suyue
616  */
617 HWTEST_F(DistributedDBCommonTest, UserChangeMonitorTest, TestSize.Level1)
618 {
619     /**
620      * @tc.steps: step1. Start UserChangeMonitor.
621      * @tc.expected: step1. success.
622      */
623     UserChangeMonitor monitor;
624     EXPECT_EQ(monitor.Start(), E_OK);
625     monitor.NotifyUserChanged();
626 
627     /**
628      * @tc.steps: step2. Call RegisterUserChangedListener with null action.
629      * @tc.expected: step2. -E_INVALID_ARGS.
630      */
631     int errCode = E_OK;
632     DistributedDB::UserChangedAction action = nullptr;
633     NotificationChain::Listener *ptr = monitor.RegisterUserChangedListener(action,
634         monitor.USER_ACTIVE_TO_NON_ACTIVE_EVENT, errCode);
635     ASSERT_EQ(ptr, nullptr);
636     EXPECT_EQ(errCode, -E_INVALID_ARGS);
637 
638     /**
639      * @tc.steps: step3. Second start UserChangeMonitor.
640      * @tc.expected: step3. success.
641      */
642     EXPECT_EQ(monitor.Start(), E_OK);
643     monitor.Stop();
644     monitor.NotifyUserChanged();
645 }
646 
647 /**
648  * @tc.name: ValueObjectConstructorTest
649  * @tc.desc: Test ValueObjectTest.
650  * @tc.type: FUNC
651  * @tc.require: DTS2024073106613
652  * @tc.author: suyue
653  */
654 HWTEST_F(DistributedDBCommonTest, ValueObjectConstructorTest, TestSize.Level1)
655 {
656     /**
657      * @tc.steps: step1. Call the default constructor of ValueObject.
658      * @tc.expected: step1. success.
659      */
660     ValueObject valueObj;
661     EXPECT_EQ(valueObj.IsValid(), false);
662 
663     /**
664      * @tc.steps: step2. Call constructor of ValueObject.
665      * @tc.expected: step2. success.
666      */
667     ValueObject valueObj1(valueObj);
668     EXPECT_EQ(valueObj1.IsValid(), false);
669     valueObj = valueObj1;
670 }
671 
672 /**
673  * @tc.name: TimeTickMonitorTest
674  * @tc.desc: Test TimeTickMonitor interfaces.
675  * @tc.type: FUNC
676  * @tc.require: DTS2024073106613
677  * @tc.author: suyue
678  */
679 HWTEST_F(DistributedDBCommonTest, TimeTickMonitorTest, TestSize.Level1)
680 {
681     /**
682      * @tc.steps: step1. Start TimeTickMonitor.
683      * @tc.expected: step1. success.
684      */
685     TimeTickMonitor monitor;
686     EXPECT_EQ(monitor.StartTimeTickMonitor(), E_OK);
687 
688     /**
689      * @tc.steps: step2. Call RegisterTimeChangedLister with null para.
690      * @tc.expected: step2. -E_INVALID_ARGS.
691      */
692     int errCode = E_OK;
693     DistributedDB::UserChangedAction action = nullptr;
694     TimeFinalizeAction finalize = nullptr;
695     NotificationChain::Listener *ptr = monitor.RegisterTimeChangedLister(action, finalize, errCode);
696     ASSERT_EQ(ptr, nullptr);
697     EXPECT_EQ(errCode, -E_INVALID_ARGS);
698 
699     /**
700      * @tc.steps: step3. Call RegisterTimeChangedLister after Stop TimeTickMonitor.
701      * @tc.expected: step3. success;
702      */
703     EXPECT_EQ(monitor.StartTimeTickMonitor(), E_OK);
704     monitor.StopTimeTickMonitor();
705     monitor.NotifyTimeChange(0);
706 
707     ptr = monitor.RegisterTimeChangedLister(action, finalize, errCode);
708     ASSERT_EQ(ptr, nullptr);
709     EXPECT_EQ(errCode, -E_NOT_INIT);
710 }
711 
712 /**
713  * @tc.name: LockStatusObserverTest
714  * @tc.desc: Test LockStatusObserver interfaces.
715  * @tc.type: FUNC
716  * @tc.require: DTS2024073106613
717  * @tc.author: suyue
718  */
719 HWTEST_F(DistributedDBCommonTest, LockStatusObserverTest, TestSize.Level1)
720 {
721     /**
722      * @tc.steps: step1. Call RegisterLockStatusChangedLister with null para.
723      * @tc.expected: step1. -E_INVALID_ARGS.
724      */
725     LockStatusObserver observer;
726     EXPECT_EQ(observer.Start(), E_OK);
727 
728     int errCode = E_OK;
729     DistributedDB::UserChangedAction action = nullptr;
730     NotificationChain::Listener *ptr = observer.RegisterLockStatusChangedLister(action, errCode);
731     ASSERT_EQ(ptr, nullptr);
732     EXPECT_EQ(errCode, -E_INVALID_ARGS);
733 
734     /**
735      * @tc.steps: step2. Call RegisterLockStatusChangedLister after stop observer.
736      * @tc.expected: step2. -E_NOT_INIT.
737      */
738     EXPECT_EQ(observer.Start(), E_OK);
739     observer.Stop();
740     observer.OnStatusChange(true);
741 
742     ptr = observer.RegisterLockStatusChangedLister(action, errCode);
743     ASSERT_EQ(ptr, nullptr);
744     EXPECT_EQ(errCode, -E_NOT_INIT);
745 }
746 
747 /**
748  * @tc.name: TaskQueueTest
749  * @tc.desc: Test TaskQueue interfaces.
750  * @tc.type: FUNC
751  * @tc.require: DTS2024073106613
752  * @tc.author: suyue
753  */
754 HWTEST_F(DistributedDBCommonTest, TaskQueueTest, TestSize.Level1)
755 {
756     /**
757      * @tc.steps: step1. Create TaskQueue object whose para is true.
758      * @tc.expected: step1. Create success.
759      */
760     TaskQueue taskObj1(true);
761     const Task task1;
762     taskObj1.PutTask(task1);
763     EXPECT_EQ(taskObj1.IsEmptyAndUnlocked(), true);
764     EXPECT_EQ(taskObj1.CanGetTask(), false);
765 
766     /**
767      * @tc.steps: step2. Create TaskQueue object whose para is false.
768      * @tc.expected: step2. Create success.
769      */
770     TaskQueue taskObj2(false);
771     EXPECT_EQ(taskObj2.IsEmptyAndUnlocked(), true);
772     EXPECT_EQ(taskObj2.CanGetTask(), false);
773 }
774 
775 /**
776  * @tc.name: AbnormalTrackerTableTest
777  * @tc.desc: Test LockStatusObserver interfaces.
778  * @tc.type: FUNC
779  * @tc.require: DTS2024073106613
780  * @tc.author: suyue
781  */
782 HWTEST_F(DistributedDBCommonTest, AbnormalTrackerTableTest, TestSize.Level1)
783 {
784     /**
785      * @tc.steps: step1. Call GetDiffIncCursorSql interface when TrackerTable is not init.
786      * @tc.expected: step1. return empty string.
787      */
788     TrackerTable trackerObj1;
789     std::string str = trackerObj1.GetDiffIncCursorSql("test1");
790     const std::string emptyStr = "";
791     EXPECT_TRUE(str.compare(0, str.length(), emptyStr) == 0);
792 
793     /**
794      * @tc.steps: step2. Call GetCreateTempTriggerSql interface when para is NONE.
795      * @tc.expected: step2. return empty string.
796      */
797     std::string str1 = trackerObj1.GetCreateTempTriggerSql(TriggerMode::TriggerModeEnum::DELETE);
798     EXPECT_TRUE(str1.compare(0, str1.length(), emptyStr) != 0);
799     std::string str2 = trackerObj1.GetCreateTempTriggerSql(TriggerMode::TriggerModeEnum::NONE);
800     EXPECT_TRUE(str2.compare(0, str2.length(), emptyStr) == 0);
801 
802     /**
803      * @tc.steps: step3. Call ReBuildTempTrigger interface when db is nullptr.
804      * @tc.expected: step3. return -E_INVALID_DB.
805      */
806     int ret = trackerObj1.ReBuildTempTrigger(nullptr, TriggerMode::TriggerModeEnum::NONE, nullptr);
807     EXPECT_EQ(ret, -E_INVALID_DB);
808 
809     /**
810      * @tc.steps: step4. Test IsChanging interface after setting schema info.
811      * @tc.expected: step4. return true.
812      */
813     const TrackerSchema schema = {
814         .tableName = "table1",
815         .extendColName = "extendCol1",
816         .trackerColNames = {"trackerCol1"},
817     };
818     trackerObj1.Init(schema);
819     EXPECT_EQ(trackerObj1.IsChanging(schema), false);
820 
821     const std::set<std::string> trackerNames = {"trackerCol"};
822     trackerObj1.SetTrackerNames(trackerNames);
823     EXPECT_EQ(trackerObj1.IsChanging(schema), true);
824     const std::string colName = "col";
825     trackerObj1.SetExtendName(colName);
826     std::string str3 = trackerObj1.GetExtendName();
827     EXPECT_TRUE(str3.compare(0, str3.length(), colName) == 0);
828     EXPECT_EQ(trackerObj1.IsChanging(schema), true);
829 }
830 }