1 /*
2 * Copyright (c) 2022 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 <condition_variable>
17 #include <gtest/gtest.h>
18 #include <thread>
19
20 #include "db_constant.h"
21 #include "distributeddb_data_generate_unit_test.h"
22 #include "distributeddb_tools_unit_test.h"
23 #include "kv_store_nb_delegate.h"
24 #include "kv_virtual_device.h"
25 #include "platform_specific.h"
26 #include "runtime_config.h"
27
28 using namespace testing::ext;
29 using namespace DistributedDB;
30 using namespace DistributedDBUnitTest;
31 using namespace std;
32
33 namespace {
34 string g_testDir;
35 const string STORE_ID = "kv_stroe_sync_test";
36 const string USER_ID_1 = "userId1";
37 const string USER_ID_2 = "userId2";
38 const std::string DEVICE_B = "deviceB";
39 const std::string DEVICE_C = "deviceC";
40 const int WAIT_TIME = 1000; // 1000ms
41 const int WAIT_3_SECONDS = 3000;
42
43 KvStoreDelegateManager g_mgr1(APP_ID, USER_ID_1);
44 KvStoreDelegateManager g_mgr2(APP_ID, USER_ID_2);
45 KvStoreConfig g_config;
46 DistributedDBToolsUnitTest g_tool;
47 KvStoreNbDelegate* g_kvDelegatePtr1 = nullptr;
48 KvStoreNbDelegate* g_kvDelegatePtr2 = nullptr;
49 VirtualCommunicatorAggregator* g_communicatorAggregator = nullptr;
50 KvVirtualDevice *g_deviceB = nullptr;
51 KvVirtualDevice *g_deviceC = nullptr;
52 DBStatus g_kvDelegateStatus1 = INVALID_ARGS;
53 DBStatus g_kvDelegateStatus2 = INVALID_ARGS;
54 std::string g_identifier;
55
56 // the type of g_kvDelegateCallback is function<void(DBStatus, KvStoreDelegate*)>
57 auto g_kvDelegateCallback1 = bind(&DistributedDBToolsUnitTest::KvStoreNbDelegateCallback,
58 placeholders::_1, placeholders::_2, std::ref(g_kvDelegateStatus1), std::ref(g_kvDelegatePtr1));
59 auto g_kvDelegateCallback2 = bind(&DistributedDBToolsUnitTest::KvStoreNbDelegateCallback,
60 placeholders::_1, placeholders::_2, std::ref(g_kvDelegateStatus2), std::ref(g_kvDelegatePtr2));
61 auto g_syncActivationCheckCallback1 = [] (const std::string &userId, const std::string &appId,
__anon1d601b670202(const std::string &userId, const std::string &appId, const std::string &storeId)62 const std::string &storeId)-> bool {
63 if (userId == USER_ID_2) {
64 return true;
65 } else {
66 return false;
67 }
68 return true;
69 };
70 auto g_syncActivationCheckCallback2 = [] (const std::string &userId, const std::string &appId,
__anon1d601b670302(const std::string &userId, const std::string &appId, const std::string &storeId)71 const std::string &storeId)-> bool {
72 if (userId == USER_ID_1) {
73 return true;
74 } else {
75 return false;
76 }
77 return true;
78 };
79 }
80
81 class DistributedDBSingleVerMultiUserTest : public testing::Test {
82 public:
83 static void SetUpTestCase(void);
84 static void TearDownTestCase(void);
85 void SetUp();
86 void TearDown();
87 };
88
SetUpTestCase(void)89 void DistributedDBSingleVerMultiUserTest::SetUpTestCase(void)
90 {
91 /**
92 * @tc.setup: Init datadir and Virtual Communicator.
93 */
94 DistributedDBToolsUnitTest::TestDirInit(g_testDir);
95 g_config.dataDir = g_testDir;
96 g_mgr1.SetKvStoreConfig(g_config);
97 g_mgr2.SetKvStoreConfig(g_config);
98
99 string dir = g_testDir + "/single_ver";
100 DIR* dirTmp = opendir(dir.c_str());
101 if (dirTmp == nullptr) {
102 OS::MakeDBDirectory(dir);
103 } else {
104 closedir(dirTmp);
105 }
106
107 g_communicatorAggregator = new (std::nothrow) VirtualCommunicatorAggregator();
108 ASSERT_TRUE(g_communicatorAggregator != nullptr);
109 RuntimeContext::GetInstance()->SetCommunicatorAggregator(g_communicatorAggregator);
110 }
111
TearDownTestCase(void)112 void DistributedDBSingleVerMultiUserTest::TearDownTestCase(void)
113 {
114 /**
115 * @tc.teardown: Release virtual Communicator and clear data dir.
116 */
117 if (DistributedDBToolsUnitTest::RemoveTestDbFiles(g_testDir) != 0) {
118 LOGE("rm test db files error!");
119 }
120 RuntimeContext::GetInstance()->SetCommunicatorAggregator(nullptr);
121 }
122
SetUp(void)123 void DistributedDBSingleVerMultiUserTest::SetUp(void)
124 {
125 DistributedDBToolsUnitTest::PrintTestCaseInfo();
126 /**
127 * @tc.setup: create virtual device B
128 */
129 g_deviceB = new (std::nothrow) KvVirtualDevice(DEVICE_B);
130 ASSERT_TRUE(g_deviceB != nullptr);
131 VirtualSingleVerSyncDBInterface *syncInterfaceB = new (std::nothrow) VirtualSingleVerSyncDBInterface();
132 ASSERT_TRUE(syncInterfaceB != nullptr);
133 ASSERT_EQ(g_deviceB->Initialize(g_communicatorAggregator, syncInterfaceB), E_OK);
134 g_deviceC = new (std::nothrow) KvVirtualDevice(DEVICE_C);
135 ASSERT_TRUE(g_deviceC != nullptr);
136 VirtualSingleVerSyncDBInterface *syncInterfaceC = new (std::nothrow) VirtualSingleVerSyncDBInterface();
137 ASSERT_TRUE(syncInterfaceC != nullptr);
138 ASSERT_EQ(g_deviceC->Initialize(g_communicatorAggregator, syncInterfaceC), E_OK);
139 }
140
TearDown(void)141 void DistributedDBSingleVerMultiUserTest::TearDown(void)
142 {
143 /**
144 * @tc.teardown: Release device A, B, C
145 */
146 if (g_deviceB != nullptr) {
147 delete g_deviceB;
148 g_deviceB = nullptr;
149 }
150 if (g_deviceC != nullptr) {
151 delete g_deviceC;
152 g_deviceC = nullptr;
153 }
154 SyncActivationCheckCallback callback = nullptr;
155 g_mgr1.SetSyncActivationCheckCallback(callback);
156 RuntimeContext::GetInstance()->ClearAllDeviceTimeInfo();
157 }
158
159 namespace {
OpenStore1(bool syncDualTupleMode=true)160 void OpenStore1(bool syncDualTupleMode = true)
161 {
162 KvStoreNbDelegate::Option option;
163 option.syncDualTupleMode = syncDualTupleMode;
164 g_mgr1.GetKvStore(STORE_ID, option, g_kvDelegateCallback1);
165 ASSERT_TRUE(g_kvDelegateStatus1 == OK);
166 ASSERT_TRUE(g_kvDelegatePtr1 != nullptr);
167 }
168
OpenStore2(bool syncDualTupleMode=true)169 void OpenStore2(bool syncDualTupleMode = true)
170 {
171 KvStoreNbDelegate::Option option;
172 option.syncDualTupleMode = syncDualTupleMode;
173 g_mgr2.GetKvStore(STORE_ID, option, g_kvDelegateCallback2);
174 ASSERT_TRUE(g_kvDelegateStatus2 == OK);
175 ASSERT_TRUE(g_kvDelegatePtr2 != nullptr);
176 }
177
CloseStore()178 void CloseStore()
179 {
180 if (g_kvDelegatePtr1 != nullptr) {
181 ASSERT_EQ(g_mgr1.CloseKvStore(g_kvDelegatePtr1), OK);
182 g_kvDelegatePtr1 = nullptr;
183 DBStatus status = g_mgr1.DeleteKvStore(STORE_ID);
184 LOGD("delete kv store status %d", status);
185 ASSERT_TRUE(status == OK);
186 }
187 if (g_kvDelegatePtr2 != nullptr) {
188 ASSERT_EQ(g_mgr2.CloseKvStore(g_kvDelegatePtr2), OK);
189 g_kvDelegatePtr2 = nullptr;
190 DBStatus status = g_mgr2.DeleteKvStore(STORE_ID);
191 LOGD("delete kv store status %d", status);
192 ASSERT_TRUE(status == OK);
193 }
194 }
195
CheckSyncTest(DBStatus status1,DBStatus status2,std::vector<std::string> & devices)196 void CheckSyncTest(DBStatus status1, DBStatus status2, std::vector<std::string> &devices)
197 {
198 std::map<std::string, DBStatus> result;
199 DBStatus status = g_tool.SyncTest(g_kvDelegatePtr1, devices, SYNC_MODE_PUSH_ONLY, result);
200 ASSERT_TRUE(status == status1);
201 if (status == OK) {
202 for (const auto &pair : result) {
203 LOGD("dev %s, status %d", pair.first.c_str(), pair.second);
204 EXPECT_TRUE(pair.second == OK);
205 }
206 }
207 result.clear();
208 status = g_tool.SyncTest(g_kvDelegatePtr2, devices, SYNC_MODE_PUSH_ONLY, result);
209 ASSERT_TRUE(status == status2);
210 if (status == OK) {
211 ASSERT_TRUE(result.size() == devices.size());
212 for (const auto &pair : result) {
213 LOGD("dev %s, status %d", pair.first.c_str(), pair.second);
214 EXPECT_TRUE(pair.second == OK);
215 }
216 }
217 }
218
AutoLaunchCallBack(const std::string & identifier,AutoLaunchParam & param,KvStoreObserverUnitTest * observer,bool ret)219 bool AutoLaunchCallBack(const std::string &identifier, AutoLaunchParam ¶m, KvStoreObserverUnitTest *observer,
220 bool ret)
221 {
222 LOGD("int AutoLaunchCallBack");
223 EXPECT_TRUE(identifier == g_identifier);
224 param.appId = APP_ID;
225 param.storeId = STORE_ID;
226 CipherPassword passwd;
227 param.option = {true, false, CipherType::DEFAULT, passwd, "", false, g_testDir, observer,
228 0, nullptr};
229 param.notifier = nullptr;
230 param.option.syncDualTupleMode = true;
231 return ret;
232 }
233
TestSyncWithUserChange(bool wait)234 void TestSyncWithUserChange(bool wait)
235 {
236 /**
237 * @tc.steps: step1. set SyncActivationCheckCallback and only userId1 can active
238 */
239 g_mgr1.SetSyncActivationCheckCallback(g_syncActivationCheckCallback2);
240 /**
241 * @tc.steps: step2. openstore1 in dual tuple sync mode and openstore2 in normal sync mode
242 * @tc.expected: step2. only user2 sync mode is active
243 */
244 OpenStore1(true);
245 OpenStore2(true);
246 /**
247 * @tc.steps: step3. set SyncActivationCheckCallback and only userId2 can active
248 */
249 g_mgr1.SetSyncActivationCheckCallback(g_syncActivationCheckCallback1);
250
251 /**
252 * @tc.steps: step4. call NotifyUserChanged and block sync db concurrently
253 * @tc.expected: step4. return OK
254 */
255 CipherPassword passwd;
256 bool startSync = false;
257 std::condition_variable cv;
258 thread subThread([&startSync, &cv]() {
259 std::mutex notifyLock;
260 std::unique_lock<std::mutex> lck(notifyLock);
261 cv.wait(lck, [&startSync]() { return startSync; });
262 EXPECT_TRUE(KvStoreDelegateManager::NotifyUserChanged() == OK);
263 });
264 subThread.detach();
265 g_communicatorAggregator->RegOnDispatch([&](const std::string&, Message *inMsg) {
266 if (!startSync) {
267 startSync = true;
268 cv.notify_all();
269 }
270 });
271
272 /**
273 * @tc.steps: step5. deviceA call sync and wait
274 * @tc.expected: step5. sync should return OK.
275 */
276 std::map<std::string, DBStatus> result;
277 std::vector<std::string> devices;
278 devices.push_back(g_deviceB->GetDeviceId());
279 DBStatus status = g_tool.SyncTest(g_kvDelegatePtr1, devices, SYNC_MODE_PUSH_ONLY, result, wait);
280 EXPECT_EQ(status, OK);
281 g_communicatorAggregator->RegOnDispatch(nullptr);
282 /**
283 * @tc.expected: step6. onComplete should be called, and status is USER_CHANGED
284 */
285 EXPECT_EQ(result.size(), devices.size());
286 for (const auto &pair : result) {
287 LOGD("dev %s, status %d", pair.first.c_str(), pair.second);
288 // If the ClearSyncOperations interface is scheduled to be executed first, syncer has been closed
289 // when AddSyncOperation is triggered and the returned status is OP_FAILED(DB_ERROR).
290 EXPECT_TRUE((pair.second == USER_CHANGED) || (pair.second == DB_ERROR));
291 }
292 CloseStore();
293 }
294 }
295
296 /**
297 * @tc.name: multi user 001
298 * @tc.desc: Test multi user change
299 * @tc.type: FUNC
300 * @tc.require:
301 * @tc.author: zhuwentao
302 */
303 HWTEST_F(DistributedDBSingleVerMultiUserTest, MultiUser001, TestSize.Level1)
304 {
305 /**
306 * @tc.steps: step1. set SyncActivationCheckCallback and only userId2 can active
307 */
308 g_mgr1.SetSyncActivationCheckCallback(g_syncActivationCheckCallback1);
309 /**
310 * @tc.steps: step2. openstore1 and openstore2
311 * @tc.expected: step2. only user2 sync mode is active
312 */
313 OpenStore1();
314 OpenStore2();
315 /**
316 * @tc.steps: step3. g_kvDelegatePtr1 and g_kvDelegatePtr2 put {k1, v1}
317 */
318 Key key = {'1'};
319 Value value = {'1'};
320 Value value2 = {'2'};
321 EXPECT_TRUE(g_kvDelegatePtr1->Put(key, value2) == OK);
322 EXPECT_TRUE(g_kvDelegatePtr2->Put(key, value) == OK);
323 /**
324 * @tc.steps: step4. g_kvDelegatePtr1 and g_kvDelegatePtr2 call sync
325 * @tc.expected: step4. g_kvDelegatePtr2 call success
326 */
327 std::vector<std::string> devices;
328 devices.push_back(g_deviceB->GetDeviceId());
329 CheckSyncTest(NOT_ACTIVE, OK, devices);
330 /**
331 * @tc.steps: step5. g_kvDelegatePtr1 support some pragma cmd call
332 * @tc.expected: step5. Pragma call success
333 */
334 int pragmaData = 1;
335 PragmaData input = static_cast<PragmaData>(&pragmaData);
336 EXPECT_TRUE(g_kvDelegatePtr1->Pragma(AUTO_SYNC, input) == OK);
337 pragmaData = 100;
338 input = static_cast<PragmaData>(&pragmaData);
339 EXPECT_TRUE(g_kvDelegatePtr1->Pragma(SET_QUEUED_SYNC_LIMIT, input) == OK);
340 EXPECT_TRUE(g_kvDelegatePtr1->Pragma(GET_QUEUED_SYNC_LIMIT, input) == OK);
341 EXPECT_TRUE(input == static_cast<PragmaData>(&pragmaData));
342 pragmaData = 1;
343 input = static_cast<PragmaData>(&pragmaData);
344 EXPECT_TRUE(g_kvDelegatePtr1->Pragma(SET_WIPE_POLICY, input) == OK);
345 EXPECT_TRUE(g_kvDelegatePtr1->Pragma(SET_SYNC_RETRY, input) == OK);
346 /**
347 * @tc.expected: step6. onComplete should be called, DeviceB have {k1,v1}
348 */
349 VirtualDataItem item;
350 g_deviceB->GetData(key, item);
351 EXPECT_TRUE(item.value == value);
352 /**
353 * @tc.expected: step7. user change
354 */
355 g_mgr1.SetSyncActivationCheckCallback(g_syncActivationCheckCallback2);
356 KvStoreDelegateManager::NotifyUserChanged();
357 /**
358 * @tc.steps: step8. g_kvDelegatePtr1 and g_kvDelegatePtr2 call sync
359 * @tc.expected: step8. g_kvDelegatePtr1 call success
360 */
361 devices.clear();
362 devices.push_back(g_deviceC->GetDeviceId());
363 CheckSyncTest(OK, NOT_ACTIVE, devices);
364 /**
365 * @tc.expected: step9. onComplete should be called, DeviceC have {k1,v1}
366 */
367 g_deviceC->GetData(key, item);
368 EXPECT_TRUE(item.value == value2);
369 CloseStore();
370 }
371
372 /**
373 * @tc.name: multi user 002
374 * @tc.desc: Test multi user not change
375 * @tc.type: FUNC
376 * @tc.require:
377 * @tc.author: zhuwentao
378 */
379 HWTEST_F(DistributedDBSingleVerMultiUserTest, MultiUser002, TestSize.Level1)
380 {
381 /**
382 * @tc.steps: step1. set SyncActivationCheckCallback and only userId2 can active
383 */
384 g_mgr1.SetSyncActivationCheckCallback(g_syncActivationCheckCallback1);
385 /**
386 * @tc.steps: step2. openstore1 and openstore2
387 * @tc.expected: step2. only user2 sync mode is active
388 */
389 OpenStore1();
390 OpenStore2();
391 /**
392 * @tc.steps: step3. g_kvDelegatePtr1 and g_kvDelegatePtr2 put {k1, v1}
393 */
394 Key key = {'1'};
395 Value value = {'1'};
396 EXPECT_TRUE(g_kvDelegatePtr1->Put(key, value) == OK);
397 EXPECT_TRUE(g_kvDelegatePtr2->Put(key, value) == OK);
398 /**
399 * @tc.steps: step4. GetKvStoreIdentifier success when userId is invalid
400 */
401 std::string userId;
402 EXPECT_TRUE(g_mgr1.GetKvStoreIdentifier(userId, APP_ID, USER_ID_2, true) != "");
403 userId.resize(130);
404 EXPECT_TRUE(g_mgr1.GetKvStoreIdentifier(userId, APP_ID, USER_ID_2, true) != "");
405 /**
406 * @tc.steps: step5. g_kvDelegatePtr1 and g_kvDelegatePtr2 call sync
407 * @tc.expected: step5. g_kvDelegatePtr2 call success
408 */
409 std::vector<std::string> devices;
410 devices.push_back(g_deviceB->GetDeviceId());
411 CheckSyncTest(NOT_ACTIVE, OK, devices);
412 /**
413 * @tc.expected: step6. onComplete should be called, DeviceB have {k1,v1}
414 */
415 VirtualDataItem item;
416 g_deviceB->GetData(key, item);
417 EXPECT_TRUE(item.value == value);
418 /**
419 * @tc.expected: step7. user not change
420 */
421 KvStoreDelegateManager::NotifyUserChanged();
422 /**
423 * @tc.steps: step8. g_kvDelegatePtr1 and g_kvDelegatePtr2 put {k2, v2}
424 */
425 key = {'2'};
426 value = {'2'};
427 EXPECT_TRUE(g_kvDelegatePtr1->Put(key, value) == OK);
428 EXPECT_TRUE(g_kvDelegatePtr2->Put(key, value) == OK);
429 /**
430 * @tc.steps: step9. g_kvDelegatePtr1 and g_kvDelegatePtr2 call sync
431 * @tc.expected: step9. g_kvDelegatePtr2 call success
432 */
433 devices.clear();
434 devices.push_back(g_deviceB->GetDeviceId());
435 CheckSyncTest(NOT_ACTIVE, OK, devices);
436 /**
437 * @tc.expected: step10. onComplete should be called, DeviceB have {k2,v2}
438 */
439 g_deviceB->GetData(key, item);
440 EXPECT_TRUE(item.value == value);
441 CloseStore();
442 }
443
444 /**
445 * @tc.name: multi user 003
446 * @tc.desc: enhancement callback return true in multiuser mode
447 * @tc.type: FUNC
448 * @tc.require:
449 * @tc.author: zhuwentao
450 */
451 HWTEST_F(DistributedDBSingleVerMultiUserTest, MultiUser003, TestSize.Level3)
452 {
453 /**
454 * @tc.steps: step1. set SyncActivationCheckCallback and only userId2 can active
455 */
456 g_mgr1.SetSyncActivationCheckCallback(g_syncActivationCheckCallback1);
457
458 KvStoreObserverUnitTest *observer = new (std::nothrow) KvStoreObserverUnitTest;
459 EXPECT_TRUE(observer != nullptr);
460 /**
461 * @tc.steps: step2. SetAutoLaunchRequestCallback
462 * @tc.expected: step2. success.
463 */
464 g_mgr1.SetAutoLaunchRequestCallback(
465 std::bind(AutoLaunchCallBack, std::placeholders::_1, std::placeholders::_2, observer, true));
466
467 /**
468 * @tc.steps: step2. RunCommunicatorLackCallback
469 * @tc.expected: step2. success.
470 */
471 g_identifier = g_mgr1.GetKvStoreIdentifier(USER_ID_2, APP_ID, STORE_ID, true);
472 EXPECT_TRUE(g_identifier == g_mgr1.GetKvStoreIdentifier(USER_ID_1, APP_ID, STORE_ID, true));
473 std::vector<uint8_t> label(g_identifier.begin(), g_identifier.end());
474 g_communicatorAggregator->SetCurrentUserId(USER_ID_2);
475 g_communicatorAggregator->RunCommunicatorLackCallback(label);
476 std::this_thread::sleep_for(std::chrono::milliseconds(WAIT_TIME));
477 /**
478 * @tc.steps: step3. device B put {k1, v1}
479 * @tc.expected: step3. success.
480 */
481 Key key = {'1'};
482 Value value = {'1'};
483 Timestamp currentTime;
484 (void)OS::GetCurrentSysTimeInMicrosecond(currentTime);
485 EXPECT_TRUE(g_deviceB->PutData(key, value, currentTime, 0) == E_OK);
486 /**
487 * @tc.steps: step4. device B push sync to A
488 * @tc.expected: step4. success.
489 */
490 EXPECT_TRUE(g_deviceB->Sync(SYNC_MODE_PUSH_ONLY, true) == E_OK);
491 std::this_thread::sleep_for(std::chrono::milliseconds(WAIT_TIME));
492 EXPECT_TRUE(observer->GetCallCount() == 1); // only A
493 /**
494 * @tc.steps: step5. deviceA have {k1,v1}
495 * @tc.expected: step5. success.
496 */
497 OpenStore2();
498 Value actualValue;
499 g_kvDelegatePtr2->Get(key, actualValue);
500 EXPECT_EQ(actualValue, value);
501
502 RuntimeConfig::SetAutoLaunchRequestCallback(nullptr, DBType::DB_KV);
503 RuntimeConfig::ReleaseAutoLaunch(USER_ID_2, APP_ID, STORE_ID, DBType::DB_KV);
504 CloseStore();
505 delete observer;
506 }
507
508 /**
509 * @tc.name: MultiUser004
510 * @tc.desc: CommunicatorLackCallback in multi user mode
511 * @tc.type: FUNC
512 * @tc.require:
513 * @tc.author: zhuwentao
514 */
515 HWTEST_F(DistributedDBSingleVerMultiUserTest, MultiUser004, TestSize.Level1)
516 {
517 /**
518 * @tc.steps: step1. set SyncActivationCheckCallback and only userId2 can active
519 */
520 g_mgr1.SetSyncActivationCheckCallback(g_syncActivationCheckCallback1);
521
522 /**
523 * @tc.steps: step2. right param A B enable
524 * @tc.expected: step2. success.
525 */
526 AutoLaunchNotifier notifier = nullptr;
527 KvStoreObserverUnitTest *observer = new (std::nothrow) KvStoreObserverUnitTest;
528 EXPECT_TRUE(observer != nullptr);
529 AutoLaunchOption option;
530 CipherPassword passwd;
531 option = {true, false, CipherType::DEFAULT, passwd, "", false, g_testDir, observer,
532 0, nullptr};
533 option.notifier = nullptr;
534 option.observer = observer;
535 option.syncDualTupleMode = true;
536 EXPECT_TRUE(g_mgr1.EnableKvStoreAutoLaunch(USER_ID_2, APP_ID, STORE_ID, option, notifier) == OK);
537 EXPECT_TRUE(g_mgr1.EnableKvStoreAutoLaunch(USER_ID_1, APP_ID, STORE_ID, option, notifier) == OK);
538 DistributedDBToolsUnitTest::Dump();
539
540 /**
541 * @tc.steps: step3. RunCommunicatorLackCallback
542 * @tc.expected: step3. userId2 open db successfully.
543 */
544 g_identifier = g_mgr1.GetKvStoreIdentifier(USER_ID_2, APP_ID, STORE_ID, true);
545 std::vector<uint8_t> label(g_identifier.begin(), g_identifier.end());
546 g_communicatorAggregator->SetCurrentUserId(USER_ID_2);
547 g_communicatorAggregator->RunCommunicatorLackCallback(label);
548 std::this_thread::sleep_for(std::chrono::milliseconds(WAIT_TIME));
549 /**
550 * @tc.steps: step5. device B put {k1, v1}
551 * @tc.expected: step5. success.
552 */
553 Key key = {'1'};
554 Value value = {'1'};
555 Timestamp currentTime;
556 (void)OS::GetCurrentSysTimeInMicrosecond(currentTime);
557 EXPECT_TRUE(g_deviceB->PutData(key, value, currentTime, 0) == E_OK);
558 /**
559 * @tc.steps: step6. device B push sync to A
560 * @tc.expected: step6. success.
561 */
562 EXPECT_TRUE(g_deviceB->Sync(SYNC_MODE_PUSH_ONLY, true) == E_OK);
563 std::this_thread::sleep_for(std::chrono::milliseconds(WAIT_TIME));
564 EXPECT_TRUE(observer->GetCallCount() == 1); // only A
565 /**
566 * @tc.steps: step7. deviceA have {k1,v1}
567 * @tc.expected: step7. success.
568 */
569 OpenStore2();
570 Value actualValue;
571 g_kvDelegatePtr2->Get(key, actualValue);
572 EXPECT_EQ(actualValue, value);
573 /**
574 * @tc.steps: step8. param A B disable
575 * @tc.expected: step8. notifier WRITE_CLOSED
576 */
577 EXPECT_TRUE(g_mgr1.DisableKvStoreAutoLaunch(USER_ID_2, APP_ID, STORE_ID) == OK);
578 std::this_thread::sleep_for(std::chrono::milliseconds(WAIT_TIME));
579 EXPECT_TRUE(g_mgr1.DisableKvStoreAutoLaunch(USER_ID_1, APP_ID, STORE_ID) == OK);
580 CloseStore();
581 delete observer;
582 }
583
584 /**
585 * @tc.name: MultiUser005
586 * @tc.desc: test NotifyUserChanged func when all db in normal sync mode
587 * @tc.type: FUNC
588 * @tc.require:
589 * @tc.author: zhuwentao
590 */
591 HWTEST_F(DistributedDBSingleVerMultiUserTest, MultiUser005, TestSize.Level1)
592 {
593 /**
594 * @tc.steps: step1. openstore1 and openstore2 in normal sync mode
595 * @tc.expected: step1. only user2 sync mode is active
596 */
597 OpenStore1(false);
598 OpenStore2(false);
599 /**
600 * @tc.steps: step2. call NotifyUserChanged
601 * @tc.expected: step2. return OK
602 */
603 EXPECT_TRUE(KvStoreDelegateManager::NotifyUserChanged() == OK);
604 CloseStore();
605 /**
606 * @tc.steps: step3. openstore1 open normal sync mode and and openstore2 in dual tuple
607 * @tc.expected: step3. only user2 sync mode is active
608 */
609 OpenStore1(false);
610 OpenStore2();
611 /**
612 * @tc.steps: step4. call NotifyUserChanged
613 * @tc.expected: step4. return OK
614 */
615 EXPECT_TRUE(KvStoreDelegateManager::NotifyUserChanged() == OK);
616 CloseStore();
617 }
618
619 /**
620 * @tc.name: MultiUser006
621 * @tc.desc: test NotifyUserChanged and close db concurrently
622 * @tc.type: FUNC
623 * @tc.require:
624 * @tc.author: zhuwentao
625 */
626 HWTEST_F(DistributedDBSingleVerMultiUserTest, MultiUser006, TestSize.Level1)
627 {
628 /**
629 * @tc.steps: step1. set SyncActivationCheckCallback and only userId1 can active
630 */
631 g_mgr1.SetSyncActivationCheckCallback(g_syncActivationCheckCallback2);
632 /**
633 * @tc.steps: step2. openstore1 in dual tuple sync mode and openstore2 in normal sync mode
634 * @tc.expected: step2. only user2 sync mode is active
635 */
636 OpenStore1(true);
637 OpenStore2(false);
638 /**
639 * @tc.steps: step3. set SyncActivationCheckCallback and only userId2 can active
640 */
641 g_mgr1.SetSyncActivationCheckCallback(g_syncActivationCheckCallback1);
642 /**
643 * @tc.steps: step4. call NotifyUserChanged and close db concurrently
644 * @tc.expected: step4. return OK
645 */
__anon1d601b670802() 646 thread subThread([]() {
647 EXPECT_TRUE(KvStoreDelegateManager::NotifyUserChanged() == OK);
648 });
649 subThread.detach();
650 EXPECT_EQ(g_mgr1.CloseKvStore(g_kvDelegatePtr1), OK);
651 g_kvDelegatePtr1 = nullptr;
652 CloseStore();
653 }
654
655 /**
656 * @tc.name: MultiUser007
657 * @tc.desc: test NotifyUserChanged and rekey db concurrently
658 * @tc.type: FUNC
659 * @tc.require:
660 * @tc.author: zhuwentao
661 */
662 HWTEST_F(DistributedDBSingleVerMultiUserTest, MultiUser007, TestSize.Level0)
663 {
664 /**
665 * @tc.steps: step1. set SyncActivationCheckCallback and only userId1 can active
666 */
667 g_mgr1.SetSyncActivationCheckCallback(g_syncActivationCheckCallback2);
668 /**
669 * @tc.steps: step2. openstore1 in dual tuple sync mode and openstore2 in normal sync mode
670 * @tc.expected: step2. only user2 sync mode is active
671 */
672 OpenStore1(true);
673 OpenStore2(false);
674 /**
675 * @tc.steps: step3. set SyncActivationCheckCallback and only userId2 can active
676 */
677 g_mgr1.SetSyncActivationCheckCallback(g_syncActivationCheckCallback1);
678 /**
679 * @tc.steps: step2. call NotifyUserChanged and close db concurrently
680 * @tc.expected: step2. return OK
681 */
682 CipherPassword passwd;
__anon1d601b670902() 683 thread subThread([]() {
684 EXPECT_TRUE(KvStoreDelegateManager::NotifyUserChanged() == OK);
685 });
686 subThread.detach();
687 std::this_thread::sleep_for(std::chrono::milliseconds(1));
688 EXPECT_TRUE(g_kvDelegatePtr1->Rekey(passwd) == OK);
689 CloseStore();
690 }
691
692 /**
693 * @tc.name: MultiUser008
694 * @tc.desc: test NotifyUserChanged and block sync concurrently
695 * @tc.type: FUNC
696 * @tc.require:
697 * @tc.author: zhuwentao
698 */
699 HWTEST_F(DistributedDBSingleVerMultiUserTest, MultiUser008, TestSize.Level1)
700 {
701 TestSyncWithUserChange(true);
702 }
703
704 /**
705 * @tc.name: MultiUser009
706 * @tc.desc: test NotifyUserChanged and non-block sync concurrently
707 * @tc.type: FUNC
708 * @tc.require:
709 * @tc.author: zhuwentao
710 */
711 HWTEST_F(DistributedDBSingleVerMultiUserTest, MultiUser009, TestSize.Level0)
712 {
713 TestSyncWithUserChange(false);
714 }
715
716 /**
717 * @tc.name: MultiUser010
718 * @tc.desc: test NotifyUserChanged and non-block sync with multi devices concurrently
719 * @tc.type: FUNC
720 * @tc.require:
721 * @tc.author: zhuwentao
722 */
723 HWTEST_F(DistributedDBSingleVerMultiUserTest, MultiUser010, TestSize.Level3)
724 {
725 /**
726 * @tc.steps: step1. set SyncActivationCheckCallback and only userId1 can active
727 */
728 g_mgr1.SetSyncActivationCheckCallback(g_syncActivationCheckCallback2);
729 /**
730 * @tc.steps: step2. openstore1 and openstore2 in dual tuple sync mode
731 * @tc.expected: step2. only userId1 sync mode is active
732 */
733 OpenStore1(true);
734 OpenStore2(true);
735 /**
736 * @tc.steps: step3. set SyncActivationCheckCallback and only userId2 can active
737 */
738 g_mgr1.SetSyncActivationCheckCallback(g_syncActivationCheckCallback1);
739 /**
740 * @tc.steps: step4. deviceA put {k1, v1}
741 */
742 Key key = {'1'};
743 Value value = {'1'};
744 EXPECT_TRUE(g_kvDelegatePtr1->Put(key, value) == OK);
745
746 /**
747 * @tc.steps: step5. deviceB set sava data dely 5s
748 */
749 g_deviceC->SetSaveDataDelayTime(WAIT_3_SECONDS);
750 /**
751 * @tc.steps: step6. call NotifyUserChanged and block sync db concurrently
752 * @tc.expected: step6. return OK
753 */
754 CipherPassword passwd;
__anon1d601b670a02() 755 thread subThread([]() {
756 std::this_thread::sleep_for(std::chrono::milliseconds(1000));
757 EXPECT_TRUE(KvStoreDelegateManager::NotifyUserChanged() == OK);
758 });
759 subThread.detach();
760 /**
761 * @tc.steps: step7. deviceA call sync and wait
762 * @tc.expected: step7. sync should return OK.
763 */
764 std::map<std::string, DBStatus> result;
765 std::vector<std::string> devices = {g_deviceB->GetDeviceId(), g_deviceC->GetDeviceId()};
766 DBStatus status = g_tool.SyncTest(g_kvDelegatePtr1, devices, SYNC_MODE_PUSH_ONLY, result, false);
767 EXPECT_TRUE(status == OK);
768
769 /**
770 * @tc.expected: step8. onComplete should be called, and status is USER_CHANGED
771 */
772 EXPECT_TRUE(result.size() == devices.size());
773 for (const auto &pair : result) {
774 LOGD("dev %s, status %d", pair.first.c_str(), pair.second);
775 if (pair.first == g_deviceB->GetDeviceId()) {
776 EXPECT_TRUE(pair.second == OK);
777 } else {
778 EXPECT_TRUE(pair.second == USER_CHANGED);
779 }
780 }
781 std::this_thread::sleep_for(std::chrono::milliseconds(WAIT_3_SECONDS));
782 CloseStore();
783 }
784
785 /**
786 * @tc.name: MultiUser011
787 * @tc.desc: test check sync active twice when open store
788 * @tc.type: FUNC
789 * @tc.require:
790 * @tc.author: zhangqiquan
791 */
792 HWTEST_F(DistributedDBSingleVerMultiUserTest, MultiUser011, TestSize.Level1)
793 {
794 uint32_t callCount = 0u;
795 /**
796 * @tc.steps: step1. set SyncActivationCheckCallback and record call count, only first call return not active
797 */
798 g_mgr1.SetSyncActivationCheckCallback([&callCount] (const std::string &userId, const std::string &appId,
__anon1d601b670b02(const std::string &userId, const std::string &appId, const std::string &storeId) 799 const std::string &storeId) -> bool {
800 callCount++;
801 return callCount != 1;
802 });
803 /**
804 * @tc.steps: step2. openstore1 in dual tuple sync mode
805 * @tc.expected: step2. it should be activated finally
806 */
807 OpenStore1(true);
808 /**
809 * @tc.steps: step3. call sync to DEVICES_B
810 * @tc.expected: step3. should return OK, not NOT_ACTIVE
811 */
812 std::map<std::string, DBStatus> result;
813 std::vector<std::string> devices = {g_deviceB->GetDeviceId()};
814 EXPECT_EQ(g_tool.SyncTest(g_kvDelegatePtr1, devices, SYNC_MODE_PUSH_ONLY, result, true), OK);
815 CloseStore();
816 }
817
818 /**
819 * @tc.name: MultiUser012
820 * @tc.desc: test NotifyUserChanged and SetEqualIdentifier sync concurrently
821 * @tc.type: FUNC
822 * @tc.require:
823 * @tc.author: zhangqiquan
824 */
825 HWTEST_F(DistributedDBSingleVerMultiUserTest, MultiUser012, TestSize.Level1)
826 {
827 /**
828 * @tc.steps: step1. set SyncActivationCheckCallback and only userId1 can active
829 */
830 g_mgr1.SetSyncActivationCheckCallback(g_syncActivationCheckCallback2);
831 /**
832 * @tc.steps: step2. openstore1 and openstore2 in dual tuple sync mode
833 * @tc.expected: step2. only userId1 sync mode is active
834 */
835 OpenStore1(true);
836 OpenStore2(true);
837 /**
838 * @tc.steps: step3. set SyncActivationCheckCallback and only userId2 can active
839 */
840 g_mgr1.SetSyncActivationCheckCallback(g_syncActivationCheckCallback1);
841 /**
842 * @tc.steps: step4. SetEqualIdentifier and NotifyUserChanged concurrently called
843 */
__anon1d601b670c02() 844 thread subThread([]() {
845 EXPECT_TRUE(KvStoreDelegateManager::NotifyUserChanged() == OK);
846 });
847 std::string identifier = KvStoreDelegateManager::GetKvStoreIdentifier("default", APP_ID, STORE_ID);
848 std::vector<std::string> devices = {g_deviceB->GetDeviceId()};
849 g_kvDelegatePtr1->SetEqualIdentifier(identifier, devices);
850 std::this_thread::sleep_for(std::chrono::milliseconds(WAIT_3_SECONDS));
851 subThread.join();
852 CloseStore();
853 }
854
855 /**
856 * @tc.name: MultiUser013
857 * @tc.desc: test dont check sync active when open store with normal store
858 * @tc.type: FUNC
859 * @tc.require:
860 * @tc.author: zhangqiquan
861 */
862 HWTEST_F(DistributedDBSingleVerMultiUserTest, MultiUser013, TestSize.Level1)
863 {
864 uint32_t callCount = 0u;
865 /**
866 * @tc.steps: step1. set SyncActivationCheckCallback and record call count
867 */
868 KvStoreDelegateManager::SetSyncActivationCheckCallback(
__anon1d601b670d02(const std::string &userId, const std::string &appId, const std::string &storeId) 869 [&callCount] (const std::string &userId, const std::string &appId, const std::string &storeId) -> bool {
870 callCount++;
871 return true;
872 });
873 /**
874 * @tc.steps: step2. openStore in no dual tuple sync mode
875 * @tc.expected: step2. it should be activated finally, and callCount should be zero
876 */
877 OpenStore1(false);
878 EXPECT_EQ(callCount, 0u);
879 CloseStore();
880 }
881
882 /**
883 * @tc.name: MultiUser014
884 * @tc.desc: test active callback call count
885 * @tc.type: FUNC
886 * @tc.require:
887 * @tc.author: zhangqiquan
888 */
889 HWTEST_F(DistributedDBSingleVerMultiUserTest, MultiUser014, TestSize.Level1)
890 {
891 uint32_t callCount = 0u;
892 /**
893 * @tc.steps: step1. set SyncActivationCheckCallback and record call count
894 */
895 KvStoreDelegateManager::SetSyncActivationCheckCallback(
__anon1d601b670e02(const std::string &userId, const std::string &appId, const std::string &storeId) 896 [&callCount] (const std::string &userId, const std::string &appId, const std::string &storeId) -> bool {
897 callCount++;
898 return false;
899 });
900 /**
901 * @tc.steps: step2. openStore in dual tuple sync mode
902 * @tc.expected: step2. it should not be activated finally, and callCount should be 2
903 */
904 OpenStore1(true);
905 EXPECT_EQ(callCount, 2u); // 2 is call count
906 callCount = 0u;
907 EXPECT_EQ(g_kvDelegatePtr1->RemoveDeviceData(), OK);
908 EXPECT_EQ(callCount, 0u);
909 CloseStore();
910 }
911
912 /**
913 * @tc.name: MultiUser015
914 * @tc.desc: Test auto launch with sub user.
915 * @tc.type: FUNC
916 * @tc.require:
917 * @tc.author: liaoyonghuang
918 */
919 HWTEST_F(DistributedDBSingleVerMultiUserTest, MultiUser015, TestSize.Level1)
920 {
921 /**
922 * @tc.steps: step1. create sub user KvStoreDelegateManager
923 * @tc.expected: step1. OK.
924 */
925 std::string subUser = "001";
926 KvStoreDelegateManager subUserMgr(APP_ID, USER_ID_1, subUser);
927 std::string subUserPath = g_testDir + "/" + subUser;
928 ASSERT_TRUE(OS::MakeDBDirectory(subUserPath) == 0);
929 KvStoreConfig config;
930 config.dataDir = subUserPath;
931 subUserMgr.SetKvStoreConfig(config);
932 KvStoreNbDelegate::Option option;
933 /**
934 * @tc.steps: step2. Enable auto launch of sub user
935 * @tc.expected: step2. success.
936 */
937 AutoLaunchNotifier notifier = nullptr;
938 KvStoreObserverUnitTest *observer = new (std::nothrow) KvStoreObserverUnitTest;
939 EXPECT_TRUE(observer != nullptr);
940 AutoLaunchOption autoLaunchOption;
941 CipherPassword passwd;
942 autoLaunchOption = {true, false, CipherType::DEFAULT, passwd, "", false, subUserPath, observer,
943 0, nullptr};
944 autoLaunchOption.notifier = nullptr;
945 autoLaunchOption.observer = observer;
946 autoLaunchOption.syncDualTupleMode = false;
947 EXPECT_TRUE(subUserMgr.EnableKvStoreAutoLaunch(
948 {USER_ID_1, APP_ID, STORE_ID, autoLaunchOption, notifier, "", subUser}) == OK);
949 DistributedDBToolsUnitTest::Dump();
950 /**
951 * @tc.steps: step3. Device B put data and sync
952 * @tc.expected: step3. success.
953 */
954 Key key = {'1'};
955 Value value = {'1'};
956 Timestamp currentTime;
957 (void)OS::GetCurrentSysTimeInMicrosecond(currentTime);
958 EXPECT_TRUE(g_deviceB->PutData(key, value, currentTime, 0) == E_OK);
959 EXPECT_TRUE(g_deviceB->Sync(SYNC_MODE_PUSH_ONLY, true) == E_OK);
960 /**
961 * @tc.steps: step4. Open kv store of sub user and check data
962 * @tc.expected: step4. Check data success.
963 */
964 subUserMgr.GetKvStore(STORE_ID, option, g_kvDelegateCallback1);
965 ASSERT_TRUE(g_kvDelegateStatus1 == OK);
966 ASSERT_TRUE(g_kvDelegatePtr1 != nullptr);
967 Value actualValue;
968 EXPECT_EQ(g_kvDelegatePtr1->Get(key, actualValue), E_OK);
969 EXPECT_EQ(actualValue, value);
970 /**
971 * @tc.steps: step5. Disable auto launch and close kv store.
972 * @tc.expected: step5. success.
973 */
974 EXPECT_TRUE(subUserMgr.DisableKvStoreAutoLaunch(USER_ID_1, subUser, APP_ID, STORE_ID) == OK);
975 ASSERT_EQ(subUserMgr.CloseKvStore(g_kvDelegatePtr1), OK);
976 g_kvDelegatePtr1 = nullptr;
977 DBStatus status = subUserMgr.DeleteKvStore(STORE_ID);
978 ASSERT_TRUE(status == OK);
979 delete observer;
980 }
981