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 }