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