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 ¶m) 237 const AutoLaunchRequestCallback g_callback = [](const std::string &identifier, AutoLaunchParam ¶m) {
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 }