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