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++) {
__anon651a4a2e0302null563 std::thread t1([&count1] {
564 PerformanceAnalysis::GetInstance(20); // 20 is stepNum
565 count1++;
566 });
567
__anon651a4a2e0402null568 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 }