• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 &param, 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