• 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 <gtest/gtest.h>
17 
18 #include "db_constant.h"
19 #include "db_properties.h"
20 #include "distributeddb_data_generate_unit_test.h"
21 #include "distributeddb_tools_unit_test.h"
22 #include "platform_specific.h"
23 #include "relational_store_delegate.h"
24 #include "relational_store_manager.h"
25 #include "relational_virtual_device.h"
26 #include "runtime_config.h"
27 #include "virtual_relational_ver_sync_db_interface.h"
28 
29 using namespace testing::ext;
30 using namespace DistributedDB;
31 using namespace DistributedDBUnitTest;
32 using namespace std;
33 
34 namespace {
35     string g_testDir;
36     const string STORE_ID = "rdb_stroe_sync_test";
37     const string USER_ID_1 = "userId1";
38     const string USER_ID_2 = "userId2";
39     const std::string DEVICE_B = "deviceB";
40     const std::string DEVICE_C = "deviceC";
41     const int WAIT_TIME = 1000; // 1000ms
42     const std::string g_tableName = "TEST_TABLE";
43     std::string g_identifier;
44 
45     RelationalStoreManager g_mgr1(APP_ID, USER_ID_1);
46     RelationalStoreManager g_mgr2(APP_ID, USER_ID_2);
47     KvStoreConfig g_config;
48     DistributedDBToolsUnitTest g_tool;
49     RelationalStoreDelegate* g_rdbDelegatePtr1 = nullptr;
50     RelationalStoreDelegate* g_rdbDelegatePtr2 = nullptr;
51     VirtualCommunicatorAggregator* g_communicatorAggregator = nullptr;
52     RelationalVirtualDevice *g_deviceB = nullptr;
53     RelationalVirtualDevice *g_deviceC = nullptr;
54     std::string g_dbDir;
55     std::string g_storePath1;
56     std::string g_storePath2;
57     RelationalStoreObserverUnitTest *g_observer = nullptr;
58 
59     auto g_syncActivationCheckCallback1 = [] (const std::string &userId, const std::string &appId,
__anonc9560f830202(const std::string &userId, const std::string &appId, const std::string &storeId)60         const std::string &storeId)-> bool {
61         if (userId == USER_ID_2) {
62             LOGE("active call back1, active user2");
63             return true;
64         } else {
65             LOGE("active call back1, no need to active user1");
66             return false;
67         }
68     };
69     auto g_syncActivationCheckCallback2 = [] (const std::string &userId, const std::string &appId,
__anonc9560f830302(const std::string &userId, const std::string &appId, const std::string &storeId)70         const std::string &storeId)-> bool {
71         if (userId == USER_ID_1) {
72             LOGE("active call back2, active user1");
73             return true;
74         } else {
75             LOGE("active call back2, no need to active user2");
76             return false;
77         }
78     };
79 
DropTable(sqlite3 * db,const std::string & tableName)80     int DropTable(sqlite3 *db, const std::string &tableName)
81     {
82         std::string sql = "DROP TABLE IF EXISTS " + tableName + ";";
83         char *errMsg = nullptr;
84         int rc = sqlite3_exec(db, sql.c_str(), nullptr, nullptr, &errMsg);
85         if (rc != 0) {
86             LOGE("failed to drop table: %s, errMsg: %s", tableName.c_str(), errMsg);
87         }
88         return rc;
89     }
90 
CreateTable(sqlite3 * db,const std::string & tableName)91     int CreateTable(sqlite3 *db, const std::string &tableName)
92     {
93         std::string sql = "CREATE TABLE " + tableName + "(id int, name text);";
94         int rc = sqlite3_exec(db, sql.c_str(), nullptr, nullptr, nullptr);
95         return rc;
96     }
97 
InsertValue(sqlite3 * db,const std::string & tableName)98     int InsertValue(sqlite3 *db, const std::string &tableName)
99     {
100         std::string sql = "insert into " + tableName + " values(1, 'aaa');";
101         return sqlite3_exec(db, sql.c_str(), nullptr, nullptr, nullptr);
102     }
103 
GetDB(sqlite3 * & db,const std::string & dbPath)104     int GetDB(sqlite3 *&db, const std::string &dbPath)
105     {
106         int flag = SQLITE_OPEN_URI | SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE;
107         int rc = sqlite3_open_v2(dbPath.c_str(), &db, flag, nullptr);
108         if (rc != SQLITE_OK) {
109             return rc;
110         }
111         EXPECT_EQ(SQLiteUtils::RegisterCalcHash(db), E_OK);
112         EXPECT_EQ(SQLiteUtils::RegisterGetSysTime(db), E_OK);
113         EXPECT_EQ(sqlite3_exec(db, "PRAGMA journal_mode=WAL;", nullptr, nullptr, nullptr), SQLITE_OK);
114         return rc;
115     }
116 
PrepareVirtualDeviceEnv(const std::string & tableName,const std::string & dbPath,std::vector<RelationalVirtualDevice * > & remoteDeviceVec)117     void PrepareVirtualDeviceEnv(const std::string &tableName, const std::string &dbPath,
118         std::vector<RelationalVirtualDevice *> &remoteDeviceVec)
119     {
120         sqlite3 *db = nullptr;
121         EXPECT_EQ(GetDB(db, dbPath), SQLITE_OK);
122         TableInfo tableInfo;
123         SQLiteUtils::AnalysisSchema(db, tableName, tableInfo);
124         for (auto &dev : remoteDeviceVec) {
125             std::vector<FieldInfo> fieldInfoList = tableInfo.GetFieldInfos();
126             dev->SetLocalFieldInfo(fieldInfoList);
127             dev->SetTableInfo(tableInfo);
128         }
129     }
130 
PrepareData(const std::string & tableName,const std::string & dbPath)131     void PrepareData(const std::string &tableName, const std::string &dbPath)
132     {
133         sqlite3 *db = nullptr;
134         EXPECT_EQ(GetDB(db, dbPath), SQLITE_OK);
135         EXPECT_EQ(InsertValue(db, tableName), SQLITE_OK);
136     }
137 
OpenStore1(bool syncDualTupleMode=true)138     void OpenStore1(bool syncDualTupleMode = true)
139     {
140         if (g_observer == nullptr) {
141             g_observer = new (std::nothrow) RelationalStoreObserverUnitTest();
142         }
143         RelationalStoreDelegate::Option option = {g_observer};
144         option.syncDualTupleMode = syncDualTupleMode;
145         g_mgr1.OpenStore(g_storePath1, STORE_ID_1, option, g_rdbDelegatePtr1);
146         ASSERT_TRUE(g_rdbDelegatePtr1 != nullptr);
147     }
148 
OpenStore2(bool syncDualTupleMode=true)149     void OpenStore2(bool syncDualTupleMode = true)
150     {
151         if (g_observer == nullptr) {
152             g_observer = new (std::nothrow) RelationalStoreObserverUnitTest();
153         }
154         RelationalStoreDelegate::Option option = {g_observer};
155         option.syncDualTupleMode = syncDualTupleMode;
156         g_mgr2.OpenStore(g_storePath2, STORE_ID_2, option, g_rdbDelegatePtr2);
157         ASSERT_TRUE(g_rdbDelegatePtr2 != nullptr);
158     }
159 
CloseStore()160     void CloseStore()
161     {
162         if (g_rdbDelegatePtr1 != nullptr) {
163             ASSERT_EQ(g_mgr1.CloseStore(g_rdbDelegatePtr1), OK);
164             g_rdbDelegatePtr1 = nullptr;
165             LOGD("delete rdb store");
166         }
167         if (g_rdbDelegatePtr2 != nullptr) {
168             ASSERT_EQ(g_mgr2.CloseStore(g_rdbDelegatePtr2), OK);
169             g_rdbDelegatePtr2 = nullptr;
170             LOGD("delete rdb store");
171         }
172     }
173 
PrepareEnvironment(const std::string & tableName,const std::string & dbPath,RelationalStoreDelegate * rdbDelegate)174     void PrepareEnvironment(const std::string &tableName, const std::string &dbPath,
175         RelationalStoreDelegate* rdbDelegate)
176     {
177         sqlite3 *db = nullptr;
178         EXPECT_EQ(GetDB(db, dbPath), SQLITE_OK);
179         EXPECT_EQ(DropTable(db, tableName), SQLITE_OK);
180         EXPECT_EQ(CreateTable(db, tableName), SQLITE_OK);
181         EXPECT_EQ(rdbDelegate->CreateDistributedTable(tableName), OK);
182         sqlite3_close(db);
183     }
184 
CheckSyncTest(DBStatus status1,DBStatus status2,std::vector<std::string> & devices)185     void CheckSyncTest(DBStatus status1, DBStatus status2, std::vector<std::string> &devices)
186     {
187         std::map<std::string, std::vector<TableStatus>> statusMap;
188         SyncStatusCallback callBack = [&statusMap](
189             const std::map<std::string, std::vector<TableStatus>> &devicesMap) {
190             statusMap = devicesMap;
191         };
192         Query query = Query::Select(g_tableName);
193         DBStatus status = g_rdbDelegatePtr1->Sync(devices, SYNC_MODE_PUSH_ONLY, query, callBack, true);
194         LOGE("expect status is: %d, actual is %d", status1, status);
195         ASSERT_TRUE(status == status1);
196         if (status == OK) {
197             for (const auto &pair : statusMap) {
198                 for (const auto &tableStatus : pair.second) {
199                     LOGD("dev %s, status %d", pair.first.c_str(), tableStatus.status);
200                     EXPECT_TRUE(tableStatus.status == OK);
201                 }
202             }
203         }
204         statusMap.clear();
205 
206         std::map<std::string, std::vector<TableStatus>> statusMap2;
207         SyncStatusCallback callBack2 = [&statusMap2](
208             const std::map<std::string, std::vector<TableStatus>> &devicesMap) {
209             LOGE("call back devicesMap.size = %d", devicesMap.size());
210             statusMap2 = devicesMap;
211         };
212         status = g_rdbDelegatePtr2->Sync(devices, SYNC_MODE_PUSH_ONLY, query, callBack2, true);
213         LOGE("expect status2 is: %d, actual is %d, statusMap2.size = %d", status2, status, statusMap2.size());
214         ASSERT_TRUE(status == status2);
215         if (status == OK) {
216             for (const auto &pair : statusMap2) {
217                 for (const auto &tableStatus : pair.second) {
218                     LOGE("*********** rdb dev %s, status %d", pair.first.c_str(), tableStatus.status);
219                     EXPECT_TRUE(tableStatus.status == OK);
220                 }
221             }
222         }
223         statusMap.clear();
224     }
225 
DoRemoteQuery()226     void DoRemoteQuery()
227     {
228         RemoteCondition condition;
229         condition.sql = "SELECT * FROM " + g_tableName;
230         std::shared_ptr<ResultSet> result = std::make_shared<RelationalResultSetImpl>();
231         EXPECT_EQ(g_rdbDelegatePtr1->RemoteQuery(g_deviceB->GetDeviceId(), condition,
232             DBConstant::MAX_TIMEOUT, result), USER_CHANGED);
233         EXPECT_EQ(result, nullptr);
234         g_communicatorAggregator->RegOnDispatch(nullptr);
235         CloseStore();
236     }
237 
CheckSyncResult(bool wait,bool isRemoteQuery)238     void CheckSyncResult(bool wait, bool isRemoteQuery)
239     {
240         std::mutex syncLock_{};
241         std::condition_variable syncCondVar_{};
242         std::map<std::string, std::vector<TableStatus>> statusMap;
243         SyncStatusCallback callBack = [&statusMap, &syncLock_, &syncCondVar_, wait](
244             const std::map<std::string, std::vector<TableStatus>> &devicesMap) {
245             statusMap = devicesMap;
246             if (!wait) {
247                 std::unique_lock<std::mutex> innerlock(syncLock_);
248                 syncCondVar_.notify_one();
249             }
250         };
251         Query query = Query::Select(g_tableName);
252         std::vector<std::string> devices;
253         devices.push_back(g_deviceB->GetDeviceId());
254         std::vector<RelationalVirtualDevice *> remoteDev;
255         remoteDev.push_back(g_deviceB);
256         PrepareVirtualDeviceEnv(g_tableName, g_storePath1, remoteDev);
257 
258         DBStatus status = DB_ERROR;
259         if (isRemoteQuery) {
260             DoRemoteQuery();
261             return;
262         }
263 
264         status = g_rdbDelegatePtr1->Sync(devices, SYNC_MODE_PUSH_ONLY, query, callBack, wait);
265         EXPECT_EQ(status, OK);
266 
267         if (!wait) {
268             std::unique_lock<std::mutex> lock(syncLock_);
269             syncCondVar_.wait(lock, [status, &statusMap]() {
270                 if (status != OK) {
271                     return true;
272                 }
273                 return !statusMap.empty();
274             });
275         }
276 
277         g_communicatorAggregator->RegOnDispatch(nullptr);
278         EXPECT_EQ(statusMap.size(), devices.size());
279         for (const auto &pair : statusMap) {
280             for (const auto &tableStatus : pair.second) {
281                 EXPECT_TRUE(tableStatus.status == USER_CHANGED);
282             }
283         }
284         CloseStore();
285     }
286 
287     int g_currentStatus = 0;
288     const AutoLaunchNotifier g_nofifier = [](const std::string &userId,
__anonc9560f830802(const std::string &userId, const std::string &appId, const std::string &storeId, AutoLaunchStatus status) 289         const std::string &appId, const std::string &storeId, AutoLaunchStatus status) {
290             LOGE("notifier status = %d", status);
291             g_currentStatus = static_cast<int>(status);
292         };
293 
__anonc9560f830902(const std::string &identifier, AutoLaunchParam &param) 294     const AutoLaunchRequestCallback g_callback = [](const std::string &identifier, AutoLaunchParam &param) {
295         if (g_identifier != identifier) {
296             LOGE("g_identifier(%s) != identifier(%s)", g_identifier.c_str(), identifier.c_str());
297             return false;
298         }
299         param.path    = g_testDir + "/test2.db";
300         param.appId   = APP_ID;
301         param.storeId = STORE_ID;
302         CipherPassword passwd;
303         param.option = {true, false, CipherType::DEFAULT, passwd, "", false, g_testDir, nullptr,
304             0, nullptr};
305         param.notifier = g_nofifier;
306         param.option.syncDualTupleMode = true;
307         return true;
308     };
309 
310 
TestSyncWithUserChange(bool wait,bool isRemoteQuery)311     void TestSyncWithUserChange(bool wait, bool isRemoteQuery)
312     {
313         /**
314          * @tc.steps: step1. set SyncActivationCheckCallback and only userId1 can active
315          */
316         RuntimeConfig::SetSyncActivationCheckCallback(g_syncActivationCheckCallback2);
317         /**
318          * @tc.steps: step2. openstore1 in dual tuple sync mode and openstore2 in normal sync mode
319          * @tc.expected: step2. only user2 sync mode is active
320          */
321         OpenStore1(true);
322         OpenStore2(true);
323 
324         /**
325          * @tc.steps: step3. prepare environment
326          */
327         PrepareEnvironment(g_tableName, g_storePath1, g_rdbDelegatePtr1);
328         PrepareEnvironment(g_tableName, g_storePath2, g_rdbDelegatePtr2);
329 
330         /**
331          * @tc.steps: step4. prepare data
332          */
333         PrepareData(g_tableName, g_storePath1);
334         PrepareData(g_tableName, g_storePath2);
335 
336         /**
337          * @tc.steps: step5. set SyncActivationCheckCallback and only userId2 can active
338          */
339         RuntimeConfig::SetSyncActivationCheckCallback(g_syncActivationCheckCallback1);
340 
341         /**
342          * @tc.steps: step6. call NotifyUserChanged and block sync db concurrently
343          * @tc.expected: step6. return OK
344          */
345         CipherPassword passwd;
346         bool startSync = false;
347         std::condition_variable cv;
348         thread subThread([&]() {
349             std::mutex notifyLock;
350             std::unique_lock<std::mutex> lck(notifyLock);
351             cv.wait(lck, [&startSync]() { return startSync; });
352             EXPECT_TRUE(RuntimeConfig::NotifyUserChanged() == OK);
353         });
354         subThread.detach();
355         g_communicatorAggregator->RegOnDispatch([&](const std::string&, Message *inMsg) {
356             if (!startSync) {
357                 startSync = true;
358                 cv.notify_all();
359             }
360         });
361 
362         /**
363          * @tc.steps: step7. deviceA call sync and wait
364          * @tc.expected: step7. sync should return OK.
365          */
366         CheckSyncResult(wait, isRemoteQuery);
367     }
368 
PrepareSelect(sqlite3 * db,sqlite3_stmt * & statement,const std::string & table)369     int PrepareSelect(sqlite3 *db, sqlite3_stmt *&statement, const std::string &table)
370     {
371         std::string dis_tableName = RelationalStoreManager::GetDistributedTableName(DEVICE_B, table);
372         const std::string sql = "SELECT * FROM " + dis_tableName;
373         LOGE("exec sql: %s", sql.c_str());
374         return sqlite3_prepare_v2(db, sql.c_str(), -1, &statement, nullptr);
375     }
376 
CheckDataInRealDevice()377     void CheckDataInRealDevice()
378     {
379         sqlite3 *db = nullptr;
380         EXPECT_EQ(GetDB(db, g_storePath2), SQLITE_OK);
381 
382         sqlite3_stmt *statement = nullptr;
383         EXPECT_EQ(PrepareSelect(db, statement, g_tableName), SQLITE_OK);
384         int rowCount = 0;
385         while (true) {
386             int rc = sqlite3_step(statement);
387             if (rc != SQLITE_ROW) {
388                 LOGD("GetSyncData Exist by code[%d]", rc);
389                 break;
390             }
391             int columnCount = sqlite3_column_count(statement);
392             EXPECT_EQ(columnCount, 2); // 2: result index
393             rowCount++;
394         }
395         EXPECT_EQ(rowCount, 1);
396         sqlite3_finalize(statement);
397     }
398 }
399 
400 class DistributedDBRelationalMultiUserTest : public testing::Test {
401 public:
402     static void SetUpTestCase(void);
403     static void TearDownTestCase(void);
404     void SetUp();
405     void TearDown();
406 };
407 
SetUpTestCase(void)408 void DistributedDBRelationalMultiUserTest::SetUpTestCase(void)
409 {
410     /**
411     * @tc.setup: Init datadir and Virtual Communicator.
412     */
413     DistributedDBToolsUnitTest::TestDirInit(g_testDir);
414     g_storePath1 = g_testDir + "/test1.db";
415     g_storePath2 = g_testDir + "/test2.db";
416     sqlite3 *db1 = nullptr;
417     ASSERT_EQ(GetDB(db1, g_storePath1), SQLITE_OK);
418     sqlite3_close(db1);
419 
420     sqlite3 *db2 = nullptr;
421     ASSERT_EQ(GetDB(db2, g_storePath2), SQLITE_OK);
422     sqlite3_close(db2);
423 
424     g_communicatorAggregator = new (std::nothrow) VirtualCommunicatorAggregator();
425     ASSERT_TRUE(g_communicatorAggregator != nullptr);
426     RuntimeContext::GetInstance()->SetCommunicatorAggregator(g_communicatorAggregator);
427 }
428 
TearDownTestCase(void)429 void DistributedDBRelationalMultiUserTest::TearDownTestCase(void)
430 {
431     /**
432      * @tc.teardown: Release virtual Communicator and clear data dir.
433      */
434     if (DistributedDBToolsUnitTest::RemoveTestDbFiles(g_testDir) != 0) {
435         LOGE("rm test db files error!");
436     }
437     RuntimeContext::GetInstance()->SetCommunicatorAggregator(nullptr);
438 }
439 
SetUp(void)440 void DistributedDBRelationalMultiUserTest::SetUp(void)
441 {
442     DistributedDBToolsUnitTest::PrintTestCaseInfo();
443     /**
444      * @tc.setup: create virtual device B
445      */
446     g_deviceB = new (std::nothrow) RelationalVirtualDevice(DEVICE_B);
447     ASSERT_TRUE(g_deviceB != nullptr);
448     VirtualRelationalVerSyncDBInterface *syncInterfaceB = new (std::nothrow) VirtualRelationalVerSyncDBInterface();
449     ASSERT_TRUE(syncInterfaceB != nullptr);
450     ASSERT_EQ(g_deviceB->Initialize(g_communicatorAggregator, syncInterfaceB), E_OK);
451     g_deviceC = new (std::nothrow) RelationalVirtualDevice(DEVICE_C);
452     ASSERT_TRUE(g_deviceC != nullptr);
453     VirtualRelationalVerSyncDBInterface *syncInterfaceC = new (std::nothrow) VirtualRelationalVerSyncDBInterface();
454     ASSERT_TRUE(syncInterfaceC != nullptr);
455     ASSERT_EQ(g_deviceC->Initialize(g_communicatorAggregator, syncInterfaceC), E_OK);
456 }
457 
TearDown(void)458 void DistributedDBRelationalMultiUserTest::TearDown(void)
459 {
460     /**
461      * @tc.teardown: Release device A, B, C
462      */
463     if (g_deviceB != nullptr) {
464         delete g_deviceB;
465         g_deviceB = nullptr;
466     }
467     if (g_deviceC != nullptr) {
468         delete g_deviceC;
469         g_deviceC = nullptr;
470     }
471     SyncActivationCheckCallback callback = nullptr;
472     RuntimeConfig::SetSyncActivationCheckCallback(callback);
473 }
474 
475 /**
476  * @tc.name: multi user 001
477  * @tc.desc: Test multi user change for rdb
478  * @tc.type: FUNC
479  * @tc.require: AR000GK58G
480  * @tc.author: zhangshijie
481  */
482 HWTEST_F(DistributedDBRelationalMultiUserTest, RdbMultiUser001, TestSize.Level0)
483 {
484     /**
485      * @tc.steps: step1. set SyncActivationCheckCallback and only userId2 can active
486      */
487     RuntimeConfig::SetSyncActivationCheckCallback(g_syncActivationCheckCallback1);
488 
489     /**
490      * @tc.steps: step2. openstore1 and openstore2
491      * @tc.expected: step2. only user2 sync mode is active
492      */
493     OpenStore1();
494     OpenStore2();
495 
496     /**
497      * @tc.steps: step3. prepare environment
498      */
499     PrepareEnvironment(g_tableName, g_storePath1, g_rdbDelegatePtr1);
500     PrepareEnvironment(g_tableName, g_storePath2, g_rdbDelegatePtr2);
501 
502     /**
503      * @tc.steps: step4. prepare data
504      */
505     PrepareData(g_tableName, g_storePath1);
506     PrepareData(g_tableName, g_storePath2);
507 
508     /**
509      * @tc.steps: step5. g_rdbDelegatePtr1 and g_rdbDelegatePtr2 call sync
510      * @tc.expected: step5. g_rdbDelegatePtr2 call success
511      */
512     std::vector<std::string> devices;
513     devices.push_back(g_deviceB->GetDeviceId());
514     std::vector<RelationalVirtualDevice *> remoteDev;
515     remoteDev.push_back(g_deviceB);
516     remoteDev.push_back(g_deviceC);
517     PrepareVirtualDeviceEnv(g_tableName, g_storePath1, remoteDev);
518     CheckSyncTest(NOT_ACTIVE, OK, devices);
519 
520     /**
521      * @tc.expected: step6. onComplete should be called, DeviceB have {k1,v1}
522      */
523     std::vector<VirtualRowData> targetData;
524     g_deviceB->GetAllSyncData(g_tableName, targetData);
525     EXPECT_EQ(targetData.size(), 1u);
526 
527     /**
528      * @tc.expected: step7. user change
529      */
530     RuntimeConfig::SetSyncActivationCheckCallback(g_syncActivationCheckCallback2);
531     RuntimeConfig::NotifyUserChanged();
532     /**
533      * @tc.steps: step8. g_kvDelegatePtr1 and g_kvDelegatePtr2 call sync
534      * @tc.expected: step8. g_kvDelegatePtr1 call success
535      */
536     devices.clear();
537     devices.push_back(g_deviceC->GetDeviceId());
538     CheckSyncTest(OK, NOT_ACTIVE, devices);
539     /**
540      * @tc.expected: step9. onComplete should be called, DeviceC have {k1,v1}
541      */
542     targetData.clear();
543     g_deviceC->GetAllSyncData(g_tableName, targetData);
544     EXPECT_EQ(targetData.size(), 1u);
545     CloseStore();
546 }
547 
548 /**
549  * @tc.name: multi user 002
550  * @tc.desc: Test multi user not change for rdb
551  * @tc.type: FUNC
552  * @tc.require: AR000GK58G
553  * @tc.author: zhangshijie
554  */
555 HWTEST_F(DistributedDBRelationalMultiUserTest, RdbMultiUser002, TestSize.Level0)
556 {
557     /**
558      * @tc.steps: step1. set SyncActivationCheckCallback and only userId2 can active
559      */
560     RuntimeConfig::SetSyncActivationCheckCallback(g_syncActivationCheckCallback1);
561 
562     /**
563      * @tc.steps: step2. openstore1 and openstore2
564      * @tc.expected: step2. only user2 sync mode is active
565      */
566     OpenStore1();
567     OpenStore2();
568 
569     /**
570      * @tc.steps: step3. prepare environment
571      */
572     PrepareEnvironment(g_tableName, g_storePath1, g_rdbDelegatePtr1);
573     PrepareEnvironment(g_tableName, g_storePath2, g_rdbDelegatePtr2);
574 
575     /**
576      * @tc.steps: step4. prepare data
577      */
578     PrepareData(g_tableName, g_storePath1);
579     PrepareData(g_tableName, g_storePath2);
580 
581     /**
582      * @tc.steps: step4. GetRelationalStoreIdentifier success when userId is invalid
583      */
584     std::string userId;
585     EXPECT_TRUE(g_mgr1.GetRelationalStoreIdentifier(userId, APP_ID, USER_ID_2, true) != "");
586     userId.resize(130);
587     EXPECT_TRUE(g_mgr1.GetRelationalStoreIdentifier(userId, APP_ID, USER_ID_2, true) != "");
588 
589     /**
590      * @tc.steps: step5. g_rdbDelegatePtr1 and g_rdbDelegatePtr2 call sync
591      * @tc.expected: step5. g_rdbDelegatePtr2 call success
592      */
593     std::vector<std::string> devices;
594     devices.push_back(g_deviceB->GetDeviceId());
595     std::vector<RelationalVirtualDevice *> remoteDev;
596     remoteDev.push_back(g_deviceB);
597     remoteDev.push_back(g_deviceC);
598     PrepareVirtualDeviceEnv(g_tableName, g_storePath1, remoteDev);
599     CheckSyncTest(NOT_ACTIVE, OK, devices);
600 
601     /**
602      * @tc.expected: step6. onComplete should be called, DeviceB have {k1,v1}
603      */
604     std::vector<VirtualRowData> targetData;
605     g_deviceB->GetAllSyncData(g_tableName, targetData);
606     EXPECT_EQ(targetData.size(), 1u);
607 
608     /**
609      * @tc.expected: step7. user not change
610      */
611     RuntimeConfig::NotifyUserChanged();
612 
613     /**
614      * @tc.steps: step8. g_kvDelegatePtr1 and g_kvDelegatePtr2 call sync
615      * @tc.expected: step8. g_kvDelegatePtr1 call success
616      */
617     CheckSyncTest(NOT_ACTIVE, OK, devices);
618 
619     /**
620      * @tc.expected: step9. onComplete should be called, DeviceC have {k1,v1}
621      */
622     targetData.clear();
623     g_deviceB->GetAllSyncData(g_tableName, targetData);
624     EXPECT_EQ(targetData.size(), 1u);
625     CloseStore();
626 }
627 
628 /**
629  * @tc.name: multi user 003
630  * @tc.desc: enhancement callback return true in multiuser mode for rdb
631  * @tc.type: FUNC
632  * @tc.require: AR000GK58G
633  * @tc.author: zhangshijie
634  */
635 HWTEST_F(DistributedDBRelationalMultiUserTest, RdbMultiUser003, TestSize.Level3)
636 {
637     /**
638      * @tc.steps: step1. prepare environment
639      */
640     OpenStore1();
641     OpenStore2();
642     PrepareEnvironment(g_tableName, g_storePath1, g_rdbDelegatePtr1);
643     PrepareEnvironment(g_tableName, g_storePath2, g_rdbDelegatePtr2);
644     CloseStore();
645 
646     /**
647      * @tc.steps: step2. set SyncActivationCheckCallback and only userId2 can active
648      */
649     RuntimeConfig::SetSyncActivationCheckCallback(g_syncActivationCheckCallback1);
650 
651     /**
652      * @tc.steps: step3. SetAutoLaunchRequestCallback
653      * @tc.expected: step3. success.
654      */
655     g_mgr1.SetAutoLaunchRequestCallback(g_callback);
656 
657     /**
658      * @tc.steps: step4. RunCommunicatorLackCallback
659      * @tc.expected: step4. success.
660      */
661     g_identifier = g_mgr1.GetRelationalStoreIdentifier(USER_ID_2, APP_ID, STORE_ID, true);
662     EXPECT_TRUE(g_identifier == g_mgr1.GetRelationalStoreIdentifier(USER_ID_1, APP_ID, STORE_ID, true));
663     std::vector<uint8_t> label(g_identifier.begin(), g_identifier.end());
664     g_communicatorAggregator->SetCurrentUserId(USER_ID_2);
665     g_communicatorAggregator->RunCommunicatorLackCallback(label);
666     std::this_thread::sleep_for(std::chrono::milliseconds(WAIT_TIME));
667 
668     /**
669      * @tc.steps: step5. device B put one data
670      * @tc.expected: step5. success.
671      */
672     VirtualRowData virtualRowData;
673     DataValue d1;
674     d1 = (int64_t)1;
675     virtualRowData.objectData.PutDataValue("id", d1);
676     DataValue d2;
677     d2.SetText("hello");
678     virtualRowData.objectData.PutDataValue("name", d2);
679     virtualRowData.logInfo.timestamp = 1;
680     g_deviceB->PutData(g_tableName, {virtualRowData});
681 
682     std::vector<RelationalVirtualDevice *> remoteDev;
683     remoteDev.push_back(g_deviceB);
684     PrepareVirtualDeviceEnv(g_tableName, g_storePath1, remoteDev);
685 
686     /**
687      * @tc.steps: step6. device B push sync to A
688      * @tc.expected: step6. success.
689      */
690     Query query = Query::Select(g_tableName);
691     EXPECT_EQ(g_deviceB->GenericVirtualDevice::Sync(SYNC_MODE_PUSH_ONLY, query, true), OK);
692 
693     /**
694      * @tc.steps: step7. deviceA have {k1,v1}
695      * @tc.expected: step7. success.
696      */
697     CheckDataInRealDevice();
698     std::this_thread::sleep_for(std::chrono::seconds(70)); // the store will close after 60 sec aotumatically
699     g_mgr1.SetAutoLaunchRequestCallback(nullptr);
700     EXPECT_EQ(g_currentStatus, AutoLaunchStatus::WRITE_CLOSED);
701     g_currentStatus = 0;
702     CloseStore();
703 }
704 
705 /**
706  * @tc.name: multi user 004
707  * @tc.desc: test NotifyUserChanged func when all db in normal sync mode for rdb
708  * @tc.type: FUNC
709  * @tc.require: AR000GK58G
710  * @tc.author: zhangshijie
711  */
712 HWTEST_F(DistributedDBRelationalMultiUserTest, RdbMultiUser004, TestSize.Level0)
713 {
714     /**
715      * @tc.steps: step1. openstore1 and openstore2 in normal sync mode
716      * @tc.expected: step1. only user2 sync mode is active
717      */
718     OpenStore1(false);
719     OpenStore2(false);
720 
721     /**
722      * @tc.steps: step2. call NotifyUserChanged
723      * @tc.expected: step2. return OK
724      */
725     EXPECT_TRUE(RuntimeConfig::NotifyUserChanged() == OK);
726     CloseStore();
727 
728      /**
729      * @tc.steps: step3. openstore1 open normal sync mode and and openstore2 in dual tuple
730      * @tc.expected: step3. only user2 sync mode is active
731      */
732     OpenStore1(false);
733     OpenStore2();
734 
735     /**
736      * @tc.steps: step4. call NotifyUserChanged
737      * @tc.expected: step4. return OK
738      */
739     EXPECT_TRUE(RuntimeConfig::NotifyUserChanged() == OK);
740     CloseStore();
741 }
742 
743 /**
744  * @tc.name: multi user 005
745  * @tc.desc: test NotifyUserChanged and close db concurrently for rdb
746  * @tc.type: FUNC
747  * @tc.require: AR000GK58G
748  * @tc.author: zhangshijie
749  */
750 HWTEST_F(DistributedDBRelationalMultiUserTest, RdbMultiUser005, TestSize.Level0)
751 {
752     /**
753      * @tc.steps: step1. set SyncActivationCheckCallback and only userId1 can active
754      */
755     RuntimeConfig::SetSyncActivationCheckCallback(g_syncActivationCheckCallback2);
756 
757     /**
758      * @tc.steps: step2. openstore1 in dual tuple sync mode and openstore2 in normal sync mode
759      * @tc.expected: step2. only user2 sync mode is active
760      */
761     OpenStore1(true);
762     OpenStore2(false);
763 
764     /**
765      * @tc.steps: step3. set SyncActivationCheckCallback and only userId2 can active
766      */
767     RuntimeConfig::SetSyncActivationCheckCallback(g_syncActivationCheckCallback1);
768 
769     /**
770      * @tc.steps: step4. call NotifyUserChanged and close db concurrently
771      * @tc.expected: step4. return OK
772      */
__anonc9560f830d02() 773     thread subThread([&]() {
774         EXPECT_TRUE(RuntimeConfig::NotifyUserChanged() == OK);
775     });
776     subThread.detach();
777     EXPECT_EQ(g_mgr1.CloseStore(g_rdbDelegatePtr1), OK);
778     g_rdbDelegatePtr1 = nullptr;
779     CloseStore();
780 }
781 
782 /**
783  * @tc.name: multi user 006
784  * @tc.desc: test NotifyUserChanged and block sync concurrently for rdb
785  * @tc.type: FUNC
786  * @tc.require: AR000GK58G
787  * @tc.author: zhangshijie
788  */
789 HWTEST_F(DistributedDBRelationalMultiUserTest, RdbMultiUser006, TestSize.Level0)
790 {
791     TestSyncWithUserChange(true, false);
792 }
793 
794 /**
795  * @tc.name: multi user 007
796  * @tc.desc: test NotifyUserChanged and non-block sync concurrently for rdb
797  * @tc.type: FUNC
798  * @tc.require: AR000GK58G
799  * @tc.author: zhangshijie
800  */
801 HWTEST_F(DistributedDBRelationalMultiUserTest, RdbMultiUser007, TestSize.Level0)
802 {
803     TestSyncWithUserChange(false, false);
804 }
805 
806 /**
807  * @tc.name: multi user 008
808  * @tc.desc: test NotifyUserChanged and remote query concurrently for rdb
809  * @tc.type: FUNC
810  * @tc.require: AR000GK58G
811  * @tc.author: zhangshijie
812  */
813 HWTEST_F(DistributedDBRelationalMultiUserTest, RdbMultiUser008, TestSize.Level1)
814 {
815     /**
816      * @tc.steps: step1. set SyncActivationCheckCallback and only userId2 can active
817      */
818     RuntimeConfig::SetSyncActivationCheckCallback(g_syncActivationCheckCallback1);
819 
820     /**
821      * @tc.steps: step2. openstore1 in dual tuple sync mode and openstore2 in normal sync mode
822      * @tc.expected: step2. only user2 sync mode is active
823      */
824     OpenStore1(true);
825     OpenStore2(true);
826     PrepareEnvironment(g_tableName, g_storePath1, g_rdbDelegatePtr1);
827 
828     /**
829      * @tc.steps: step3. user1 call remote query
830      * @tc.expected: step3. sync should return NOT_ACTIVE.
831      */
832     std::vector<RelationalVirtualDevice *> remoteDev;
833     remoteDev.push_back(g_deviceB);
834     PrepareVirtualDeviceEnv(g_tableName, g_storePath1, remoteDev);
835     RemoteCondition condition;
836     condition.sql = "SELECT * FROM " + g_tableName;
837     std::shared_ptr<ResultSet> result = std::make_shared<RelationalResultSetImpl>();
838     DBStatus status = g_rdbDelegatePtr1->RemoteQuery(g_deviceB->GetDeviceId(), condition,
839         DBConstant::MAX_TIMEOUT, result);
840     EXPECT_EQ(status, NOT_ACTIVE);
841     EXPECT_EQ(result, nullptr);
842     CloseStore();
843 }
844 
845 /**
846  * @tc.name: multi user 009
847  * @tc.desc: test NotifyUserChanged and remote query concurrently for rdb
848  * @tc.type: FUNC
849  * @tc.require: AR000GK58G
850  * @tc.author: zhangshijie
851  */
852 HWTEST_F(DistributedDBRelationalMultiUserTest, RdbMultiUser009, TestSize.Level0)
853 {
854     TestSyncWithUserChange(false, true);
855 }
856 
857 /**
858  * @tc.name: multi user 010
859  * @tc.desc: test check sync active twice when open store
860  * @tc.type: FUNC
861  * @tc.require: AR000GK58G
862  * @tc.author: zhangqiquan
863  */
864 HWTEST_F(DistributedDBRelationalMultiUserTest, RdbMultiUser010, TestSize.Level1)
865 {
866     uint32_t callCount = 0u;
867     /**
868      * @tc.steps: step1. set SyncActivationCheckCallback and record call count, only first call return not active
869      */
870     RuntimeConfig::SetSyncActivationCheckCallback([&callCount] (const std::string &userId, const std::string &appId,
__anonc9560f830e02(const std::string &userId, const std::string &appId, const std::string &storeId) 871         const std::string &storeId) -> bool {
872         callCount++;
873         return callCount != 1;
874     });
875     /**
876      * @tc.steps: step2. openstore1 in dual tuple sync mode
877      * @tc.expected: step2. it should be activity finally
878      */
879     OpenStore1(true);
880     /**
881      * @tc.steps: step3. prepare environment
882      */
883     PrepareEnvironment(g_tableName, g_storePath1, g_rdbDelegatePtr1);
884     /**
885      * @tc.steps: step4. call sync to DEVICES_B
886      * @tc.expected: step4. should return OK, not NOT_ACTIVE
887      */
888     Query query = Query::Select(g_tableName);
889     EXPECT_EQ(g_rdbDelegatePtr1->Sync({DEVICE_B}, SYNC_MODE_PUSH_ONLY, query, nullptr, true), OK);
890     CloseStore();
891 }