• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2024 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 <condition_variable>
17 #include <gtest/gtest.h>
18 #include <thread>
19 
20 #include "cloud_db_sync_utils_test.h"
21 #include "db_constant.h"
22 #include "distributeddb_data_generate_unit_test.h"
23 #include "distributeddb_tools_unit_test.h"
24 #include "kv_store_nb_delegate.h"
25 #include "kv_virtual_device.h"
26 #include "platform_specific.h"
27 #include "relational_store_manager.h"
28 #include "runtime_config.h"
29 #include "virtual_asset_loader.h"
30 #include "virtual_cloud_data_translate.h"
31 
32 using namespace testing::ext;
33 using namespace DistributedDB;
34 using namespace DistributedDBUnitTest;
35 using namespace std;
36 
37 namespace {
38     RelationalStoreObserverUnitTest *g_observer = nullptr;
39     std::shared_ptr<std::string> g_testDir = nullptr;
40     VirtualCommunicatorAggregator* g_communicatorAggregator = nullptr;
41     const std::string DEVICE_A = "real_device";
42     const std::string DEVICE_B = "deviceB";
43     const std::string KEY_INSTANCE_ID = "INSTANCE_ID";
44     const std::string KEY_SUB_USER = "SUB_USER";
45     KvVirtualDevice *g_deviceB = nullptr;
46     DistributedDBToolsUnitTest g_tool;
47     CloudSyncOption g_CloudSyncoption;
48     std::shared_ptr<VirtualCloudDb> virtualCloudDb_ = nullptr;
49     std::shared_ptr<VirtualCloudDataTranslate> g_virtualCloudDataTranslate;
50     const string ASSETS_TABLE_NAME = "student";
51     const string ASSETS_TABLE_NAME_SHARED = "student_shared";
52     const string COL_ID = "id";
53     const string COL_NAME = "name";
54     const string COL_ASSET = "asset";
55     const string COL_ASSETS = "assets";
56     const int64_t WAIT_TIME = 5;
57     const std::vector<Field> CLOUD_FIELDS = {{COL_ID, TYPE_INDEX<int64_t>, true}, {COL_NAME, TYPE_INDEX<std::string>},
58         {COL_ASSET, TYPE_INDEX<Asset>}, {COL_ASSETS, TYPE_INDEX<Assets>}};
59     const string CREATE_SINGLE_PRIMARY_KEY_TABLE = "CREATE TABLE IF NOT EXISTS " + ASSETS_TABLE_NAME + "(" + COL_ID +
60         " INTEGER PRIMARY KEY," + COL_NAME + " TEXT ," + COL_ASSET + " ASSET," + COL_ASSETS + " ASSETS" + ");";
61     const Asset ASSET_COPY = {.version = 1,
62         .name = "Phone",
63         .assetId = "0",
64         .subpath = "/local/sync",
65         .uri = "/local/sync",
66         .modifyTime = "123456",
67         .createTime = "",
68         .size = "256",
69         .hash = "ASE"};
70     int64_t g_nameId = 0;
71 
OpenDelegate(const std::string & dlpPath,KvStoreNbDelegate * & delegatePtr,KvStoreDelegateManager & mgr,bool syncDualTupleMode=false)72     DBStatus OpenDelegate(const std::string &dlpPath, KvStoreNbDelegate *&delegatePtr,
73         KvStoreDelegateManager &mgr, bool syncDualTupleMode = false)
74     {
75         if (g_testDir == nullptr) {
76             return DB_ERROR;
77         }
78         std::string dbPath = *g_testDir + dlpPath;
79         KvStoreConfig storeConfig;
80         storeConfig.dataDir = dbPath;
81         OS::MakeDBDirectory(dbPath);
82         mgr.SetKvStoreConfig(storeConfig);
83 
84         string dir = dbPath + "/single_ver";
85         DIR* dirTmp = opendir(dir.c_str());
86         if (dirTmp == nullptr) {
87             OS::MakeDBDirectory(dir);
88         } else {
89             closedir(dirTmp);
90         }
91 
92         KvStoreNbDelegate::Option option;
93         option.syncDualTupleMode = syncDualTupleMode;
94         DBStatus res = OK;
95         mgr.GetKvStore(STORE_ID_1, option, [&delegatePtr, &res](DBStatus status, KvStoreNbDelegate *delegate) {
96             delegatePtr = delegate;
97             res = status;
98         });
99         return res;
100     }
101 
GetDataBaseSchema()102     DataBaseSchema GetDataBaseSchema()
103     {
104         DataBaseSchema schema;
105         TableSchema tableSchema;
106         tableSchema.name = CloudDbConstant::CLOUD_KV_TABLE_NAME;
107         Field field;
108         field.colName = CloudDbConstant::CLOUD_KV_FIELD_KEY;
109         field.type = TYPE_INDEX<std::string>;
110         field.primary = true;
111         tableSchema.fields.push_back(field);
112         field.colName = CloudDbConstant::CLOUD_KV_FIELD_DEVICE;
113         field.primary = false;
114         tableSchema.fields.push_back(field);
115         field.colName = CloudDbConstant::CLOUD_KV_FIELD_ORI_DEVICE;
116         tableSchema.fields.push_back(field);
117         field.colName = CloudDbConstant::CLOUD_KV_FIELD_VALUE;
118         tableSchema.fields.push_back(field);
119         field.colName = CloudDbConstant::CLOUD_KV_FIELD_DEVICE_CREATE_TIME;
120         field.type = TYPE_INDEX<int64_t>;
121         tableSchema.fields.push_back(field);
122         schema.tables.push_back(tableSchema);
123         return schema;
124     }
125 
SetCloudDB(KvStoreNbDelegate * & delegatePtr)126     DBStatus SetCloudDB(KvStoreNbDelegate *&delegatePtr)
127     {
128         std::map<std::string, std::shared_ptr<ICloudDb>> cloudDbs;
129         cloudDbs[USER_ID] = virtualCloudDb_;
130         delegatePtr->SetCloudDB(cloudDbs);
131         std::map<std::string, DataBaseSchema> schemas;
132         schemas[USER_ID] = GetDataBaseSchema();
133         return delegatePtr->SetCloudDbSchema(schemas);
134     }
135 
OpenDelegate(const std::string & dlpPath,RelationalStoreDelegate * & rdbDelegatePtr,RelationalStoreManager & mgr,sqlite3 * & db)136     DBStatus OpenDelegate(const std::string &dlpPath, RelationalStoreDelegate *&rdbDelegatePtr,
137         RelationalStoreManager &mgr, sqlite3 *&db)
138     {
139         if (g_testDir == nullptr) {
140             return DB_ERROR;
141         }
142         std::string dbDir = *g_testDir + dlpPath;
143         OS::MakeDBDirectory(dbDir);
144         std::string dbPath = dbDir + "/test.db";
145         db = RelationalTestUtils::CreateDataBase(dbPath);
146         EXPECT_EQ(RelationalTestUtils::ExecSql(db, "PRAGMA journal_mode=WAL;"), SQLITE_OK);
147         EXPECT_EQ(RelationalTestUtils::ExecSql(db, CREATE_SINGLE_PRIMARY_KEY_TABLE), SQLITE_OK);
148         g_observer = new (std::nothrow) RelationalStoreObserverUnitTest();
149         RelationalStoreDelegate::Option option = { .observer = g_observer };
150         return mgr.OpenStore(dbPath, STORE_ID_1, option, rdbDelegatePtr);
151     }
152 
GetCloudDbSchema(DataBaseSchema & dataBaseSchema)153     void GetCloudDbSchema(DataBaseSchema &dataBaseSchema)
154     {
155         TableSchema assetsTableSchema = {.name = ASSETS_TABLE_NAME, .sharedTableName = ASSETS_TABLE_NAME_SHARED,
156             .fields = CLOUD_FIELDS};
157         dataBaseSchema.tables.push_back(assetsTableSchema);
158     }
159 
SetCloudDB(RelationalStoreDelegate * & delegatePtr)160     DBStatus SetCloudDB(RelationalStoreDelegate *&delegatePtr)
161     {
162         EXPECT_EQ(delegatePtr->CreateDistributedTable(ASSETS_TABLE_NAME, CLOUD_COOPERATION), DBStatus::OK);
163         std::shared_ptr<VirtualAssetLoader> virtualAssetLoader = make_shared<VirtualAssetLoader>();
164         EXPECT_EQ(delegatePtr->SetCloudDB(virtualCloudDb_), DBStatus::OK);
165         EXPECT_EQ(delegatePtr->SetIAssetLoader(virtualAssetLoader), DBStatus::OK);
166         DataBaseSchema dataBaseSchema;
167         GetCloudDbSchema(dataBaseSchema);
168         return delegatePtr->SetCloudDbSchema(dataBaseSchema);
169     }
170 
CloseDelegate(KvStoreNbDelegate * & delegatePtr,KvStoreDelegateManager & mgr,std::string storeID)171     void CloseDelegate(KvStoreNbDelegate *&delegatePtr, KvStoreDelegateManager &mgr, std::string storeID)
172     {
173         if (delegatePtr == nullptr) {
174             return;
175         }
176         EXPECT_EQ(mgr.CloseKvStore(delegatePtr), OK);
177         delegatePtr = nullptr;
178         EXPECT_EQ(mgr.DeleteKvStore(storeID), OK);
179     }
180 
CloseDelegate(RelationalStoreDelegate * & delegatePtr,RelationalStoreManager & mgr,sqlite3 * & db)181     void CloseDelegate(RelationalStoreDelegate *&delegatePtr, RelationalStoreManager &mgr, sqlite3 *&db)
182     {
183         EXPECT_EQ(sqlite3_close_v2(db), SQLITE_OK);
184         db = nullptr;
185         if (delegatePtr == nullptr) {
186             return;
187         }
188         EXPECT_EQ(mgr.CloseStore(delegatePtr), OK);
189         delegatePtr = nullptr;
190         if (g_observer == nullptr) {
191             return;
192         }
193         delete g_observer;
194         g_observer = nullptr;
195     }
196 
197 class DistributedDBSingleVerMultiSubUserTest : public testing::Test {
198 public:
199     static void SetUpTestCase(void);
200     static void TearDownTestCase(void);
201     void SetUp();
202     void TearDown();
203 protected:
204     void BlockSync(KvStoreNbDelegate *delegate, DBStatus expectDBStatus, CloudSyncOption option,
205         int expectSyncResult = OK);
206     void InsertLocalData(int64_t begin, int64_t count, const std::string &tableName, bool isAssetNull, sqlite3 *&db);
207     void GenerateDataRecords(int64_t begin, int64_t count, int64_t gidStart, std::vector<VBucket> &record,
208         std::vector<VBucket> &extend);
209     CloudSyncOption PrepareOption(const Query &query, LockAction action);
210     void CallSync(RelationalStoreDelegate *delegate, const CloudSyncOption &option, DBStatus expectResult = OK);
211     SyncProcess lastProcess_;
212 };
213 
SetUpTestCase(void)214 void DistributedDBSingleVerMultiSubUserTest::SetUpTestCase(void)
215 {
216     /**
217      * @tc.setup: Init datadir and Virtual Communicator.
218      */
219     std::string testDir;
220     DistributedDBToolsUnitTest::TestDirInit(testDir);
221     if (g_testDir == nullptr) {
222         g_testDir = std::make_shared<std::string>(testDir);
223     }
224 
225     g_communicatorAggregator = new (std::nothrow) VirtualCommunicatorAggregator();
226     ASSERT_TRUE(g_communicatorAggregator != nullptr);
227     RuntimeContext::GetInstance()->SetCommunicatorAggregator(g_communicatorAggregator);
228 
229     g_CloudSyncoption.mode = SyncMode::SYNC_MODE_CLOUD_MERGE;
230     g_CloudSyncoption.users.push_back(USER_ID);
231     g_CloudSyncoption.devices.push_back("cloud");
232     g_virtualCloudDataTranslate = std::make_shared<VirtualCloudDataTranslate>();
233     RuntimeConfig::SetCloudTranslate(g_virtualCloudDataTranslate);
234 }
235 
TearDownTestCase(void)236 void DistributedDBSingleVerMultiSubUserTest::TearDownTestCase(void)
237 {
238     /**
239      * @tc.teardown: Release virtual Communicator and clear data dir.
240      */
241     if (g_testDir != nullptr && DistributedDBToolsUnitTest::RemoveTestDbFiles(*g_testDir) != 0) {
242         LOGE("rm test db files error!");
243     }
244     RuntimeContext::GetInstance()->SetCommunicatorAggregator(nullptr);
245 }
246 
SetUp(void)247 void DistributedDBSingleVerMultiSubUserTest::SetUp(void)
248 {
249     virtualCloudDb_ = std::make_shared<VirtualCloudDb>();
250     DistributedDBToolsUnitTest::PrintTestCaseInfo();
251     g_deviceB = new (std::nothrow) KvVirtualDevice(DEVICE_B);
252     ASSERT_TRUE(g_deviceB != nullptr);
253     VirtualSingleVerSyncDBInterface *syncInterfaceB = new (std::nothrow) VirtualSingleVerSyncDBInterface();
254     ASSERT_TRUE(syncInterfaceB != nullptr);
255     ASSERT_EQ(g_deviceB->Initialize(g_communicatorAggregator, syncInterfaceB), E_OK);
256 }
257 
TearDown(void)258 void DistributedDBSingleVerMultiSubUserTest::TearDown(void)
259 {
260     virtualCloudDb_ = nullptr;
261     if (g_deviceB != nullptr) {
262         delete g_deviceB;
263         g_deviceB = nullptr;
264     }
265     PermissionCheckCallbackV3 nullCallback = nullptr;
266     RuntimeConfig::SetPermissionCheckCallback(nullCallback);
267     SyncActivationCheckCallbackV2 activeCallBack = nullptr;
268     RuntimeConfig::SetSyncActivationCheckCallback(activeCallBack);
269     RuntimeConfig::SetPermissionConditionCallback(nullptr);
270     if (DistributedDBToolsUnitTest::RemoveTestDbFiles(*g_testDir) != 0) {
271         LOGE("rm test db files error.");
272     }
273 }
274 
BlockSync(KvStoreNbDelegate * delegate,DBStatus expectDBStatus,CloudSyncOption option,int expectSyncResult)275 void DistributedDBSingleVerMultiSubUserTest::BlockSync(KvStoreNbDelegate *delegate, DBStatus expectDBStatus,
276     CloudSyncOption option, int expectSyncResult)
277 {
278     if (delegate == nullptr) {
279         return;
280     }
281     std::mutex dataMutex;
282     std::condition_variable cv;
283     bool finish = false;
284     SyncProcess last;
285     auto callback = [expectDBStatus, &last, &cv, &dataMutex, &finish, &option](const std::map<std::string,
286         SyncProcess> &process) {
287         size_t notifyCnt = 0;
288         for (const auto &item: process) {
289             LOGD("user = %s, status = %d", item.first.c_str(), item.second.process);
290             if (item.second.process != DistributedDB::FINISHED) {
291                 continue;
292             }
293             EXPECT_EQ(item.second.errCode, expectDBStatus);
294             {
295                 std::lock_guard<std::mutex> autoLock(dataMutex);
296                 notifyCnt++;
297                 if (notifyCnt == option.users.size()) {
298                     finish = true;
299                     last = item.second;
300                     cv.notify_one();
301                 }
302             }
303         }
304     };
305     EXPECT_EQ(delegate->Sync(option, callback), expectSyncResult);
306     if (expectSyncResult == OK) {
307         std::unique_lock<std::mutex> uniqueLock(dataMutex);
308         cv.wait(uniqueLock, [&finish]() {
309             return finish;
310         });
311     }
312     lastProcess_ = last;
313 }
314 
GenerateDataRecords(int64_t begin,int64_t count,int64_t gidStart,std::vector<VBucket> & record,std::vector<VBucket> & extend)315 void DistributedDBSingleVerMultiSubUserTest::GenerateDataRecords(
316     int64_t begin, int64_t count, int64_t gidStart, std::vector<VBucket> &record, std::vector<VBucket> &extend)
317 {
318     for (int64_t i = begin; i < begin + count; i++) {
319         Assets assets;
320         Asset asset = ASSET_COPY;
321         asset.name = ASSET_COPY.name + std::to_string(i);
322         assets.emplace_back(asset);
323         asset.name = ASSET_COPY.name + std::to_string(i) + "_copy";
324         assets.emplace_back(asset);
325         VBucket data;
326         data.insert_or_assign(COL_ID, i);
327         data.insert_or_assign(COL_NAME, "name" + std::to_string(g_nameId++));
328         data.insert_or_assign(COL_ASSETS, assets);
329         record.push_back(data);
330 
331         VBucket log;
332         Timestamp now = TimeHelper::GetSysCurrentTime();
333         log.insert_or_assign(CloudDbConstant::CREATE_FIELD, (int64_t)now / CloudDbConstant::TEN_THOUSAND);
334         log.insert_or_assign(CloudDbConstant::MODIFY_FIELD, (int64_t)now / CloudDbConstant::TEN_THOUSAND);
335         log.insert_or_assign(CloudDbConstant::DELETE_FIELD, false);
336         log.insert_or_assign(CloudDbConstant::GID_FIELD, std::to_string(i + gidStart));
337         extend.push_back(log);
338     }
339 }
340 
InsertLocalData(int64_t begin,int64_t count,const std::string & tableName,bool isAssetNull,sqlite3 * & db)341 void DistributedDBSingleVerMultiSubUserTest::InsertLocalData(int64_t begin, int64_t count,
342     const std::string &tableName, bool isAssetNull, sqlite3 *&db)
343 {
344     int errCode;
345     std::vector<VBucket> record;
346     std::vector<VBucket> extend;
347     GenerateDataRecords(begin, count, 0, record, extend);
348     const string sql = "insert or replace into " + tableName + " values (?,?,?,?);";
349     for (VBucket vBucket : record) {
350         sqlite3_stmt *stmt = nullptr;
351         ASSERT_EQ(SQLiteUtils::GetStatement(db, sql, stmt), E_OK);
352         ASSERT_EQ(SQLiteUtils::BindInt64ToStatement(stmt, 1, std::get<int64_t>(vBucket[COL_ID])), E_OK); // 1 is id
353         ASSERT_EQ(SQLiteUtils::BindTextToStatement(stmt, 2, std::get<string>(vBucket[COL_NAME])), E_OK); // 2 is name
354         if (isAssetNull) {
355             ASSERT_EQ(sqlite3_bind_null(stmt, 3), SQLITE_OK); // 3 is asset
356         } else {
357             std::vector<uint8_t> assetBlob = g_virtualCloudDataTranslate->AssetToBlob(ASSET_COPY);
358             ASSERT_EQ(SQLiteUtils::BindBlobToStatement(stmt, 3, assetBlob, false), E_OK); // 3 is asset
359         }
360         std::vector<uint8_t> assetsBlob = g_virtualCloudDataTranslate->AssetsToBlob(
361             std::get<Assets>(vBucket[COL_ASSETS]));
362         ASSERT_EQ(SQLiteUtils::BindBlobToStatement(stmt, 4, assetsBlob, false), E_OK); // 4 is assets
363         EXPECT_EQ(SQLiteUtils::StepWithRetry(stmt), SQLiteUtils::MapSQLiteErrno(SQLITE_DONE));
364         SQLiteUtils::ResetStatement(stmt, true, errCode);
365     }
366 }
367 
PrepareOption(const Query & query,LockAction action)368 CloudSyncOption DistributedDBSingleVerMultiSubUserTest::PrepareOption(const Query &query, LockAction action)
369 {
370     CloudSyncOption option;
371     option.devices = { "CLOUD" };
372     option.mode = SYNC_MODE_CLOUD_MERGE;
373     option.query = query;
374     option.waitTime = WAIT_TIME;
375     option.priorityTask = false;
376     option.compensatedSyncOnly = false;
377     option.lockAction = action;
378     return option;
379 }
380 
CallSync(RelationalStoreDelegate * delegate,const CloudSyncOption & option,DBStatus expectResult)381 void DistributedDBSingleVerMultiSubUserTest::CallSync(RelationalStoreDelegate *delegate, const CloudSyncOption &option,
382     DBStatus expectResult)
383 {
384     std::mutex dataMutex;
385     std::condition_variable cv;
386     bool finish = false;
387     auto callback = [&cv, &dataMutex, &finish](const std::map<std::string, SyncProcess> &process) {
388         for (const auto &item: process) {
389             if (item.second.process == DistributedDB::FINISHED) {
390                 {
391                     std::lock_guard<std::mutex> autoLock(dataMutex);
392                     finish = true;
393                 }
394                 cv.notify_one();
395             }
396         }
397     };
398     ASSERT_EQ(delegate->Sync(option, callback), expectResult);
399     if (expectResult == OK) {
400         std::unique_lock<std::mutex> uniqueLock(dataMutex);
401         cv.wait(uniqueLock, [&finish]() {
402             return finish;
403         });
404     }
405 }
406 
407 /**
408  * @tc.name: KvDelegateInvalidParamTest001
409  * @tc.desc: Test kv delegate open with invalid subUser.
410  * @tc.type: FUNC
411  * @tc.require:
412  * @tc.author: zhaoliang
413  */
414 HWTEST_F(DistributedDBSingleVerMultiSubUserTest, KvDelegateInvalidParamTest001, TestSize.Level1)
415 {
416     std::string subUser1 = std::string(129, 'a');
417     KvStoreDelegateManager mgr1(APP_ID, USER_ID, subUser1, INSTANCE_ID_1);
418     KvStoreNbDelegate *delegatePtr1 = nullptr;
419     EXPECT_EQ(OpenDelegate("/subUser1", delegatePtr1, mgr1), INVALID_ARGS);
420     ASSERT_EQ(delegatePtr1, nullptr);
421 
422     std::string subUser2 = "subUser-1";
423     KvStoreDelegateManager mgr2(APP_ID, USER_ID, subUser2, INSTANCE_ID_1);
424     KvStoreNbDelegate *delegatePtr2 = nullptr;
425     EXPECT_EQ(OpenDelegate("/subUser1", delegatePtr2, mgr2), INVALID_ARGS);
426     ASSERT_EQ(delegatePtr2, nullptr);
427 
428     std::string subUser3 = std::string(128, 'a');
429     KvStoreDelegateManager mgr3(APP_ID, USER_ID, subUser3, INSTANCE_ID_1);
430     KvStoreNbDelegate *delegatePtr3 = nullptr;
431     EXPECT_EQ(OpenDelegate("/subUser1", delegatePtr3, mgr3), OK);
432     ASSERT_NE(delegatePtr3, nullptr);
433 
434     CloseDelegate(delegatePtr3, mgr3, STORE_ID_1);
435 }
436 
437 /**
438  * @tc.name: SubUserPermissionCheck
439  * @tc.desc: permission check subuser
440  * @tc.type: FUNC
441  * @tc.require:
442  * @tc.author: luoguo
443  */
444 HWTEST_F(DistributedDBSingleVerMultiSubUserTest, SubUserPermissionCheck, TestSize.Level1)
445 {
446     /**
447      * @tc.steps: step1. set permission check callback
448      * @tc.expected: step1. set OK.
449      */
450     std::string subUser1 = std::string(128, 'a');
451     KvStoreDelegateManager mgr1(APP_ID, USER_ID, subUser1, INSTANCE_ID_1);
__anon7fd7632e0702(const PermissionCheckParamV4 &param, uint8_t flag) 452     auto permissionCheckCallback = [] (const PermissionCheckParamV4 &param, uint8_t flag) -> bool {
453         if (param.deviceId == g_deviceB->GetDeviceId() && (flag && CHECK_FLAG_SPONSOR)) {
454             LOGD("in RunPermissionCheck callback func, check not pass, flag:%d", flag);
455             return false;
456         } else {
457             LOGD("in RunPermissionCheck callback func, check pass, flag:%d", flag);
458             return true;
459         }
460     };
461     EXPECT_EQ(mgr1.SetPermissionCheckCallback(permissionCheckCallback), OK);
462 
463     /**
464      * @tc.steps: step2. deviceB put {1,1}
465      * @tc.expected: step2. put success
466      */
467     KvStoreNbDelegate *delegatePtr1 = nullptr;
468     EXPECT_EQ(OpenDelegate("/subUser1", delegatePtr1, mgr1), OK);
469     ASSERT_NE(delegatePtr1, nullptr);
470 
471     DBStatus status = OK;
472     std::vector<std::string> devices;
473     devices.push_back(g_deviceB->GetDeviceId());
474 
475     Key key = {'1'};
476     Value value = {'1'};
477     g_deviceB->PutData(key, value, 0, 0);
478     ASSERT_TRUE(status == OK);
479 
480     /**
481      * @tc.steps: step3. deviceB push data
482      * @tc.expected: step3. return PERMISSION_CHECK_FORBID_SYNC.
483      */
484     std::map<std::string, DBStatus> result;
485     status = g_tool.SyncTest(delegatePtr1, devices, SYNC_MODE_PUSH_ONLY, result);
486     ASSERT_TRUE(status == OK);
487     std::this_thread::sleep_for(std::chrono::milliseconds(WAIT_TIME));
488 
489     ASSERT_TRUE(result.size() == devices.size());
490     for (const auto &pair : result) {
491         LOGD("dev %s, status %d", pair.first.c_str(), pair.second);
492         if (g_deviceB->GetDeviceId() == pair.first) {
493             EXPECT_TRUE(pair.second == PERMISSION_CHECK_FORBID_SYNC);
494         } else {
495             EXPECT_TRUE(pair.second == OK);
496         }
497     }
498 
499     PermissionCheckCallbackV4 nullCallback = nullptr;
500     EXPECT_EQ(mgr1.SetPermissionCheckCallback(nullCallback), OK);
501     CloseDelegate(delegatePtr1, mgr1, STORE_ID_1);
502 }
503 
504 /**
505  * @tc.name: RDBDelegateInvalidParamTest001
506  * @tc.desc: Test rdb delegate open with invalid subUser.
507  * @tc.type: FUNC
508  * @tc.require:
509  * @tc.author: zhaoliang
510  */
511 HWTEST_F(DistributedDBSingleVerMultiSubUserTest, RDBDelegateInvalidParamTest001, TestSize.Level1)
512 {
513     std::string subUser1 = std::string(129, 'a');
514     RelationalStoreManager mgr1(APP_ID, USER_ID, subUser1, INSTANCE_ID_1);
515     RelationalStoreDelegate *rdbDelegatePtr1 = nullptr;
516     sqlite3 *db1;
517     EXPECT_EQ(OpenDelegate("/subUser1", rdbDelegatePtr1, mgr1, db1), INVALID_ARGS);
518     ASSERT_EQ(rdbDelegatePtr1, nullptr);
519     CloseDelegate(rdbDelegatePtr1, mgr1, db1);
520 
521     std::string subUser2 = "subUser-1";
522     RelationalStoreManager mgr2(APP_ID, USER_ID, subUser2, INSTANCE_ID_1);
523     RelationalStoreDelegate *rdbDelegatePtr2 = nullptr;
524     sqlite3 *db2;
525     EXPECT_EQ(OpenDelegate("/subUser1", rdbDelegatePtr2, mgr2, db2), INVALID_ARGS);
526     ASSERT_EQ(rdbDelegatePtr2, nullptr);
527     CloseDelegate(rdbDelegatePtr2, mgr2, db2);
528 
529     std::string subUser3 = std::string(128, 'a');
530     RelationalStoreManager mgr3(APP_ID, USER_ID, subUser3, INSTANCE_ID_1);
531     RelationalStoreDelegate *rdbDelegatePtr3 = nullptr;
532     sqlite3 *db3;
533     EXPECT_EQ(OpenDelegate("/subUser1", rdbDelegatePtr3, mgr3, db3), OK);
534     ASSERT_NE(rdbDelegatePtr3, nullptr);
535 
536     CloseDelegate(rdbDelegatePtr3, mgr3, db3);
537 }
538 
539 /**
540  * @tc.name: SameDelegateTest001
541  * @tc.desc: Test kv delegate open with diff subUser.
542  * @tc.type: FUNC
543  * @tc.require:
544  * @tc.author: zhaoliang
545  */
546 HWTEST_F(DistributedDBSingleVerMultiSubUserTest, SameDelegateTest001, TestSize.Level1)
547 {
548     KvStoreDelegateManager mgr1(APP_ID, USER_ID, SUB_USER_1, INSTANCE_ID_1);
549     KvStoreNbDelegate *delegatePtr1 = nullptr;
550     EXPECT_EQ(OpenDelegate("/subUser1", delegatePtr1, mgr1), OK);
551     ASSERT_NE(delegatePtr1, nullptr);
552 
553     KvStoreDelegateManager mgr2(APP_ID, USER_ID, SUB_USER_2, INSTANCE_ID_1);
554     KvStoreNbDelegate *delegatePtr2 = nullptr;
555     EXPECT_EQ(OpenDelegate("/subUser2", delegatePtr2, mgr2), OK);
556     ASSERT_NE(delegatePtr2, nullptr);
557 
558     Key key1 = {'k', '1'};
559     Value value1 = {'v', '1'};
560     delegatePtr1->Put(key1, value1);
561     Key key2 = {'k', '2'};
562     Value value2 = {'v', '2'};
563     delegatePtr2->Put(key2, value2);
564 
565     Value value;
566     EXPECT_EQ(delegatePtr1->Get(key1, value), OK);
567     EXPECT_EQ(value1, value);
568     EXPECT_EQ(delegatePtr2->Get(key2, value), OK);
569     EXPECT_EQ(value2, value);
570 
571     EXPECT_EQ(delegatePtr1->Get(key2, value), NOT_FOUND);
572     EXPECT_EQ(delegatePtr2->Get(key1, value), NOT_FOUND);
573 
574     CloseDelegate(delegatePtr1, mgr1, STORE_ID_1);
575     CloseDelegate(delegatePtr2, mgr2, STORE_ID_1);
576 }
577 
578 /**
579  * @tc.name: SameDelegateTest002
580  * @tc.desc: Test rdb delegate open with diff subUser.
581  * @tc.type: FUNC
582  * @tc.require:
583  * @tc.author: zhaoliang
584  */
585 HWTEST_F(DistributedDBSingleVerMultiSubUserTest, SameDelegateTest002, TestSize.Level1)
586 {
587     RelationalStoreManager mgr1(APP_ID, USER_ID, SUB_USER_1, INSTANCE_ID_1);
588     RelationalStoreDelegate *rdbDelegatePtr1 = nullptr;
589     sqlite3 *db1;
590     EXPECT_EQ(OpenDelegate("/subUser1", rdbDelegatePtr1, mgr1, db1), OK);
591     ASSERT_NE(rdbDelegatePtr1, nullptr);
592 
593     RelationalStoreManager mgr2(APP_ID, USER_ID, SUB_USER_2, INSTANCE_ID_1);
594     RelationalStoreDelegate *rdbDelegatePtr2 = nullptr;
595     sqlite3 *db2;
596     EXPECT_EQ(OpenDelegate("/subUser2", rdbDelegatePtr2, mgr2, db2), OK);
597     ASSERT_NE(rdbDelegatePtr2, nullptr);
598 
599     int localCount = 10;
600     InsertLocalData(0, localCount, ASSETS_TABLE_NAME, true, db1);
601     InsertLocalData(10, localCount, ASSETS_TABLE_NAME, true, db2);
602 
603     std::string sql1 = "select count(*) from " + ASSETS_TABLE_NAME + " where id < 10;";
604     std::string sql2 = "select count(*) from " + ASSETS_TABLE_NAME + " where id >= 10;";
605 
606     EXPECT_EQ(sqlite3_exec(db1, sql1.c_str(), CloudDBSyncUtilsTest::QueryCountCallback,
607         reinterpret_cast<void *>(10), nullptr), SQLITE_OK);
608     EXPECT_EQ(sqlite3_exec(db2, sql2.c_str(), CloudDBSyncUtilsTest::QueryCountCallback,
609         reinterpret_cast<void *>(10), nullptr), SQLITE_OK);
610 
611     EXPECT_EQ(sqlite3_exec(db1, sql2.c_str(), CloudDBSyncUtilsTest::QueryCountCallback,
612         reinterpret_cast<void *>(0), nullptr), SQLITE_OK);
613     EXPECT_EQ(sqlite3_exec(db2, sql1.c_str(), CloudDBSyncUtilsTest::QueryCountCallback,
614         reinterpret_cast<void *>(0), nullptr), SQLITE_OK);
615 
616     CloseDelegate(rdbDelegatePtr1, mgr1, db1);
617     CloseDelegate(rdbDelegatePtr2, mgr2, db2);
618 }
619 
620 /**
621  * @tc.name: SubUserDelegateCRUDTest001
622  * @tc.desc: Test subUser rdb delegate crud function.
623  * @tc.type: FUNC
624  * @tc.require:
625  * @tc.author: zhaoliang
626  */
627 HWTEST_F(DistributedDBSingleVerMultiSubUserTest, SubUserDelegateCRUDTest001, TestSize.Level1)
628 {
629     RelationalStoreManager mgr1(APP_ID, USER_ID, SUB_USER_1, INSTANCE_ID_1);
630     RelationalStoreDelegate *rdbDelegatePtr1 = nullptr;
631     sqlite3 *db1;
632     EXPECT_EQ(OpenDelegate("/subUser1", rdbDelegatePtr1, mgr1, db1), OK);
633     ASSERT_NE(rdbDelegatePtr1, nullptr);
634 
635     int localCount = 10;
636     InsertLocalData(0, localCount, ASSETS_TABLE_NAME, true, db1);
637     std::string sql1 = "select count(*) from " + ASSETS_TABLE_NAME + ";";
638     EXPECT_EQ(sqlite3_exec(db1, sql1.c_str(), CloudDBSyncUtilsTest::QueryCountCallback,
639         reinterpret_cast<void *>(10), nullptr), SQLITE_OK);
640 
641     InsertLocalData(0, localCount, ASSETS_TABLE_NAME, true, db1);
642     EXPECT_EQ(sqlite3_exec(db1, sql1.c_str(), CloudDBSyncUtilsTest::QueryCountCallback,
643         reinterpret_cast<void *>(10), nullptr), SQLITE_OK);
644 
645     std::string sql2 = "delete from " + ASSETS_TABLE_NAME + ";";
646     EXPECT_EQ(sqlite3_exec(db1, sql2.c_str(), CloudDBSyncUtilsTest::QueryCountCallback,
647         reinterpret_cast<void *>(0), nullptr), SQLITE_OK);
648     EXPECT_EQ(sqlite3_exec(db1, sql1.c_str(), CloudDBSyncUtilsTest::QueryCountCallback,
649         reinterpret_cast<void *>(0), nullptr), SQLITE_OK);
650 
651     CloseDelegate(rdbDelegatePtr1, mgr1, db1);
652 }
653 
654 /**
655  * @tc.name: SubUserDelegateCRUDTest002
656  * @tc.desc: Test subUser kv delegate crud function.
657  * @tc.type: FUNC
658  * @tc.require:
659  * @tc.author: zhaoliang
660  */
661 HWTEST_F(DistributedDBSingleVerMultiSubUserTest, SubUserDelegateCRUDTest002, TestSize.Level1)
662 {
663     KvStoreDelegateManager mgr1(APP_ID, USER_ID, SUB_USER_1, INSTANCE_ID_1);
664     KvStoreNbDelegate *delegatePtr1 = nullptr;
665     EXPECT_EQ(OpenDelegate("/subUser1", delegatePtr1, mgr1), OK);
666     ASSERT_NE(delegatePtr1, nullptr);
667 
668     Key key1 = {'k', '1'};
669     Value value1 = {'v', '1'};
670     delegatePtr1->Put(key1, value1);
671 
672     Value value;
673     EXPECT_EQ(delegatePtr1->Get(key1, value), OK);
674     EXPECT_EQ(value1, value);
675 
676     Value value2 = {'v', '2'};
677     delegatePtr1->Put(key1, value2);
678     EXPECT_EQ(delegatePtr1->Get(key1, value), OK);
679     EXPECT_EQ(value2, value);
680 
681     EXPECT_EQ(delegatePtr1->Delete(key1), OK);
682     EXPECT_EQ(delegatePtr1->Get(key1, value), NOT_FOUND);
683 
684     CloseDelegate(delegatePtr1, mgr1, STORE_ID_1);
685 }
686 
687 #ifdef USE_DISTRIBUTEDDB_CLOUD
688 /**
689  * @tc.name: SubUserDelegateCloudSyncTest001
690  * @tc.desc: Test subUser kv delegate cloud sync function.
691  * @tc.type: FUNC
692  * @tc.require:
693  * @tc.author: zhaoliang
694  */
695 HWTEST_F(DistributedDBSingleVerMultiSubUserTest, SubUserDelegateCloudSyncTest001, TestSize.Level0)
696 {
697     KvStoreDelegateManager mgr1(APP_ID, USER_ID, SUB_USER_1, INSTANCE_ID_1);
698     KvStoreNbDelegate *delegatePtr1 = nullptr;
699     EXPECT_EQ(OpenDelegate("/subUser1", delegatePtr1, mgr1), OK);
700     ASSERT_NE(delegatePtr1, nullptr);
701     EXPECT_EQ(SetCloudDB(delegatePtr1), OK);
702 
703     KvStoreDelegateManager mgr2(APP_ID, USER_ID, SUB_USER_2, INSTANCE_ID_1);
704     KvStoreNbDelegate *delegatePtr2 = nullptr;
705     EXPECT_EQ(OpenDelegate("/subUser2", delegatePtr2, mgr2), OK);
706     ASSERT_NE(delegatePtr2, nullptr);
707     EXPECT_EQ(SetCloudDB(delegatePtr2), OK);
708 
709     Key key = {'k'};
710     Value expectValue = {'v'};
711     ASSERT_EQ(delegatePtr1->Put(key, expectValue), OK);
712     BlockSync(delegatePtr1, OK, g_CloudSyncoption);
713     for (const auto &table : lastProcess_.tableProcess) {
714         EXPECT_EQ(table.second.upLoadInfo.total, 1u);
715     }
716     BlockSync(delegatePtr2, OK, g_CloudSyncoption);
717     for (const auto &table : lastProcess_.tableProcess) {
718         EXPECT_EQ(table.second.downLoadInfo.total, 1u);
719     }
720     Value actualValue;
721     EXPECT_EQ(delegatePtr2->Get(key, actualValue), OK);
722     EXPECT_EQ(actualValue, expectValue);
723 
724     CloseDelegate(delegatePtr1, mgr1, STORE_ID_1);
725     CloseDelegate(delegatePtr2, mgr2, STORE_ID_1);
726 }
727 
728 /**
729  * @tc.name: SubUserDelegateCloudSyncTest002
730  * @tc.desc: Test subUser rdb delegate cloud sync function.
731  * @tc.type: FUNC
732  * @tc.require:
733  * @tc.author: zhaoliang
734  */
735 HWTEST_F(DistributedDBSingleVerMultiSubUserTest, SubUserDelegateCloudSyncTest002, TestSize.Level0)
736 {
737     RelationalStoreManager mgr1(APP_ID, USER_ID, SUB_USER_1, INSTANCE_ID_1);
738     RelationalStoreDelegate *rdbDelegatePtr1 = nullptr;
739     sqlite3 *db1;
740     EXPECT_EQ(OpenDelegate("/subUser1", rdbDelegatePtr1, mgr1, db1), OK);
741     ASSERT_NE(rdbDelegatePtr1, nullptr);
742     EXPECT_EQ(SetCloudDB(rdbDelegatePtr1), OK);
743 
744     RelationalStoreManager mgr2(APP_ID, USER_ID, SUB_USER_2, INSTANCE_ID_1);
745     RelationalStoreDelegate *rdbDelegatePtr2 = nullptr;
746     sqlite3 *db2;
747     EXPECT_EQ(OpenDelegate("/subUser2", rdbDelegatePtr2, mgr2, db2), OK);
748     ASSERT_NE(rdbDelegatePtr2, nullptr);
749     EXPECT_EQ(SetCloudDB(rdbDelegatePtr2), OK);
750 
751     int localCount = 10;
752     InsertLocalData(0, localCount, ASSETS_TABLE_NAME, true, db1);
753     CloudSyncOption option = PrepareOption(Query::Select().FromTable({ ASSETS_TABLE_NAME }), LockAction::NONE);
754     CallSync(rdbDelegatePtr1, option);
755     CallSync(rdbDelegatePtr2, option);
756 
757     std::string sql = "select count(*) from " + ASSETS_TABLE_NAME + ";";
758     EXPECT_EQ(sqlite3_exec(db2, sql.c_str(), CloudDBSyncUtilsTest::QueryCountCallback,
759         reinterpret_cast<void *>(10), nullptr), SQLITE_OK);
760 
761     CloseDelegate(rdbDelegatePtr1, mgr1, db1);
762     CloseDelegate(rdbDelegatePtr2, mgr2, db2);
763 }
764 #endif
765 
766 /**
767  * @tc.name: MultiSubUserDelegateSync001
768  * @tc.desc: Test subUser delegate sync function.
769  * @tc.type: FUNC
770  * @tc.require:
771  * @tc.author: zhaoliang
772  */
773 HWTEST_F(DistributedDBSingleVerMultiSubUserTest, MultiSubUserDelegateSync001, TestSize.Level1)
774 {
775     KvStoreDelegateManager mgr1(APP_ID, USER_ID, SUB_USER_1, INSTANCE_ID_1);
__anon7fd7632e0802(const PermissionCheckParam &param, uint8_t flag) 776     RuntimeConfig::SetPermissionCheckCallback([](const PermissionCheckParam &param, uint8_t flag) {
777         if ((flag & PermissionCheckFlag::CHECK_FLAG_RECEIVE) != 0) {
778             bool res = false;
779             if (param.extraConditions.find(KEY_SUB_USER) != param.extraConditions.end()) {
780                 res = param.extraConditions.at(KEY_SUB_USER) == SUB_USER_1;
781             }
782             return res;
783         }
784         if (param.userId != USER_ID || param.appId != APP_ID || param.storeId != STORE_ID_1 ||
785             (param.instanceId != INSTANCE_ID_1 && param.instanceId != 0)) {
786             return false;
787         }
788         return true;
789     });
__anon7fd7632e0902(const PermissionConditionParam &param) 790     RuntimeConfig::SetPermissionConditionCallback([](const PermissionConditionParam &param) {
791         std::map<std::string, std::string> res;
792         res.emplace(KEY_SUB_USER, SUB_USER_1);
793         return res;
794     });
795 
796     KvStoreNbDelegate *delegatePtr1 = nullptr;
797     EXPECT_EQ(OpenDelegate("/subUser1", delegatePtr1, mgr1), OK);
798     ASSERT_NE(delegatePtr1, nullptr);
799 
800     Key key1 = {'k', '1'};
801     Value value1 = {'v', '1'};
802     delegatePtr1->Put(key1, value1);
803 
804     std::map<std::string, DBStatus> result;
805     DBStatus status = g_tool.SyncTest(delegatePtr1, { DEVICE_B }, SYNC_MODE_PUSH_ONLY, result);
806     EXPECT_TRUE(status == OK);
807     EXPECT_EQ(result[DEVICE_B], OK);
808 
809     CloseDelegate(delegatePtr1, mgr1, STORE_ID_1);
810 }
811 
812 /**
813  * @tc.name: MultiSubUserDelegateSync002
814  * @tc.desc: Test subUser delegate sync active if callback return true.
815  * @tc.type: FUNC
816  * @tc.require:
817  * @tc.author: zhaoliang
818  */
819 HWTEST_F(DistributedDBSingleVerMultiSubUserTest, MultiSubUserDelegateSync002, TestSize.Level1)
820 {
821     KvStoreDelegateManager mgr1(APP_ID, USER_ID, SUB_USER_1, INSTANCE_ID_1);
__anon7fd7632e0a02(const ActivationCheckParam &param) 822     RuntimeConfig::SetSyncActivationCheckCallback([](const ActivationCheckParam &param) {
823         if (param.userId == USER_ID && param.appId == APP_ID && param.storeId == STORE_ID_1 &&
824             param.instanceId == INSTANCE_ID_1) {
825             return true;
826         }
827         return false;
828     });
829 
830     KvStoreNbDelegate *delegatePtr1 = nullptr;
831     EXPECT_EQ(OpenDelegate("/subUser1", delegatePtr1, mgr1, true), OK);
832     ASSERT_NE(delegatePtr1, nullptr);
833 
834     std::map<std::string, DBStatus> result;
835     DBStatus status = g_tool.SyncTest(delegatePtr1, { DEVICE_B }, SYNC_MODE_PUSH_ONLY, result);
836     EXPECT_EQ(status, OK);
837     EXPECT_EQ(result[DEVICE_B], OK);
838 
839     CloseDelegate(delegatePtr1, mgr1, STORE_ID_1);
840 }
841 
842 } // namespace