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,
__anon3413e1da0202(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,
__anon3413e1da0302(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 
PrepareVirtualDeviceBEnv(const std::string & tableName)134     void PrepareVirtualDeviceBEnv(const std::string &tableName)
135     {
136         std::vector<RelationalVirtualDevice *> remoteDev;
137         remoteDev.push_back(g_deviceB);
138         PrepareVirtualDeviceEnv(tableName, g_storePath1, remoteDev);
139     }
140 
PrepareData(const std::string & tableName,const std::string & dbPath)141     void PrepareData(const std::string &tableName, const std::string &dbPath)
142     {
143         sqlite3 *db = nullptr;
144         EXPECT_EQ(GetDB(db, dbPath), SQLITE_OK);
145         EXPECT_EQ(InsertValue(db, tableName), SQLITE_OK);
146         EXPECT_EQ(sqlite3_close_v2(db), SQLITE_OK);
147     }
148 
OpenStore1(bool syncDualTupleMode=true)149     void OpenStore1(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_mgr1.OpenStore(g_storePath1, STORE_ID_1, option, g_rdbDelegatePtr1);
157         ASSERT_TRUE(g_rdbDelegatePtr1 != nullptr);
158     }
159 
OpenStore2(bool syncDualTupleMode=true)160     void OpenStore2(bool syncDualTupleMode = true)
161     {
162         if (g_observer == nullptr) {
163             g_observer = new (std::nothrow) RelationalStoreObserverUnitTest();
164         }
165         RelationalStoreDelegate::Option option = {g_observer};
166         option.syncDualTupleMode = syncDualTupleMode;
167         g_mgr2.OpenStore(g_storePath2, STORE_ID_2, option, g_rdbDelegatePtr2);
168         ASSERT_TRUE(g_rdbDelegatePtr2 != nullptr);
169     }
170 
CloseStore()171     void CloseStore()
172     {
173         if (g_rdbDelegatePtr1 != nullptr) {
174             ASSERT_EQ(g_mgr1.CloseStore(g_rdbDelegatePtr1), OK);
175             g_rdbDelegatePtr1 = nullptr;
176             LOGD("delete rdb store");
177         }
178         if (g_rdbDelegatePtr2 != nullptr) {
179             ASSERT_EQ(g_mgr2.CloseStore(g_rdbDelegatePtr2), OK);
180             g_rdbDelegatePtr2 = nullptr;
181             LOGD("delete rdb store");
182         }
183     }
184 
PrepareEnvironment(const std::string & tableName,const std::string & dbPath,RelationalStoreDelegate * rdbDelegate)185     void PrepareEnvironment(const std::string &tableName, const std::string &dbPath,
186         RelationalStoreDelegate* rdbDelegate)
187     {
188         sqlite3 *db = nullptr;
189         EXPECT_EQ(GetDB(db, dbPath), SQLITE_OK);
190         EXPECT_EQ(DropTable(db, tableName), SQLITE_OK);
191         EXPECT_EQ(CreateTable(db, tableName), SQLITE_OK);
192         if (rdbDelegate != nullptr) {
193             EXPECT_EQ(rdbDelegate->CreateDistributedTable(tableName), OK);
194         }
195         sqlite3_close(db);
196     }
197 
CheckSyncTest(DBStatus status1,DBStatus status2,std::vector<std::string> & devices)198     void CheckSyncTest(DBStatus status1, DBStatus status2, std::vector<std::string> &devices)
199     {
200         std::map<std::string, std::vector<TableStatus>> statusMap;
201         SyncStatusCallback callBack = [&statusMap](
202             const std::map<std::string, std::vector<TableStatus>> &devicesMap) {
203             statusMap = devicesMap;
204         };
205         Query query = Query::Select(g_tableName);
206         DBStatus status = g_rdbDelegatePtr1->Sync(devices, SYNC_MODE_PUSH_ONLY, query, callBack, true);
207         LOGE("expect status is: %d, actual is %d", status1, status);
208         ASSERT_TRUE(status == status1);
209         if (status == OK) {
210             for (const auto &pair : statusMap) {
211                 for (const auto &tableStatus : pair.second) {
212                     LOGD("dev %s, status %d", pair.first.c_str(), tableStatus.status);
213                     EXPECT_TRUE(tableStatus.status == OK);
214                 }
215             }
216         }
217         statusMap.clear();
218 
219         std::map<std::string, std::vector<TableStatus>> statusMap2;
220         SyncStatusCallback callBack2 = [&statusMap2](
221             const std::map<std::string, std::vector<TableStatus>> &devicesMap) {
222             LOGE("call back devicesMap.size = %d", devicesMap.size());
223             statusMap2 = devicesMap;
224         };
225         status = g_rdbDelegatePtr2->Sync(devices, SYNC_MODE_PUSH_ONLY, query, callBack2, true);
226         LOGE("expect status2 is: %d, actual is %d, statusMap2.size = %d", status2, status, statusMap2.size());
227         ASSERT_TRUE(status == status2);
228         if (status == OK) {
229             for (const auto &pair : statusMap2) {
230                 for (const auto &tableStatus : pair.second) {
231                     LOGE("*********** rdb dev %s, status %d", pair.first.c_str(), tableStatus.status);
232                     EXPECT_TRUE(tableStatus.status == OK);
233                 }
234             }
235         }
236         statusMap.clear();
237     }
238 
239     int g_currentStatus = 0;
240     const AutoLaunchNotifier g_notifier = [](const std::string &userId,
__anon3413e1da0602(const std::string &userId, const std::string &appId, const std::string &storeId, AutoLaunchStatus status) 241         const std::string &appId, const std::string &storeId, AutoLaunchStatus status) {
242             LOGD("notifier status = %d", status);
243             g_currentStatus = static_cast<int>(status);
244         };
245 
__anon3413e1da0702(const std::string &identifier, AutoLaunchParam &param) 246     const AutoLaunchRequestCallback g_callback = [](const std::string &identifier, AutoLaunchParam &param) {
247         if (g_identifier != identifier) {
248             LOGD("g_identifier(%s) != identifier(%s)", g_identifier.c_str(), identifier.c_str());
249             return false;
250         }
251         param.path    = g_testDir + "/test2.db";
252         param.appId   = APP_ID;
253         param.storeId = STORE_ID;
254         CipherPassword passwd;
255         param.option = {true, false, CipherType::DEFAULT, passwd, "", false, g_testDir, nullptr,
256             0, nullptr};
257         param.notifier = g_notifier;
258         param.option.syncDualTupleMode = true;
259         return true;
260     };
261 
DoRemoteQuery()262     void DoRemoteQuery()
263     {
264         RemoteCondition condition;
265         condition.sql = "SELECT * FROM " + g_tableName;
266         std::shared_ptr<ResultSet> result = std::make_shared<RelationalResultSetImpl>();
267         EXPECT_EQ(g_rdbDelegatePtr1->RemoteQuery(g_deviceB->GetDeviceId(), condition,
268             DBConstant::MAX_TIMEOUT, result), USER_CHANGED);
269         EXPECT_EQ(result, nullptr);
270         g_communicatorAggregator->RegOnDispatch(nullptr);
271         CloseStore();
272     }
273 
CheckSyncResult(bool wait,bool isRemoteQuery)274     void CheckSyncResult(bool wait, bool isRemoteQuery)
275     {
276         std::mutex syncLock_{};
277         std::condition_variable syncCondVar_{};
278         std::map<std::string, std::vector<TableStatus>> statusMap;
279         SyncStatusCallback callBack = [&statusMap, &syncLock_, &syncCondVar_, wait](
280             const std::map<std::string, std::vector<TableStatus>> &devicesMap) {
281             statusMap = devicesMap;
282             if (!wait) {
283                 std::unique_lock<std::mutex> innerlock(syncLock_);
284                 syncCondVar_.notify_one();
285             }
286         };
287         Query query = Query::Select(g_tableName);
288         std::vector<std::string> devices;
289         devices.push_back(g_deviceB->GetDeviceId());
290         std::vector<RelationalVirtualDevice *> remoteDev;
291         remoteDev.push_back(g_deviceB);
292         PrepareVirtualDeviceEnv(g_tableName, g_storePath1, remoteDev);
293 
294         DBStatus status = DB_ERROR;
295         if (isRemoteQuery) {
296             DoRemoteQuery();
297             return;
298         }
299 
300         status = g_rdbDelegatePtr1->Sync(devices, SYNC_MODE_PUSH_ONLY, query, callBack, wait);
301         EXPECT_EQ(status, OK);
302 
303         if (!wait) {
304             std::unique_lock<std::mutex> lock(syncLock_);
305             syncCondVar_.wait(lock, [status, &statusMap]() {
306                 if (status != OK) {
307                     return true;
308                 }
309                 return !statusMap.empty();
310             });
311         }
312 
313         g_communicatorAggregator->RegOnDispatch(nullptr);
314         EXPECT_EQ(statusMap.size(), devices.size());
315         for (const auto &pair : statusMap) {
316             for (const auto &tableStatus : pair.second) {
317                 EXPECT_TRUE(tableStatus.status == USER_CHANGED);
318             }
319         }
320         CloseStore();
321     }
322 
TestSyncWithUserChange(bool wait,bool isRemoteQuery)323     void TestSyncWithUserChange(bool wait, bool isRemoteQuery)
324     {
325         /**
326          * @tc.steps: step1. set SyncActivationCheckCallback and only userId1 can active
327          */
328         RuntimeConfig::SetSyncActivationCheckCallback(g_syncActivationCheckCallback2);
329         /**
330          * @tc.steps: step2. openstore1 in dual tuple sync mode and openstore2 in normal sync mode
331          * @tc.expected: step2. only user2 sync mode is active
332          */
333         OpenStore1(true);
334         OpenStore2(true);
335 
336         /**
337          * @tc.steps: step3. prepare environment
338          */
339         PrepareEnvironment(g_tableName, g_storePath1, g_rdbDelegatePtr1);
340         PrepareEnvironment(g_tableName, g_storePath2, g_rdbDelegatePtr2);
341 
342         /**
343          * @tc.steps: step4. prepare data
344          */
345         PrepareData(g_tableName, g_storePath1);
346         PrepareData(g_tableName, g_storePath2);
347 
348         /**
349          * @tc.steps: step5. set SyncActivationCheckCallback and only userId2 can active
350          */
351         RuntimeConfig::SetSyncActivationCheckCallback(g_syncActivationCheckCallback1);
352 
353         /**
354          * @tc.steps: step6. call NotifyUserChanged and block sync db concurrently
355          * @tc.expected: step6. return OK
356          */
357         CipherPassword passwd;
358         bool startSync = false;
359         std::condition_variable cv;
360         thread subThread([&]() {
361             std::mutex notifyLock;
362             std::unique_lock<std::mutex> lck(notifyLock);
363             cv.wait(lck, [&startSync]() { return startSync; });
364             EXPECT_TRUE(RuntimeConfig::NotifyUserChanged() == OK);
365         });
366         subThread.detach();
367         g_communicatorAggregator->RegOnDispatch([&](const std::string&, Message *inMsg) {
368             if (!startSync) {
369                 startSync = true;
370                 cv.notify_all();
371                 std::this_thread::sleep_for(std::chrono::milliseconds(WAIT_TIME)); // wait for notify user change
372             }
373         });
374 
375         /**
376          * @tc.steps: step7. deviceA call sync and wait
377          * @tc.expected: step7. sync should return OK.
378          */
379         CheckSyncResult(wait, isRemoteQuery);
380     }
381 
PrepareSelect(sqlite3 * db,sqlite3_stmt * & statement,const std::string & table)382     int PrepareSelect(sqlite3 *db, sqlite3_stmt *&statement, const std::string &table)
383     {
384         std::string dis_tableName = RelationalStoreManager::GetDistributedTableName(DEVICE_B, table);
385         const std::string sql = "SELECT * FROM " + dis_tableName;
386         LOGD("exec sql: %s", sql.c_str());
387         return sqlite3_prepare_v2(db, sql.c_str(), -1, &statement, nullptr);
388     }
389 
CheckDataInRealDevice()390     void CheckDataInRealDevice()
391     {
392         sqlite3 *db = nullptr;
393         EXPECT_EQ(GetDB(db, g_storePath2), SQLITE_OK);
394 
395         sqlite3_stmt *statement = nullptr;
396         EXPECT_EQ(PrepareSelect(db, statement, g_tableName), SQLITE_OK);
397         int rowCount = 0;
398         while (true) {
399             int rc = sqlite3_step(statement);
400             if (rc != SQLITE_ROW) {
401                 LOGD("GetSyncData Exist by code[%d]", rc);
402                 break;
403             }
404             int columnCount = sqlite3_column_count(statement);
405             EXPECT_EQ(columnCount, 2); // 2: result index
406             rowCount++;
407         }
408         EXPECT_EQ(rowCount, 1);
409         sqlite3_finalize(statement);
410         EXPECT_EQ(sqlite3_close_v2(db), SQLITE_OK);
411     }
412 
RegOnDispatchWithoutDataPacket(std::atomic<int> & messageCount,bool checkVirtual=true)413     void RegOnDispatchWithoutDataPacket(std::atomic<int> &messageCount, bool checkVirtual = true)
414     {
415         g_communicatorAggregator->RegOnDispatch([&messageCount, checkVirtual](const std::string &dev, Message *msg) {
416             if (msg->GetMessageId() != TIME_SYNC_MESSAGE && msg->GetMessageId() != ABILITY_SYNC_MESSAGE) {
417                 return;
418             }
419             if (((checkVirtual && dev != DEVICE_B) || (!checkVirtual && dev != "real_device")) ||
420                 msg->GetMessageType() != TYPE_REQUEST) {
421                 return;
422             }
423             messageCount++;
424         });
425     }
426 }
427 
428 class DistributedDBRelationalMultiUserTest : public testing::Test {
429 public:
430     static void SetUpTestCase(void);
431     static void TearDownTestCase(void);
432     void SetUp();
433     void TearDown();
434 };
435 
SetUpTestCase(void)436 void DistributedDBRelationalMultiUserTest::SetUpTestCase(void)
437 {
438     /**
439     * @tc.setup: Init datadir and Virtual Communicator.
440     */
441     DistributedDBToolsUnitTest::TestDirInit(g_testDir);
442     g_storePath1 = g_testDir + "/test1.db";
443     g_storePath2 = g_testDir + "/test2.db";
444     sqlite3 *db1 = nullptr;
445     ASSERT_EQ(GetDB(db1, g_storePath1), SQLITE_OK);
446     sqlite3_close(db1);
447 
448     sqlite3 *db2 = nullptr;
449     ASSERT_EQ(GetDB(db2, g_storePath2), SQLITE_OK);
450     sqlite3_close(db2);
451 
452     g_communicatorAggregator = new (std::nothrow) VirtualCommunicatorAggregator();
453     ASSERT_TRUE(g_communicatorAggregator != nullptr);
454     RuntimeContext::GetInstance()->SetCommunicatorAggregator(g_communicatorAggregator);
455 }
456 
TearDownTestCase(void)457 void DistributedDBRelationalMultiUserTest::TearDownTestCase(void)
458 {
459     /**
460      * @tc.teardown: Release virtual Communicator and clear data dir.
461      */
462     if (DistributedDBToolsUnitTest::RemoveTestDbFiles(g_testDir) != 0) {
463         LOGE("rm test db files error!");
464     }
465     RuntimeContext::GetInstance()->SetCommunicatorAggregator(nullptr);
466 }
467 
SetUp(void)468 void DistributedDBRelationalMultiUserTest::SetUp(void)
469 {
470     DistributedDBToolsUnitTest::PrintTestCaseInfo();
471     /**
472      * @tc.setup: create virtual device B
473      */
474     g_deviceB = new (std::nothrow) RelationalVirtualDevice(DEVICE_B);
475     ASSERT_TRUE(g_deviceB != nullptr);
476     VirtualRelationalVerSyncDBInterface *syncInterfaceB = new (std::nothrow) VirtualRelationalVerSyncDBInterface();
477     ASSERT_TRUE(syncInterfaceB != nullptr);
478     ASSERT_EQ(g_deviceB->Initialize(g_communicatorAggregator, syncInterfaceB), E_OK);
479     g_deviceC = new (std::nothrow) RelationalVirtualDevice(DEVICE_C);
480     ASSERT_TRUE(g_deviceC != nullptr);
481     VirtualRelationalVerSyncDBInterface *syncInterfaceC = new (std::nothrow) VirtualRelationalVerSyncDBInterface();
482     ASSERT_TRUE(syncInterfaceC != nullptr);
483     ASSERT_EQ(g_deviceC->Initialize(g_communicatorAggregator, syncInterfaceC), E_OK);
484 }
485 
TearDown(void)486 void DistributedDBRelationalMultiUserTest::TearDown(void)
487 {
488     /**
489      * @tc.teardown: Release device A, B, C
490      */
491     if (g_deviceB != nullptr) {
492         delete g_deviceB;
493         g_deviceB = nullptr;
494     }
495     if (g_deviceC != nullptr) {
496         delete g_deviceC;
497         g_deviceC = nullptr;
498     }
499     SyncActivationCheckCallback callback = nullptr;
500     RuntimeConfig::SetSyncActivationCheckCallback(callback);
501     RuntimeContext::GetInstance()->ClearAllDeviceTimeInfo();
502 }
503 
504 /**
505  * @tc.name: multi user 001
506  * @tc.desc: Test multi user change for rdb
507  * @tc.type: FUNC
508  * @tc.require: AR000GK58G
509  * @tc.author: zhangshijie
510  */
511 HWTEST_F(DistributedDBRelationalMultiUserTest, RdbMultiUser001, TestSize.Level0)
512 {
513     /**
514      * @tc.steps: step1. set SyncActivationCheckCallback and only userId2 can active
515      */
516     RuntimeConfig::SetSyncActivationCheckCallback(g_syncActivationCheckCallback1);
517 
518     /**
519      * @tc.steps: step2. openstore1 and openstore2
520      * @tc.expected: step2. only user2 sync mode is active
521      */
522     OpenStore1();
523     OpenStore2();
524 
525     /**
526      * @tc.steps: step3. prepare environment
527      */
528     PrepareEnvironment(g_tableName, g_storePath1, g_rdbDelegatePtr1);
529     PrepareEnvironment(g_tableName, g_storePath2, g_rdbDelegatePtr2);
530 
531     /**
532      * @tc.steps: step4. prepare data
533      */
534     PrepareData(g_tableName, g_storePath1);
535     PrepareData(g_tableName, g_storePath2);
536 
537     /**
538      * @tc.steps: step5. g_rdbDelegatePtr1 and g_rdbDelegatePtr2 call sync
539      * @tc.expected: step5. g_rdbDelegatePtr2 call success
540      */
541     std::vector<std::string> devices;
542     devices.push_back(g_deviceB->GetDeviceId());
543     std::vector<RelationalVirtualDevice *> remoteDev;
544     remoteDev.push_back(g_deviceB);
545     remoteDev.push_back(g_deviceC);
546     PrepareVirtualDeviceEnv(g_tableName, g_storePath1, remoteDev);
547     CheckSyncTest(NOT_ACTIVE, OK, devices);
548 
549     /**
550      * @tc.expected: step6. onComplete should be called, DeviceB have {k1,v1}
551      */
552     std::vector<VirtualRowData> targetData;
553     g_deviceB->GetAllSyncData(g_tableName, targetData);
554     EXPECT_EQ(targetData.size(), 1u);
555 
556     /**
557      * @tc.expected: step7. user change
558      */
559     RuntimeConfig::SetSyncActivationCheckCallback(g_syncActivationCheckCallback2);
560     RuntimeConfig::NotifyUserChanged();
561     /**
562      * @tc.steps: step8. g_kvDelegatePtr1 and g_kvDelegatePtr2 call sync
563      * @tc.expected: step8. g_kvDelegatePtr1 call success
564      */
565     devices.clear();
566     devices.push_back(g_deviceC->GetDeviceId());
567     CheckSyncTest(OK, NOT_ACTIVE, devices);
568     /**
569      * @tc.expected: step9. onComplete should be called, DeviceC have {k1,v1}
570      */
571     targetData.clear();
572     g_deviceC->GetAllSyncData(g_tableName, targetData);
573     EXPECT_EQ(targetData.size(), 1u);
574     CloseStore();
575 }
576 
577 /**
578  * @tc.name: multi user 002
579  * @tc.desc: Test multi user not change for rdb
580  * @tc.type: FUNC
581  * @tc.require: AR000GK58G
582  * @tc.author: zhangshijie
583  */
584 HWTEST_F(DistributedDBRelationalMultiUserTest, RdbMultiUser002, TestSize.Level0)
585 {
586     /**
587      * @tc.steps: step1. set SyncActivationCheckCallback and only userId2 can active
588      */
589     RuntimeConfig::SetSyncActivationCheckCallback(g_syncActivationCheckCallback1);
590     /**
591      * @tc.steps: step2. openstore1 and openstore2
592      * @tc.expected: step2. only user2 sync mode is active
593      */
594     OpenStore1();
595     OpenStore2();
596 
597     /**
598      * @tc.steps: step3. prepare environment
599      */
600     PrepareEnvironment(g_tableName, g_storePath1, g_rdbDelegatePtr1);
601     PrepareEnvironment(g_tableName, g_storePath2, g_rdbDelegatePtr2);
602 
603     /**
604      * @tc.steps: step4. prepare data
605      */
606     PrepareData(g_tableName, g_storePath1);
607     PrepareData(g_tableName, g_storePath2);
608 
609     /**
610      * @tc.steps: step4. GetRelationalStoreIdentifier success when userId is invalid
611      */
612     std::string userId;
613     EXPECT_TRUE(g_mgr1.GetRelationalStoreIdentifier(userId, APP_ID, USER_ID_2, true) != "");
614     userId.resize(130);
615     EXPECT_TRUE(g_mgr1.GetRelationalStoreIdentifier(userId, APP_ID, USER_ID_2, true) != "");
616 
617     /**
618      * @tc.steps: step5. g_rdbDelegatePtr1 and g_rdbDelegatePtr2 call sync
619      * @tc.expected: step5. g_rdbDelegatePtr2 call success
620      */
621     std::vector<std::string> devices;
622     devices.push_back(g_deviceB->GetDeviceId());
623     std::vector<RelationalVirtualDevice *> remoteDev;
624     remoteDev.push_back(g_deviceB);
625     remoteDev.push_back(g_deviceC);
626     PrepareVirtualDeviceEnv(g_tableName, g_storePath1, remoteDev);
627     CheckSyncTest(NOT_ACTIVE, OK, devices);
628 
629     /**
630      * @tc.expected: step6. onComplete should be called, DeviceB have {k1,v1}
631      */
632     std::vector<VirtualRowData> targetData;
633     g_deviceB->GetAllSyncData(g_tableName, targetData);
634     EXPECT_EQ(targetData.size(), 1u);
635 
636     /**
637      * @tc.expected: step7. user not change
638      */
639     RuntimeConfig::NotifyUserChanged();
640 
641     /**
642      * @tc.steps: step8. g_kvDelegatePtr1 and g_kvDelegatePtr2 call sync
643      * @tc.expected: step8. g_kvDelegatePtr1 call success
644      */
645     CheckSyncTest(NOT_ACTIVE, OK, devices);
646 
647     /**
648      * @tc.expected: step9. onComplete should be called, DeviceC have {k1,v1}
649      */
650     targetData.clear();
651     g_deviceB->GetAllSyncData(g_tableName, targetData);
652     EXPECT_EQ(targetData.size(), 1u);
653     CloseStore();
654 }
655 
656 /**
657  * @tc.name: multi user 003
658  * @tc.desc: enhancement callback return true in multiuser mode for rdb
659  * @tc.type: FUNC
660  * @tc.require: AR000GK58G
661  * @tc.author: zhangshijie
662  */
663 HWTEST_F(DistributedDBRelationalMultiUserTest, RdbMultiUser003, TestSize.Level3)
664 {
665     /**
666      * @tc.steps: step1. prepare environment
667      */
668     OpenStore1();
669     OpenStore2();
670     PrepareEnvironment(g_tableName, g_storePath1, g_rdbDelegatePtr1);
671     PrepareEnvironment(g_tableName, g_storePath2, g_rdbDelegatePtr2);
672     CloseStore();
673 
674     /**
675      * @tc.steps: step2. set SyncActivationCheckCallback and only userId2 can active
676      */
677     RuntimeConfig::SetSyncActivationCheckCallback(g_syncActivationCheckCallback1);
678 
679     /**
680      * @tc.steps: step3. SetAutoLaunchRequestCallback
681      * @tc.expected: step3. success.
682      */
683     g_mgr1.SetAutoLaunchRequestCallback(g_callback);
684 
685     /**
686      * @tc.steps: step4. RunCommunicatorLackCallback
687      * @tc.expected: step4. success.
688      */
689     g_identifier = g_mgr1.GetRelationalStoreIdentifier(USER_ID_2, APP_ID, STORE_ID, true);
690     EXPECT_TRUE(g_identifier == g_mgr1.GetRelationalStoreIdentifier(USER_ID_1, APP_ID, STORE_ID, true));
691     std::vector<uint8_t> label(g_identifier.begin(), g_identifier.end());
692     g_communicatorAggregator->SetCurrentUserId(USER_ID_2);
693     g_communicatorAggregator->RunCommunicatorLackCallback(label);
694     std::this_thread::sleep_for(std::chrono::milliseconds(WAIT_TIME));
695 
696     /**
697      * @tc.steps: step5. device B put one data
698      * @tc.expected: step5. success.
699      */
700     VirtualRowData virtualRowData;
701     DataValue d1;
702     d1 = (int64_t)1;
703     virtualRowData.objectData.PutDataValue("id", d1);
704     DataValue d2;
705     d2.SetText("hello");
706     virtualRowData.objectData.PutDataValue("name", d2);
707     virtualRowData.logInfo.timestamp = 1;
708     g_deviceB->PutData(g_tableName, {virtualRowData});
709 
710     std::vector<RelationalVirtualDevice *> remoteDev;
711     remoteDev.push_back(g_deviceB);
712     PrepareVirtualDeviceEnv(g_tableName, g_storePath1, remoteDev);
713 
714     /**
715      * @tc.steps: step6. device B push sync to A
716      * @tc.expected: step6. success.
717      */
718     Query query = Query::Select(g_tableName);
719     EXPECT_EQ(g_deviceB->GenericVirtualDevice::Sync(SYNC_MODE_PUSH_ONLY, query, true), OK);
720 
721     /**
722      * @tc.steps: step7. deviceA have {k1,v1}
723      * @tc.expected: step7. success.
724      */
725     CheckDataInRealDevice();
726 
727     RuntimeConfig::SetAutoLaunchRequestCallback(nullptr, DBType::DB_RELATION);
728     RuntimeConfig::ReleaseAutoLaunch(USER_ID_2, APP_ID, STORE_ID, DBType::DB_RELATION);
729     RuntimeConfig::ReleaseAutoLaunch(USER_ID_2, APP_ID, STORE_ID, DBType::DB_RELATION);
730     g_currentStatus = 0;
731     CloseStore();
732 }
733 
734 /**
735  * @tc.name: multi user 004
736  * @tc.desc: test NotifyUserChanged func when all db in normal sync mode for rdb
737  * @tc.type: FUNC
738  * @tc.require: AR000GK58G
739  * @tc.author: zhangshijie
740  */
741 HWTEST_F(DistributedDBRelationalMultiUserTest, RdbMultiUser004, TestSize.Level0)
742 {
743     /**
744      * @tc.steps: step1. openstore1 and openstore2 in normal sync mode
745      * @tc.expected: step1. only user2 sync mode is active
746      */
747     OpenStore1(false);
748     OpenStore2(false);
749 
750     /**
751      * @tc.steps: step2. call NotifyUserChanged
752      * @tc.expected: step2. return OK
753      */
754     EXPECT_TRUE(RuntimeConfig::NotifyUserChanged() == OK);
755     CloseStore();
756 
757      /**
758      * @tc.steps: step3. openstore1 open normal sync mode and and openstore2 in dual tuple
759      * @tc.expected: step3. only user2 sync mode is active
760      */
761     OpenStore1(false);
762     OpenStore2();
763 
764     /**
765      * @tc.steps: step4. call NotifyUserChanged
766      * @tc.expected: step4. return OK
767      */
768     EXPECT_TRUE(RuntimeConfig::NotifyUserChanged() == OK);
769     CloseStore();
770 }
771 
772 /**
773  * @tc.name: multi user 005
774  * @tc.desc: test NotifyUserChanged and close db concurrently for rdb
775  * @tc.type: FUNC
776  * @tc.require: AR000GK58G
777  * @tc.author: zhangshijie
778  */
779 HWTEST_F(DistributedDBRelationalMultiUserTest, RdbMultiUser005, TestSize.Level0)
780 {
781     /**
782      * @tc.steps: step1. set SyncActivationCheckCallback and only userId1 can active
783      */
784     RuntimeConfig::SetSyncActivationCheckCallback(g_syncActivationCheckCallback2);
785 
786     /**
787      * @tc.steps: step2. openstore1 in dual tuple sync mode and openstore2 in normal sync mode
788      * @tc.expected: step2. only user2 sync mode is active
789      */
790     OpenStore1(true);
791     OpenStore2(false);
792 
793     /**
794      * @tc.steps: step3. set SyncActivationCheckCallback and only userId2 can active
795      */
796     RuntimeConfig::SetSyncActivationCheckCallback(g_syncActivationCheckCallback1);
797 
798     /**
799      * @tc.steps: step4. call NotifyUserChanged and close db concurrently
800      * @tc.expected: step4. return OK
801      */
__anon3413e1da0e02() 802     thread subThread([&]() {
803         EXPECT_TRUE(RuntimeConfig::NotifyUserChanged() == OK);
804     });
805     subThread.detach();
806     EXPECT_EQ(g_mgr1.CloseStore(g_rdbDelegatePtr1), OK);
807     g_rdbDelegatePtr1 = nullptr;
808     CloseStore();
809 }
810 
811 /**
812  * @tc.name: multi user 006
813  * @tc.desc: test NotifyUserChanged and block sync concurrently for rdb
814  * @tc.type: FUNC
815  * @tc.require: AR000GK58G
816  * @tc.author: zhangshijie
817  */
818 HWTEST_F(DistributedDBRelationalMultiUserTest, RdbMultiUser006, TestSize.Level0)
819 {
820     TestSyncWithUserChange(true, false);
821 }
822 
823 /**
824  * @tc.name: multi user 007
825  * @tc.desc: test NotifyUserChanged and non-block sync concurrently for rdb
826  * @tc.type: FUNC
827  * @tc.require: AR000GK58G
828  * @tc.author: zhangshijie
829  */
830 HWTEST_F(DistributedDBRelationalMultiUserTest, RdbMultiUser007, TestSize.Level0)
831 {
832     TestSyncWithUserChange(false, false);
833 }
834 
835 /**
836  * @tc.name: multi user 008
837  * @tc.desc: test NotifyUserChanged and remote query concurrently for rdb
838  * @tc.type: FUNC
839  * @tc.require: AR000GK58G
840  * @tc.author: zhangshijie
841  */
842 HWTEST_F(DistributedDBRelationalMultiUserTest, RdbMultiUser008, TestSize.Level1)
843 {
844     /**
845      * @tc.steps: step1. set SyncActivationCheckCallback and only userId2 can active
846      */
847     RuntimeConfig::SetSyncActivationCheckCallback(g_syncActivationCheckCallback1);
848 
849     /**
850      * @tc.steps: step2. openstore1 in dual tuple sync mode and openstore2 in normal sync mode
851      * @tc.expected: step2. only user2 sync mode is active
852      */
853     OpenStore1(true);
854     OpenStore2(true);
855     PrepareEnvironment(g_tableName, g_storePath1, g_rdbDelegatePtr1);
856 
857     /**
858      * @tc.steps: step3. user1 call remote query
859      * @tc.expected: step3. sync should return NOT_ACTIVE.
860      */
861     std::vector<RelationalVirtualDevice *> remoteDev;
862     remoteDev.push_back(g_deviceB);
863     PrepareVirtualDeviceEnv(g_tableName, g_storePath1, remoteDev);
864     RemoteCondition condition;
865     condition.sql = "SELECT * FROM " + g_tableName;
866     std::shared_ptr<ResultSet> result = std::make_shared<RelationalResultSetImpl>();
867     DBStatus status = g_rdbDelegatePtr1->RemoteQuery(g_deviceB->GetDeviceId(), condition,
868         DBConstant::MAX_TIMEOUT, result);
869     EXPECT_EQ(status, NOT_ACTIVE);
870     EXPECT_EQ(result, nullptr);
871     CloseStore();
872 }
873 
874 /**
875  * @tc.name: multi user 009
876  * @tc.desc: test user change and remote query concurrently for rdb
877  * @tc.type: FUNC
878  * @tc.require: AR000GK58G
879  * @tc.author: zhangshijie
880  */
881 HWTEST_F(DistributedDBRelationalMultiUserTest, RdbMultiUser009, TestSize.Level0)
882 {
883     TestSyncWithUserChange(false, true);
884 }
885 
886 /**
887  * @tc.name: multi user 010
888  * @tc.desc: test check sync active twice when open store
889  * @tc.type: FUNC
890  * @tc.require: AR000GK58G
891  * @tc.author: zhangqiquan
892  */
893 HWTEST_F(DistributedDBRelationalMultiUserTest, RdbMultiUser010, TestSize.Level1)
894 {
895     uint32_t callCount = 0u;
896     /**
897      * @tc.steps: step1. set SyncActivationCheckCallback and record call count, only first call return not active
898      */
899     RuntimeConfig::SetSyncActivationCheckCallback([&callCount] (const std::string &userId, const std::string &appId,
__anon3413e1da0f02(const std::string &userId, const std::string &appId, const std::string &storeId) 900         const std::string &storeId) -> bool {
901         callCount++;
902         return callCount != 1;
903     });
904     /**
905      * @tc.steps: step2. openstore1 in dual tuple sync mode
906      * @tc.expected: step2. it should be activated finally
907      */
908     OpenStore1(true);
909     /**
910      * @tc.steps: step3. prepare environment
911      */
912     PrepareEnvironment(g_tableName, g_storePath1, g_rdbDelegatePtr1);
913     /**
914      * @tc.steps: step4. call sync to DEVICES_B
915      * @tc.expected: step4. should return OK, not NOT_ACTIVE
916      */
917     Query query = Query::Select(g_tableName);
918     SyncStatusCallback callback = nullptr;
919     EXPECT_EQ(g_rdbDelegatePtr1->Sync({DEVICE_B}, SYNC_MODE_PUSH_ONLY, query, callback, true), OK);
920     CloseStore();
921 }
922 
923 /**
924  * @tc.name: multi user 011
925  * @tc.desc: test use different option to open store for rdb
926  * @tc.type: FUNC
927  * @tc.require: AR000GK58G
928  * @tc.author: zhangshijie
929  */
930 HWTEST_F(DistributedDBRelationalMultiUserTest, RdbMultiUser011, TestSize.Level1)
931 {
932     for (int i = 0; i < 2; i++) {
933         bool syncDualTupleMode = i / 2;
934         OpenStore1(syncDualTupleMode);
935         RelationalStoreDelegate::Option option = { g_observer };
936         option.syncDualTupleMode = !syncDualTupleMode;
937         RelationalStoreDelegate *rdbDeletegatePtr = nullptr;
938         EXPECT_EQ(g_mgr1.OpenStore(g_storePath1, STORE_ID_1, option, rdbDeletegatePtr), MODE_MISMATCH);
939         EXPECT_EQ(rdbDeletegatePtr, nullptr);
940         CloseStore();
941     }
942 }
943 
944 /**
945  * @tc.name: multi user 012
946  * @tc.desc: test dont check sync active when open store with normal store
947  * @tc.type: FUNC
948  * @tc.require: AR000GK58G
949  * @tc.author: zhangqiquan
950  */
951 HWTEST_F(DistributedDBRelationalMultiUserTest, RdbMultiUser012, TestSize.Level1)
952 {
953     uint32_t callCount = 0u;
954     /**
955      * @tc.steps: step1. set SyncActivationCheckCallback and record call count
956      */
957     RuntimeConfig::SetSyncActivationCheckCallback([&callCount] (const std::string &userId, const std::string &appId,
__anon3413e1da1002(const std::string &userId, const std::string &appId, const std::string &storeId) 958         const std::string &storeId) -> bool {
959         callCount++;
960         return true;
961     });
962     /**
963      * @tc.steps: step2. openStore in no dual tuple sync mode
964      * @tc.expected: step2. it should be activated finally, and callCount should be zero
965      */
966     OpenStore1(false);
967     EXPECT_EQ(callCount, 0u);
968     CloseStore();
969 }
970 
971 /**
972  * @tc.name: multi user 013
973  * @tc.desc: test dont check sync active when open store with normal store
974  * @tc.type: FUNC
975  * @tc.require: AR000GK58G
976  * @tc.author: zhangqiquan
977  */
978 HWTEST_F(DistributedDBRelationalMultiUserTest, RdbMultiUser013, TestSize.Level1)
979 {
980     uint32_t callCount = 0u;
981     /**
982      * @tc.steps: step1. set SyncActivationCheckCallback and record call count
983      */
984     RuntimeConfig::SetSyncActivationCheckCallback([&callCount] (const std::string &userId, const std::string &appId,
__anon3413e1da1102(const std::string &userId, const std::string &appId, const std::string &storeId) 985         const std::string &storeId) -> bool {
986         callCount++;
987         return true;
988     });
989     /**
990      * @tc.steps: step2. openStore in dual tuple sync mode
991      * @tc.expected: step2. it should not be activated finally, and callCount should be 2
992      */
993     OpenStore1(true);
994     EXPECT_EQ(callCount, 2u);
995     callCount = 0u;
996     EXPECT_EQ(g_rdbDelegatePtr1->RemoveDeviceData("DEVICE"), OK);
997     EXPECT_EQ(callCount, 0u);
998     CloseStore();
999 }
1000 
1001 /**
1002  * @tc.name: multi user 014
1003  * @tc.desc: test remote query with multi user
1004  * @tc.type: FUNC
1005  * @tc.require:
1006  * @tc.author: zhangqiquan
1007  */
1008 HWTEST_F(DistributedDBRelationalMultiUserTest, RdbMultiUser014, TestSize.Level0)
1009 {
1010     /**
1011      * @tc.steps: step1. set SyncActivationCheckCallback and only userId2 can active
1012      */
1013     RuntimeConfig::SetSyncActivationCheckCallback(g_syncActivationCheckCallback2);
1014     /**
1015      * @tc.steps: step2. openStore in dual tuple sync mode and call remote query
1016      */
1017     OpenStore1(true);
1018     PrepareEnvironment(g_tableName, g_storePath1, g_rdbDelegatePtr1);
1019     /**
1020      * @tc.steps: step3. disable communicator and call remote query
1021      * @tc.expected: step3. failed by communicator
1022      */
1023     g_communicatorAggregator->DisableCommunicator();
1024     RemoteCondition condition;
1025     condition.sql = "SELECT * FROM RdbMultiUser014";
1026     std::shared_ptr<ResultSet> resultSet;
1027     DBStatus status = g_rdbDelegatePtr1->RemoteQuery("DEVICE", condition, DBConstant::MAX_TIMEOUT, resultSet);
1028     EXPECT_EQ(status, COMM_FAILURE);
1029     EXPECT_EQ(resultSet, nullptr);
1030     CloseStore();
1031     g_communicatorAggregator->EnableCommunicator();
1032     SyncActivationCheckCallbackV2 callbackV2 = nullptr;
1033     RuntimeConfig::SetSyncActivationCheckCallback(callbackV2);
1034     OS::RemoveFile(g_storePath1);
1035     PrepareEnvironment(g_tableName, g_storePath1, g_rdbDelegatePtr1);
1036 }
1037 
1038 /**
1039  * @tc.name: RDBSyncOpt001
1040  * @tc.desc: check time sync and ability sync once
1041  * @tc.type: FUNC
1042  * @tc.require:
1043  * @tc.author: zhangqiquan
1044  */
1045 HWTEST_F(DistributedDBRelationalMultiUserTest, RDBSyncOpt001, TestSize.Level0)
1046 {
1047     /**
1048      * @tc.steps: step1. record packet which send to B
1049      */
1050     std::atomic<int> messageCount = 0;
1051     RegOnDispatchWithoutDataPacket(messageCount);
1052     /**
1053      * @tc.steps: step2. openStore in dual tuple sync mode and call remote query
1054      */
1055     OpenStore1(true);
1056     PrepareEnvironment(g_tableName, g_storePath1, g_rdbDelegatePtr1);
1057     PrepareVirtualDeviceBEnv(g_tableName);
1058     /**
1059      * @tc.steps: step3. call sync to DEVICES_B
1060      * @tc.expected: step3. should return OK
1061      */
1062     Query query = Query::Select(g_tableName);
1063     SyncStatusCallback callback = nullptr;
1064     EXPECT_EQ(g_rdbDelegatePtr1->Sync({DEVICE_B}, SYNC_MODE_PUSH_ONLY, query, callback, true), OK);
1065     CloseStore();
1066     EXPECT_EQ(messageCount, 2); // 2 contain time sync request packet and ability sync packet
1067     /**
1068      * @tc.steps: step4. re open store and sync again
1069      * @tc.expected: step4. reopen OK and sync success, no negotiation packet
1070      */
1071     OpenStore1(true);
1072     messageCount = 0;
1073     EXPECT_EQ(g_rdbDelegatePtr1->Sync({DEVICE_B}, SYNC_MODE_PUSH_ONLY, query, callback, true), OK);
1074     EXPECT_EQ(messageCount, 0);
1075     CloseStore();
1076     OS::RemoveFile(g_storePath1);
1077     PrepareEnvironment(g_tableName, g_storePath1, g_rdbDelegatePtr1);
1078     g_communicatorAggregator->RegOnDispatch(nullptr);
1079 }
1080 
1081 /**
1082  * @tc.name: RDBSyncOpt002
1083  * @tc.desc: check re ability sync after create distributed table
1084  * @tc.type: FUNC
1085  * @tc.require:
1086  * @tc.author: zhangqiquan
1087  */
1088 HWTEST_F(DistributedDBRelationalMultiUserTest, RDBSyncOpt002, TestSize.Level0)
1089 {
1090     /**
1091      * @tc.steps: step1. record packet which send to B
1092      */
1093     std::atomic<int> messageCount = 0;
1094     RegOnDispatchWithoutDataPacket(messageCount);
1095     /**
1096      * @tc.steps: step2. openStore in dual tuple sync mode and call remote query
1097      */
1098     OpenStore1(true);
1099     PrepareEnvironment(g_tableName, g_storePath1, g_rdbDelegatePtr1);
1100     PrepareVirtualDeviceBEnv(g_tableName);
1101     /**
1102      * @tc.steps: step3. call sync to DEVICES_B
1103      * @tc.expected: step3. should return OK
1104      */
1105     Query query = Query::Select(g_tableName);
1106     SyncStatusCallback callback = nullptr;
1107     EXPECT_EQ(g_rdbDelegatePtr1->Sync({DEVICE_B}, SYNC_MODE_PUSH_ONLY, query, callback, true), OK);
1108     EXPECT_EQ(messageCount, 2); // 2 contain time sync request packet and ability sync packet
1109     /**
1110      * @tc.steps: step4. create distributed table and sync again
1111      * @tc.expected: step4. reopen OK and sync success, only ability packet
1112      */
1113     PrepareEnvironment("table2", g_storePath1, g_rdbDelegatePtr1);
1114     messageCount = 0;
1115     EXPECT_EQ(g_rdbDelegatePtr1->Sync({DEVICE_B}, SYNC_MODE_PUSH_ONLY, query, callback, true), OK);
1116     EXPECT_EQ(messageCount, 1);
1117     CloseStore();
1118     OS::RemoveFile(g_storePath1);
1119     PrepareEnvironment(g_tableName, g_storePath1, g_rdbDelegatePtr1);
1120     g_communicatorAggregator->RegOnDispatch(nullptr);
1121 }
1122 
1123 /**
1124  * @tc.name: RDBSyncOpt003
1125  * @tc.desc: check re ability sync after create distributed table
1126  * @tc.type: FUNC
1127  * @tc.require:
1128  * @tc.author: zhangqiquan
1129  */
1130 HWTEST_F(DistributedDBRelationalMultiUserTest, RDBSyncOpt003, TestSize.Level0)
1131 {
1132     /**
1133      * @tc.steps: step1. record packet which send to B
1134      */
1135     std::atomic<int> messageCount = 0;
1136     RegOnDispatchWithoutDataPacket(messageCount, false);
1137     /**
1138      * @tc.steps: step2. openStore in dual tuple sync mode and call remote query
1139      */
1140     OpenStore1(true);
1141     PrepareEnvironment(g_tableName, g_storePath1, g_rdbDelegatePtr1);
1142     PrepareVirtualDeviceBEnv(g_tableName);
1143     /**
1144      * @tc.steps: step3. call sync to DEVICES_B
1145      * @tc.expected: step3. should return OK
1146      */
1147     Query query = Query::Select(g_tableName);
1148     SyncStatusCallback callback = nullptr;
1149     EXPECT_EQ(g_deviceB->GenericVirtualDevice::Sync(SYNC_MODE_PUSH_ONLY, query, true), E_OK);
1150     EXPECT_EQ(messageCount, 2); // 2 contain time sync request packet and ability sync packet
1151     /**
1152      * @tc.steps: step4. create distributed table and sync again
1153      * @tc.expected: step4. reopen OK and sync success, only ability packet
1154      */
1155     PrepareEnvironment("table2", g_storePath1, g_rdbDelegatePtr1);
1156     messageCount = 0;
1157     EXPECT_EQ(g_deviceB->GenericVirtualDevice::Sync(SYNC_MODE_PUSH_ONLY, query, true), E_OK);
1158     EXPECT_EQ(messageCount, 1);
1159     CloseStore();
1160     OS::RemoveFile(g_storePath1);
1161     PrepareEnvironment(g_tableName, g_storePath1, g_rdbDelegatePtr1);
1162     g_communicatorAggregator->RegOnDispatch(nullptr);
1163 }
1164 
1165 /**
1166  * @tc.name: RDBSyncOpt004
1167  * @tc.desc: check ability sync once after reopen
1168  * @tc.type: FUNC
1169  * @tc.require:
1170  * @tc.author: zhangqiquan
1171  */
1172 HWTEST_F(DistributedDBRelationalMultiUserTest, RDBSyncOpt004, TestSize.Level0)
1173 {
1174     /**
1175      * @tc.steps: step1. record packet which send to B
1176      */
1177     std::atomic<int> messageCount = 0;
1178     RegOnDispatchWithoutDataPacket(messageCount, false);
1179     /**
1180      * @tc.steps: step2. openStore in dual tuple sync mode and call remote query
1181      */
1182     OpenStore1(true);
1183     PrepareEnvironment(g_tableName, g_storePath1, g_rdbDelegatePtr1);
1184     PrepareVirtualDeviceBEnv(g_tableName);
1185     /**
1186      * @tc.steps: step3. call sync to DEVICES_B
1187      * @tc.expected: step3. should return OK
1188      */
1189     Query query = Query::Select(g_tableName);
1190     g_deviceB->GenericVirtualDevice::Sync(DistributedDB::SYNC_MODE_PUSH_ONLY, query, true);
1191     CloseStore();
1192     EXPECT_EQ(messageCount, 2); // 2 contain time sync request packet and ability sync packet
1193     /**
1194      * @tc.steps: step4. re open store and sync again
1195      * @tc.expected: step4. reopen OK and sync success, no negotiation packet
1196      */
1197     OpenStore1(true);
1198     messageCount = 0;
1199     g_deviceB->GenericVirtualDevice::Sync(DistributedDB::SYNC_MODE_PUSH_ONLY, query, true);
1200     EXPECT_EQ(messageCount, 0);
1201     CloseStore();
1202     OS::RemoveFile(g_storePath1);
1203     PrepareEnvironment(g_tableName, g_storePath1, g_rdbDelegatePtr1);
1204     g_communicatorAggregator->RegOnDispatch(nullptr);
1205 }
1206 
1207 /**
1208  * @tc.name: RDBSyncOpt005
1209  * @tc.desc: check re time sync after time change
1210  * @tc.type: FUNC
1211  * @tc.require:
1212  * @tc.author: zhangqiquan
1213  */
1214 HWTEST_F(DistributedDBRelationalMultiUserTest, RDBSyncOpt005, TestSize.Level0)
1215 {
1216     /**
1217      * @tc.steps: step1. record packet which send to B
1218      */
1219     std::atomic<int> messageCount = 0;
1220     RegOnDispatchWithoutDataPacket(messageCount, false);
1221     /**
1222      * @tc.steps: step2. openStore in dual tuple sync mode and call remote query
1223      */
1224     OpenStore1(true);
1225     PrepareEnvironment(g_tableName, g_storePath1, g_rdbDelegatePtr1);
1226     PrepareVirtualDeviceBEnv(g_tableName);
1227     /**
1228      * @tc.steps: step3. call sync to DEVICES_B
1229      * @tc.expected: step3. should return OK
1230      */
1231     Query query = Query::Select(g_tableName);
1232     SyncStatusCallback callback = nullptr;
1233     EXPECT_EQ(g_deviceB->GenericVirtualDevice::Sync(SYNC_MODE_PUSH_ONLY, query, true), E_OK);
1234     EXPECT_EQ(messageCount, 2); // 2 contain time sync request packet and ability sync packet
1235     /**
1236      * @tc.steps: step4. notify time change and sync again
1237      * @tc.expected: step4. sync success, only time sync packet
1238      */
1239     RuntimeContext::GetInstance()->NotifyTimestampChanged(100);
1240     RuntimeContext::GetInstance()->RecordAllTimeChange();
1241     RuntimeContext::GetInstance()->ClearAllDeviceTimeInfo();
1242     messageCount = 0;
1243     EXPECT_EQ(g_deviceB->GenericVirtualDevice::Sync(SYNC_MODE_PUSH_ONLY, query, true), E_OK);
1244     EXPECT_EQ(messageCount, 1);
1245     CloseStore();
1246     OS::RemoveFile(g_storePath1);
1247     PrepareEnvironment(g_tableName, g_storePath1, g_rdbDelegatePtr1);
1248     g_communicatorAggregator->RegOnDispatch(nullptr);
1249 }