1 /*
2  * Copyright (c) 2023 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 #include "cloud_syncer.h"
16 
17 #include <gtest/gtest.h>
18 
19 #include "cloud/asset_operation_utils.h"
20 #include "cloud_syncer_test.h"
21 #include "cloud_store_types.h"
22 #include "db_errno.h"
23 #include "distributeddb_tools_unit_test.h"
24 #include "relational_store_manager.h"
25 #include "distributeddb_data_generate_unit_test.h"
26 #include "relational_sync_able_storage.h"
27 #include "relational_store_instance.h"
28 #include "sqlite_relational_store.h"
29 #include "log_table_manager_factory.h"
30 
31 using namespace testing::ext;
32 using namespace DistributedDB;
33 using namespace DistributedDBUnitTest;
34 using namespace std;
35 
36 namespace {
37     constexpr auto FIELD_ID = "id";
38     constexpr auto FIELD_NAME = "name";
39     constexpr auto FIELD_HOUSE = "house";
40     constexpr auto FIELD_CARS = "cars";
41     const string STORE_ID = "Relational_Store_ID";
42     const string TABLE_NAME = "cloudData";
43     string g_storePath;
44     string g_dbDir;
45     string TEST_DIR;
46     DistributedDB::RelationalStoreManager g_mgr(APP_ID, USER_ID);
47     RelationalStoreDelegate *g_delegate = nullptr;
48     IRelationalStore *g_store = nullptr;
49     std::shared_ptr<TestStorageProxy> g_storageProxy = nullptr;
50     std::shared_ptr<TestCloudSyncer> g_cloudSyncer = nullptr;
51     Asset a1;
52     Asset a1Changed;
53     Asset a2;
54     Asset a2Changed;
55     Asset a3;
56     Asset a3Changed;
57     Asset a4;
58     Asset a4Changed;
59     Asset a5;
60     Asset a5Changed;
61     const std::vector<Field> ASSET_FIELDS = {
62         {FIELD_HOUSE, TYPE_INDEX<Asset>, false}, {FIELD_CARS, TYPE_INDEX<Assets>, false}
63     };
64     VBucket DATA_BASELINE;
65     VBucket DATA_EMPTY_ASSET;
66     VBucket DATA_ASSET_SAME_NAME_BUT_CHANGE;
67     VBucket DATA_ASSETS_SAME_NAME_PARTIALLY_CHANGED;
68     VBucket DATA_ALL_SAME;
69     VBucket DATA_ASSETS_MORE_FIELD;
70     VBucket DATA_EMPTY;
71     VBucket DATA_ASSETS_DIFFERENT_FIELD;
72     VBucket DATA_ASSETS_DIFFERENT_CHANGED_FIELD;
73     VBucket DATA_ASSETS_SAME_NAME_ALL_CHANGED;
74     VBucket DATA_ASSETS_ASSET_SAME_NAME;
75     VBucket DATA_NULL_ASSET;
76     VBucket DATA_ASSET_IN_ASSETS;
77     VBucket DATA_NULL_ASSETS;
78     VBucket DATA_ALL_NULL_ASSETS;
79     VBucket DATA_EMPTY_ASSETS;
80     VBucket DATA_UPDATE_DELTE_NOCHANGE_INSERT;
81     VBucket DATA_SAME_NAME_ASSETS;
82 
GenAsset(std::string name,std::string hash)83     Asset GenAsset(std::string name, std::string hash)
84     {
85         Asset asset;
86         asset.name = name;
87         asset.hash = hash;
88         return asset;
89     }
90 
GenDatum(int64_t id,std::string name,Type asset,Type assets)91     VBucket GenDatum(int64_t id, std::string name, Type asset, Type assets)
92     {
93         VBucket datum;
94         datum[FIELD_ID] = id;
95         datum[FIELD_NAME] = name;
96         datum[FIELD_HOUSE] = asset;
97         datum[FIELD_CARS] = assets;
98         return datum;
99     }
100 
GenData()101     void GenData()
102     {
103         a1 = GenAsset("mansion", "mansion1");
104         a1Changed = GenAsset("mansion", "mansion1Changed");
105         a2 = GenAsset("suv", "suv1");
106         a2Changed = GenAsset("suv", "suv1Changed");
107         a3 = GenAsset("truck", "truck1");
108         a3Changed = GenAsset("truck", "truck1Changed");
109         a4 = GenAsset("sedan", "sedan1");
110         a4Changed = GenAsset("sedan", "sedan1Changed");
111         a5 = GenAsset("trucker", "truck1");
112         a5Changed = GenAsset("trucker", "truck1Changed");
113         DATA_EMPTY.clear();
114         DATA_BASELINE = GenDatum(1, "Jack", a1, Assets({a2, a3, a4})); // id is 1
115         DATA_EMPTY_ASSET = GenDatum(2, "PoorGuy", a1, Assets({})); // id is 2
116         DATA_EMPTY_ASSET.erase(FIELD_HOUSE);
117         DATA_ASSET_SAME_NAME_BUT_CHANGE = GenDatum(3, "Alice", a1Changed, Assets({a2, a3, a4})); // id is 3
118         DATA_ASSETS_SAME_NAME_PARTIALLY_CHANGED = GenDatum(4, "David", a1, Assets({a2, a3Changed, a4})); // id is 4
119         DATA_ALL_SAME = GenDatum(5, "Marry", a1, Assets({a2, a3, a4})); // id is 5
120         DATA_ASSETS_MORE_FIELD = GenDatum(6, "Carl", a1, Assets({a2, a3, a4, a5})); // id is 6
121         DATA_ASSETS_DIFFERENT_FIELD = GenDatum(7, "Carllol", a1, Assets({a2, a3, a5})); // id is 7
122         DATA_ASSETS_DIFFERENT_CHANGED_FIELD = GenDatum(8, "Carllol", a1, Assets({a2, a3Changed, a5})); // id is 8
123         DATA_ASSETS_SAME_NAME_ALL_CHANGED = GenDatum(
124             9, "Lob", a1Changed, Assets({a2Changed, a3Changed, a4Changed})); // id is 9
125         DATA_ASSETS_ASSET_SAME_NAME = GenDatum(10, "Lob2", a1, Assets({a1, a2, a3})); // id is 10
126         std::monostate nil;
127         DATA_NULL_ASSET = GenDatum(11, "Lob3", nil, Assets({a1, a2, a3})); // id is 11
128         DATA_ASSET_IN_ASSETS = GenDatum(12, "Lob4", Assets({a1}), Assets({a2, a3, a4})); // id is 12
129         DATA_NULL_ASSETS = GenDatum(13, "Lob5", Assets({a1}), nil); // id is 13
130         DATA_ALL_NULL_ASSETS = GenDatum(14, "Nico", nil, nil); // id is 14
131         DATA_EMPTY_ASSETS = GenDatum(15, "Lob6", a1, Assets({})); // id is 15
132         DATA_EMPTY_ASSETS.erase(FIELD_CARS);
133         DATA_UPDATE_DELTE_NOCHANGE_INSERT = GenDatum(16, "Nico321", nil, Assets({a2Changed, a4, a5})); // id is 16
134         DATA_SAME_NAME_ASSETS = GenDatum(16, "Nico156", nil, Assets({a1, a1Changed})); // id is 16
135     }
136 
CreateDB()137     void CreateDB()
138     {
139         sqlite3 *db = nullptr;
140         int errCode = sqlite3_open(g_storePath.c_str(), &db);
141         if (errCode != SQLITE_OK) {
142             LOGE("open db failed:%d", errCode);
143             sqlite3_close(db);
144             return;
145         }
146         const string sql =
147             "PRAGMA journal_mode=WAL;";
148         ASSERT_EQ(SQLiteUtils::ExecuteRawSQL(db, sql.c_str()), E_OK);
149         sqlite3_close(db);
150     }
151 
InitStoreProp(const std::string & storePath,const std::string & appId,const std::string & userId,RelationalDBProperties & properties)152     void InitStoreProp(const std::string &storePath, const std::string &appId, const std::string &userId,
153         RelationalDBProperties &properties)
154     {
155         properties.SetStringProp(RelationalDBProperties::DATA_DIR, storePath);
156         properties.SetStringProp(RelationalDBProperties::APP_ID, appId);
157         properties.SetStringProp(RelationalDBProperties::USER_ID, userId);
158         properties.SetStringProp(RelationalDBProperties::STORE_ID, STORE_ID);
159         std::string identifier = userId + "-" + appId + "-" + STORE_ID;
160         std::string hashIdentifier = DBCommon::TransferHashString(identifier);
161         properties.SetStringProp(RelationalDBProperties::IDENTIFIER_DATA, hashIdentifier);
162     }
163 
GetRelationalStore()164     const RelationalSyncAbleStorage *GetRelationalStore()
165     {
166         RelationalDBProperties properties;
167         InitStoreProp(g_storePath, APP_ID, USER_ID, properties);
168         int errCode = E_OK;
169         g_store = RelationalStoreInstance::GetDataBase(properties, errCode);
170         if (g_store == nullptr) {
171             LOGE("Get db failed:%d", errCode);
172             return nullptr;
173         }
174         return static_cast<SQLiteRelationalStore *>(g_store)->GetStorageEngine();
175     }
176 
177     class DistributedDBCloudAssetCompareTest : public testing::Test {
178     public:
179         static void SetUpTestCase(void);
180         static void TearDownTestCase(void);
181         void SetUp();
182         void TearDown();
183     };
184 
SetUpTestCase(void)185     void DistributedDBCloudAssetCompareTest::SetUpTestCase(void)
186     {
187         DistributedDBToolsUnitTest::TestDirInit(TEST_DIR);
188         LOGD("test dir is %s", TEST_DIR.c_str());
189         g_dbDir = TEST_DIR + "/";
190         g_storePath =  g_dbDir + STORE_ID + ".db";
191         DistributedDBToolsUnitTest::RemoveTestDbFiles(TEST_DIR);
192     }
193 
TearDownTestCase(void)194     void DistributedDBCloudAssetCompareTest::TearDownTestCase(void)
195     {
196     }
197 
SetUp(void)198     void DistributedDBCloudAssetCompareTest::SetUp(void)
199     {
200         DistributedDBToolsUnitTest::PrintTestCaseInfo();
201         LOGD("Test dir is %s", TEST_DIR.c_str());
202         CreateDB();
203         ASSERT_EQ(g_mgr.OpenStore(g_storePath, STORE_ID, RelationalStoreDelegate::Option {}, g_delegate), DBStatus::OK);
204         ASSERT_NE(g_delegate, nullptr);
205         g_storageProxy = std::make_shared<TestStorageProxy>((ICloudSyncStorageInterface *) GetRelationalStore());
206         ASSERT_NE(g_storageProxy, nullptr);
207         g_cloudSyncer = std::make_shared<TestCloudSyncer>(g_storageProxy);
208         ASSERT_NE(g_cloudSyncer, nullptr);
209         g_cloudSyncer->SetAssetFields(TABLE_NAME, ASSET_FIELDS);
210         GenData();
211     }
212 
TearDown(void)213     void DistributedDBCloudAssetCompareTest::TearDown(void)
214     {
215         RefObject::DecObjRef(g_store);
216         if (g_delegate != nullptr) {
217             EXPECT_EQ(g_mgr.CloseStore(g_delegate), DBStatus::OK);
218             g_delegate = nullptr;
219             g_storageProxy = nullptr;
220             g_cloudSyncer = nullptr;
221         }
222         if (DistributedDBToolsUnitTest::RemoveTestDbFiles(TEST_DIR) != 0) {
223             LOGE("rm test db files error.");
224         }
225     }
226 
IsAssetEq(Asset & target,Asset & expected)227     static bool IsAssetEq(Asset &target, Asset &expected)
228     {
229         if (target.name != expected.name ||
230             target.flag != expected.flag ||
231             target.status != expected.status) {
232             return false;
233         }
234         return true;
235     }
236 
CheckAssetDownloadList(std::string fieldName,std::map<std::string,Assets> & target,std::map<std::string,Assets> & expected)237     static bool CheckAssetDownloadList(std::string fieldName, std::map<std::string, Assets> &target,
238         std::map<std::string, Assets> &expected)
239     {
240         if (target[fieldName].size() != expected[fieldName].size()) {
241             LOGE("[CheckAssetDownloadList] size is not equal actual %zu expect %zu", target[fieldName].size(),
242                 expected[fieldName].size());
243             return false;
244         }
245         for (size_t i = 0; i < target[fieldName].size(); i++) {
246             if (!IsAssetEq(target[fieldName][i], expected[fieldName][i])) {
247                 LOGE("[CheckAssetDownloadList] asset not equal fieldName %s index %zu", fieldName.c_str(), i);
248                 return false;
249             }
250         }
251         return true;
252     }
253 
TagAsset(AssetOpType flag,AssetStatus status,Asset & asset)254     static void TagAsset(AssetOpType flag, AssetStatus status, Asset &asset)
255     {
256         asset.flag = static_cast<uint32_t>(flag);
257         asset.status = static_cast<uint32_t>(status);
258     }
259 
GetDownloadWithNullStatus()260     static AssetStatus GetDownloadWithNullStatus()
261     {
262         return static_cast<AssetStatus>(static_cast<uint32_t>(DOWNLOADING) | static_cast<uint32_t>(DOWNLOAD_WITH_NULL));
263     }
264 
265     /**
266      * @tc.name: AssetCmpTest001
267      * @tc.desc:
268      * @tc.type: FUNC
269      * @tc.require:
270      * @tc.author: wanyi
271      */
272     HWTEST_F(DistributedDBCloudAssetCompareTest, AssetCmpTest001, TestSize.Level0)
273     {
274         auto assetList = g_cloudSyncer->TestTagAssetsInSingleRecord(DATA_BASELINE, DATA_EMPTY);
275         std::map<std::string, Assets> expectedList;
276         TagAsset(AssetOpType::INSERT, GetDownloadWithNullStatus(), a1);
277         TagAsset(AssetOpType::INSERT, GetDownloadWithNullStatus(), a2);
278         TagAsset(AssetOpType::INSERT, GetDownloadWithNullStatus(), a3);
279         TagAsset(AssetOpType::INSERT, GetDownloadWithNullStatus(), a4);
280         expectedList[FIELD_HOUSE] = { a1 };
281         expectedList[FIELD_CARS] = { a2, a3, a4 };
282         ASSERT_TRUE(CheckAssetDownloadList(FIELD_HOUSE, assetList, expectedList));
283         ASSERT_TRUE(CheckAssetDownloadList(FIELD_CARS, assetList, expectedList));
284     }
285 
286     /**
287      * @tc.name: AssetCmpTest002
288      * @tc.desc:
289      * @tc.type: FUNC
290      * @tc.require:
291      * @tc.author: wanyi
292      */
293     HWTEST_F(DistributedDBCloudAssetCompareTest, AssetCmpTest002, TestSize.Level0)
294     {
295         auto assetList = g_cloudSyncer->TestTagAssetsInSingleRecord(DATA_BASELINE, DATA_EMPTY_ASSET);
296         std::map<std::string, Assets> expectedList;
297         TagAsset(AssetOpType::INSERT, GetDownloadWithNullStatus(), a1);
298         TagAsset(AssetOpType::INSERT, GetDownloadWithNullStatus(), a2);
299         TagAsset(AssetOpType::INSERT, GetDownloadWithNullStatus(), a3);
300         TagAsset(AssetOpType::INSERT, GetDownloadWithNullStatus(), a4);
301         expectedList[FIELD_HOUSE] = { a1 };
302         expectedList[FIELD_CARS] = { a2, a3, a4 };
303         ASSERT_TRUE(CheckAssetDownloadList(FIELD_HOUSE, assetList, expectedList));
304         ASSERT_TRUE(CheckAssetDownloadList(FIELD_CARS, assetList, expectedList));
305     }
306 
307     /**
308      * @tc.name: AssetCmpTest003
309      * @tc.desc:
310      * @tc.type: FUNC
311      * @tc.require:
312      * @tc.author: wanyi
313      */
314     HWTEST_F(DistributedDBCloudAssetCompareTest, AssetCmpTest003, TestSize.Level0)
315     {
316         auto assetList = g_cloudSyncer->TestTagAssetsInSingleRecord(DATA_BASELINE, DATA_ASSET_SAME_NAME_BUT_CHANGE);
317         std::map<std::string, Assets> expectedList;
318         TagAsset(AssetOpType::UPDATE, AssetStatus::DOWNLOADING, a1);
319         expectedList[FIELD_HOUSE] = { a1 };
320         expectedList[FIELD_CARS] = { a2, a3, a4 };
321         ASSERT_TRUE(CheckAssetDownloadList(FIELD_HOUSE, assetList, expectedList));
322         ASSERT_TRUE(CheckAssetDownloadList(FIELD_CARS, assetList, expectedList));
323     }
324 
325     /**
326      * @tc.name: AssetCmpTest004
327      * @tc.desc:
328      * @tc.type: FUNC
329      * @tc.require:
330      * @tc.author: wanyi
331      */
332     HWTEST_F(DistributedDBCloudAssetCompareTest, AssetCmpTest004, TestSize.Level0)
333     {
334         auto assetList = g_cloudSyncer->TestTagAssetsInSingleRecord(
335             DATA_BASELINE, DATA_ASSETS_SAME_NAME_PARTIALLY_CHANGED);
336         std::map<std::string, Assets> expectedList;
337         TagAsset(AssetOpType::UPDATE, AssetStatus::DOWNLOADING, a3);
338         expectedList[FIELD_HOUSE] = {};
339         expectedList[FIELD_CARS] = { a2, a3, a4 };
340         ASSERT_TRUE(CheckAssetDownloadList(FIELD_HOUSE, assetList, expectedList));
341         ASSERT_TRUE(CheckAssetDownloadList(FIELD_CARS, assetList, expectedList));
342     }
343 
344     /**
345      * @tc.name: AssetCmpTest005
346      * @tc.desc:
347      * @tc.type: FUNC
348      * @tc.require:
349      * @tc.author: wanyi
350      */
351     HWTEST_F(DistributedDBCloudAssetCompareTest, AssetCmpTest005, TestSize.Level0)
352     {
353         auto assetList = g_cloudSyncer->TestTagAssetsInSingleRecord(
354             DATA_BASELINE, DATA_ALL_SAME);
355         std::map<std::string, Assets> expectedList;
356         expectedList[FIELD_HOUSE] = {};
357         expectedList[FIELD_CARS] = { a2, a3, a4 };
358         ASSERT_TRUE(CheckAssetDownloadList(FIELD_HOUSE, assetList, expectedList));
359         ASSERT_TRUE(CheckAssetDownloadList(FIELD_CARS, assetList, expectedList));
360     }
361 
362     /**
363      * @tc.name: AssetCmpTest006
364      * @tc.desc:
365      * @tc.type: FUNC
366      * @tc.require:
367      * @tc.author: wanyi
368      */
369     HWTEST_F(DistributedDBCloudAssetCompareTest, AssetCmpTest006, TestSize.Level0)
370     {
371         auto assetList = g_cloudSyncer->TestTagAssetsInSingleRecord(
372             DATA_BASELINE, DATA_ASSETS_MORE_FIELD);
373         std::map<std::string, Assets> expectedList;
374         TagAsset(AssetOpType::DELETE, AssetStatus::DOWNLOADING, a5);
375         expectedList[FIELD_HOUSE] = {};
376         expectedList[FIELD_CARS] = { a2, a3, a4, a5 };
377         ASSERT_TRUE(CheckAssetDownloadList(FIELD_HOUSE, assetList, expectedList));
378         ASSERT_TRUE(CheckAssetDownloadList(FIELD_CARS, assetList, expectedList));
379     }
380 
381     /**
382      * @tc.name: AssetCmpTest007
383      * @tc.desc:
384      * @tc.type: FUNC
385      * @tc.require:
386      * @tc.author: wanyi
387      */
388     HWTEST_F(DistributedDBCloudAssetCompareTest, AssetCmpTest007, TestSize.Level0)
389     {
390         auto assetList = g_cloudSyncer->TestTagAssetsInSingleRecord(
391             DATA_BASELINE, DATA_ASSETS_DIFFERENT_FIELD);
392         std::map<std::string, Assets> expectedList;
393         TagAsset(AssetOpType::DELETE, AssetStatus::DOWNLOADING, a5);
394         TagAsset(AssetOpType::INSERT, GetDownloadWithNullStatus(), a4);
395         expectedList[FIELD_HOUSE] = {};
396         expectedList[FIELD_CARS] = { a2, a3, a5, a4 };
397         ASSERT_TRUE(CheckAssetDownloadList(FIELD_HOUSE, assetList, expectedList));
398         ASSERT_TRUE(CheckAssetDownloadList(FIELD_CARS, assetList, expectedList));
399     }
400 
401     /**
402      * @tc.name: AssetCmpTest008
403      * @tc.desc:
404      * @tc.type: FUNC
405      * @tc.require:
406      * @tc.author: wanyi
407      */
408     HWTEST_F(DistributedDBCloudAssetCompareTest, AssetCmpTest008, TestSize.Level0)
409     {
410         auto assetList = g_cloudSyncer->TestTagAssetsInSingleRecord(
411             DATA_BASELINE, DATA_ASSETS_DIFFERENT_CHANGED_FIELD);
412         std::map<std::string, Assets> expectedList;
413         TagAsset(AssetOpType::UPDATE, AssetStatus::DOWNLOADING, a3);
414         TagAsset(AssetOpType::DELETE, AssetStatus::DOWNLOADING, a5);
415         TagAsset(AssetOpType::INSERT, GetDownloadWithNullStatus(), a4);
416         expectedList[FIELD_HOUSE] = {};
417         expectedList[FIELD_CARS] = { a2, a3, a5, a4 };
418         ASSERT_TRUE(CheckAssetDownloadList(FIELD_HOUSE, assetList, expectedList));
419         ASSERT_TRUE(CheckAssetDownloadList(FIELD_CARS, assetList, expectedList));
420     }
421 
422     /**
423      * @tc.name: AssetCmpTest009
424      * @tc.desc:
425      * @tc.type: FUNC
426      * @tc.require:
427      * @tc.author: wanyi
428      */
429     HWTEST_F(DistributedDBCloudAssetCompareTest, AssetCmpTest009, TestSize.Level0)
430     {
431         auto assetList = g_cloudSyncer->TestTagAssetsInSingleRecord(
432             DATA_BASELINE, DATA_ASSETS_SAME_NAME_ALL_CHANGED);
433         std::map<std::string, Assets> expectedList;
434         TagAsset(AssetOpType::UPDATE, AssetStatus::DOWNLOADING, a1);
435         TagAsset(AssetOpType::UPDATE, AssetStatus::DOWNLOADING, a2);
436         TagAsset(AssetOpType::UPDATE, AssetStatus::DOWNLOADING, a3);
437         TagAsset(AssetOpType::UPDATE, AssetStatus::DOWNLOADING, a4);
438         expectedList[FIELD_HOUSE] = { a1 };
439         expectedList[FIELD_CARS] = { a2, a3, a4 };
440         ASSERT_TRUE(CheckAssetDownloadList(FIELD_HOUSE, assetList, expectedList));
441         ASSERT_TRUE(CheckAssetDownloadList(FIELD_CARS, assetList, expectedList));
442     }
443 
444     /**
445      * @tc.name: AssetCmpTest010
446      * @tc.desc:
447      * @tc.type: FUNC
448      * @tc.require:
449      * @tc.author: wanyi
450      */
451     HWTEST_F(DistributedDBCloudAssetCompareTest, AssetCmpTest010, TestSize.Level0)
452     {
453         auto assetList = g_cloudSyncer->TestTagAssetsInSingleRecord(
454             DATA_EMPTY_ASSET, DATA_BASELINE);
455         std::map<std::string, Assets> expectedList;
456         TagAsset(AssetOpType::DELETE, AssetStatus::DOWNLOADING, a1);
457         TagAsset(AssetOpType::DELETE, AssetStatus::DOWNLOADING, a2);
458         TagAsset(AssetOpType::DELETE, AssetStatus::DOWNLOADING, a3);
459         TagAsset(AssetOpType::DELETE, AssetStatus::DOWNLOADING, a4);
460         expectedList[FIELD_HOUSE] = { a1 };
461         expectedList[FIELD_CARS] = { a2, a3, a4 };
462         ASSERT_TRUE(CheckAssetDownloadList(FIELD_HOUSE, assetList, expectedList));
463         ASSERT_TRUE(CheckAssetDownloadList(FIELD_CARS, assetList, expectedList));
464     }
465 
466     /**
467      * @tc.name: AssetCmpTest011
468      * @tc.desc:
469      * @tc.type: FUNC
470      * @tc.require:
471      * @tc.author: wanyi
472      */
473     HWTEST_F(DistributedDBCloudAssetCompareTest, AssetCmpTest011, TestSize.Level0)
474     {
475         auto assetList = g_cloudSyncer->TestTagAssetsInSingleRecord(
476             DATA_EMPTY_ASSET, DATA_ASSETS_ASSET_SAME_NAME);
477         std::map<std::string, Assets> expectedList;
478         TagAsset(AssetOpType::DELETE, AssetStatus::DOWNLOADING, a1);
479         TagAsset(AssetOpType::DELETE, AssetStatus::DOWNLOADING, a2);
480         TagAsset(AssetOpType::DELETE, AssetStatus::DOWNLOADING, a3);
481         expectedList[FIELD_HOUSE] = { a1 };
482         expectedList[FIELD_CARS] = { a1, a2, a3 };
483         ASSERT_TRUE(CheckAssetDownloadList(FIELD_HOUSE, assetList, expectedList));
484         ASSERT_TRUE(CheckAssetDownloadList(FIELD_CARS, assetList, expectedList));
485     }
486 
487     /**
488      * @tc.name: AssetCmpTest012
489      * @tc.desc:
490      * @tc.type: FUNC
491      * @tc.require:
492      * @tc.author: wanyi
493      */
494     HWTEST_F(DistributedDBCloudAssetCompareTest, AssetCmpTest012, TestSize.Level0)
495     {
496         auto assetList = g_cloudSyncer->TestTagAssetsInSingleRecord(
497             DATA_EMPTY_ASSET, DATA_ASSETS_ASSET_SAME_NAME);
498         std::map<std::string, Assets> expectedList;
499         TagAsset(AssetOpType::DELETE, AssetStatus::DOWNLOADING, a1);
500         TagAsset(AssetOpType::DELETE, AssetStatus::DOWNLOADING, a2);
501         TagAsset(AssetOpType::DELETE, AssetStatus::DOWNLOADING, a3);
502         expectedList[FIELD_HOUSE] = { a1 };
503         expectedList[FIELD_CARS] = { a1, a2, a3 };
504         ASSERT_TRUE(CheckAssetDownloadList(FIELD_HOUSE, assetList, expectedList));
505         ASSERT_TRUE(CheckAssetDownloadList(FIELD_CARS, assetList, expectedList));
506     }
507 
508     /**
509      * @tc.name: AssetCmpTest013
510      * @tc.desc:
511      * @tc.type: FUNC
512      * @tc.require:
513      * @tc.author: wanyi
514      */
515     HWTEST_F(DistributedDBCloudAssetCompareTest, AssetCmpTest013, TestSize.Level0)
516     {
517         auto assetList = g_cloudSyncer->TestTagAssetsInSingleRecord(
518             DATA_BASELINE, DATA_ASSET_IN_ASSETS);
519         std::map<std::string, Assets> expectedList;
520         TagAsset(AssetOpType::NO_CHANGE, AssetStatus::DOWNLOADING, a1);
521         TagAsset(AssetOpType::NO_CHANGE, AssetStatus::DOWNLOADING, a2);
522         TagAsset(AssetOpType::NO_CHANGE, AssetStatus::DOWNLOADING, a3);
523         TagAsset(AssetOpType::NO_CHANGE, AssetStatus::DOWNLOADING, a4);
524         a2.status = static_cast<uint32_t>(AssetStatus::NORMAL);
525         a3.status = static_cast<uint32_t>(AssetStatus::NORMAL);
526         a4.status = static_cast<uint32_t>(AssetStatus::NORMAL);
527         expectedList[FIELD_CARS] = {a2, a3, a4};
528         ASSERT_TRUE(CheckAssetDownloadList(FIELD_HOUSE, assetList, expectedList));
529         ASSERT_TRUE(CheckAssetDownloadList(FIELD_CARS, assetList, expectedList));
530     }
531 
532     /**
533      * @tc.name: AssetCmpTest014
534      * @tc.desc:
535      * @tc.type: FUNC
536      * @tc.require:
537      * @tc.author: wanyi
538      */
539     HWTEST_F(DistributedDBCloudAssetCompareTest, AssetCmpTest014, TestSize.Level0)
540     {
541         auto assetList = g_cloudSyncer->TestTagAssetsInSingleRecord(
542             DATA_BASELINE, DATA_NULL_ASSETS);
543         std::map<std::string, Assets> expectedList;
544         TagAsset(AssetOpType::NO_CHANGE, AssetStatus::DOWNLOADING, a1);
545         TagAsset(AssetOpType::INSERT, GetDownloadWithNullStatus(), a2);
546         TagAsset(AssetOpType::INSERT, GetDownloadWithNullStatus(), a3);
547         TagAsset(AssetOpType::INSERT, GetDownloadWithNullStatus(), a4);
548         expectedList[FIELD_HOUSE] = {};
549         expectedList[FIELD_CARS] = { a2, a3, a4 };
550         ASSERT_TRUE(CheckAssetDownloadList(FIELD_HOUSE, assetList, expectedList));
551         ASSERT_TRUE(CheckAssetDownloadList(FIELD_CARS, assetList, expectedList));
552     }
553 
554 
555     /**
556      * @tc.name: AssetCmpTest015
557      * @tc.desc:
558      * @tc.type: FUNC
559      * @tc.require:
560      * @tc.author: wanyi
561      */
562     HWTEST_F(DistributedDBCloudAssetCompareTest, AssetCmpTest015, TestSize.Level0)
563     {
564         auto assetList = g_cloudSyncer->TestTagAssetsInSingleRecord(DATA_ASSET_SAME_NAME_BUT_CHANGE, DATA_BASELINE);
565         std::map<std::string, Assets> expectedList;
566         TagAsset(AssetOpType::UPDATE, AssetStatus::DOWNLOADING, a1Changed);
567         expectedList[FIELD_HOUSE] = { a1Changed };
568         expectedList[FIELD_CARS] = {a2, a3, a4};
569         ASSERT_TRUE(CheckAssetDownloadList(FIELD_HOUSE, assetList, expectedList));
570         ASSERT_TRUE(CheckAssetDownloadList(FIELD_CARS, assetList, expectedList));
571     }
572 
573     /**
574      * @tc.name: AssetCmpTest016
575      * @tc.desc:
576      * @tc.type: FUNC
577      * @tc.require:
578      * @tc.author: wanyi
579      */
580     HWTEST_F(DistributedDBCloudAssetCompareTest, AssetCmpTest016, TestSize.Level0)
581     {
582         auto assetList = g_cloudSyncer->TestTagAssetsInSingleRecord(DATA_BASELINE, DATA_ASSET_SAME_NAME_BUT_CHANGE);
583         EXPECT_EQ(std::get<Asset>(DATA_BASELINE[FIELD_HOUSE]).flag, static_cast<uint32_t>(AssetOpType::UPDATE));
584     }
585 
586     /**
587      * @tc.name: AssetCmpTest017
588      * @tc.desc:
589      * @tc.type: FUNC
590      * @tc.require:
591      * @tc.author: wanyi
592      */
593     HWTEST_F(DistributedDBCloudAssetCompareTest, AssetCmpTest017, TestSize.Level0)
594     {
595         auto assetList = g_cloudSyncer->TestTagAssetsInSingleRecord(
596             DATA_BASELINE, DATA_ASSETS_SAME_NAME_PARTIALLY_CHANGED, true);
597         EXPECT_EQ(std::get<Assets>(DATA_BASELINE[FIELD_CARS])[0].status, AssetStatus::NORMAL);
598         EXPECT_EQ(std::get<Assets>(DATA_BASELINE[FIELD_CARS])[1].status, AssetStatus::UPDATE);
599         EXPECT_EQ(std::get<Assets>(DATA_BASELINE[FIELD_CARS])[2].status, AssetStatus::NORMAL);
600     }
601 
602     /**
603      * @tc.name: AssetCmpTest018
604      * @tc.desc:
605      * @tc.type: FUNC
606      * @tc.require:
607      * @tc.author: wanyi
608      */
609     HWTEST_F(DistributedDBCloudAssetCompareTest, AssetCmpTest018, TestSize.Level0)
610     {
611         auto assetList = g_cloudSyncer->TestTagAssetsInSingleRecord(
612             DATA_BASELINE, DATA_EMPTY, true);
613         EXPECT_EQ(std::get<Asset>(DATA_BASELINE[FIELD_HOUSE]).status, AssetStatus::INSERT);
614         EXPECT_EQ(std::get<Assets>(DATA_BASELINE[FIELD_CARS])[0].status, AssetStatus::INSERT);
615         EXPECT_EQ(std::get<Assets>(DATA_BASELINE[FIELD_CARS])[1].status, AssetStatus::INSERT);
616         EXPECT_EQ(std::get<Assets>(DATA_BASELINE[FIELD_CARS])[2].status, AssetStatus::INSERT);
617     }
618 
619     /**
620      * @tc.name: AssetCmpTest019
621      * @tc.desc:
622      * @tc.type: FUNC
623      * @tc.require:
624      * @tc.author: wanyi
625      */
626     HWTEST_F(DistributedDBCloudAssetCompareTest, AssetCmpTest019, TestSize.Level0)
627     {
628         auto assetList = g_cloudSyncer->TestTagAssetsInSingleRecord(
629             DATA_EMPTY, DATA_BASELINE, true);
630         EXPECT_EQ(std::get<Assets>(DATA_EMPTY[FIELD_CARS])[0].status, AssetStatus::DELETE | AssetStatus::HIDDEN);
631         EXPECT_EQ(std::get<Assets>(DATA_EMPTY[FIELD_CARS])[1].status, AssetStatus::DELETE | AssetStatus::HIDDEN);
632         EXPECT_EQ(std::get<Assets>(DATA_EMPTY[FIELD_CARS])[2].status, AssetStatus::DELETE | AssetStatus::HIDDEN);
633     }
634 
635     /**
636      * @tc.name: AssetCmpTest020
637      * @tc.desc:
638      * @tc.type: FUNC
639      * @tc.require:
640      * @tc.author: wanyi
641      */
642     HWTEST_F(DistributedDBCloudAssetCompareTest, AssetCmpTest020, TestSize.Level0)
643     {
644         auto assetList = g_cloudSyncer->TestTagAssetsInSingleRecord(
645             DATA_ALL_NULL_ASSETS, DATA_BASELINE, false);
646         EXPECT_EQ(std::get<Asset>(DATA_BASELINE[FIELD_HOUSE]).flag, static_cast<uint32_t>(AssetOpType::DELETE));
647         EXPECT_EQ(std::get<Assets>(DATA_ALL_NULL_ASSETS[FIELD_CARS])[0].flag,
648             static_cast<uint32_t>(AssetOpType::DELETE));
649         EXPECT_EQ(std::get<Assets>(DATA_ALL_NULL_ASSETS[FIELD_CARS])[1].flag,
650             static_cast<uint32_t>(AssetOpType::DELETE));
651         EXPECT_EQ(std::get<Assets>(DATA_ALL_NULL_ASSETS[FIELD_CARS])[2].flag,
652             static_cast<uint32_t>(AssetOpType::DELETE));
653 
654         std::map<std::string, Assets> expectedList;
655         TagAsset(AssetOpType::DELETE, AssetStatus::DOWNLOADING, a1);
656         TagAsset(AssetOpType::DELETE, AssetStatus::DOWNLOADING, a2);
657         TagAsset(AssetOpType::DELETE, AssetStatus::DOWNLOADING, a3);
658         TagAsset(AssetOpType::DELETE, AssetStatus::DOWNLOADING, a4);
659         expectedList[FIELD_HOUSE] = { a1 };
660         expectedList[FIELD_CARS] = { a2, a3, a4 };
661         ASSERT_TRUE(CheckAssetDownloadList(FIELD_HOUSE, assetList, expectedList));
662         ASSERT_TRUE(CheckAssetDownloadList(FIELD_CARS, assetList, expectedList));
663     }
664 
665     /**
666      * @tc.name: AssetCmpTest021
667      * @tc.desc:
668      * @tc.type: FUNC
669      * @tc.require:
670      * @tc.author: wanyi
671      */
672     HWTEST_F(DistributedDBCloudAssetCompareTest, AssetCmpTest021, TestSize.Level0)
673     {
674         auto assetList = g_cloudSyncer->TestTagAssetsInSingleRecord(
675             DATA_ALL_NULL_ASSETS, DATA_ALL_NULL_ASSETS, true);
676         ASSERT_TRUE(DATA_ALL_NULL_ASSETS[FIELD_HOUSE].index() == TYPE_INDEX<Nil>);
677         ASSERT_TRUE(DATA_ALL_NULL_ASSETS[FIELD_CARS].index() == TYPE_INDEX<Nil>);
678 
679         std::map<std::string, Assets> expectedList;
680         expectedList[FIELD_HOUSE] = {};
681         expectedList[FIELD_CARS] = {};
682         ASSERT_TRUE(CheckAssetDownloadList(FIELD_HOUSE, assetList, expectedList));
683         ASSERT_TRUE(CheckAssetDownloadList(FIELD_CARS, assetList, expectedList));
684     }
685 
686     /**
687      * @tc.name: AssetCmpTest022
688      * @tc.desc:
689      * @tc.type: FUNC
690      * @tc.require:
691      * @tc.author: wanyi
692      */
693     HWTEST_F(DistributedDBCloudAssetCompareTest, AssetCmpTest022, TestSize.Level0)
694     {
695         auto assetList = g_cloudSyncer->TestTagAssetsInSingleRecord(
696             DATA_BASELINE, DATA_ALL_NULL_ASSETS, false);
697         EXPECT_EQ(std::get<Asset>(DATA_BASELINE[FIELD_HOUSE]).flag, static_cast<uint32_t>(AssetOpType::INSERT));
698         EXPECT_EQ(std::get<Assets>(DATA_BASELINE[FIELD_CARS])[0].flag, static_cast<uint32_t>(AssetOpType::INSERT));
699         EXPECT_EQ(std::get<Assets>(DATA_BASELINE[FIELD_CARS])[1].flag, static_cast<uint32_t>(AssetOpType::INSERT));
700         EXPECT_EQ(std::get<Assets>(DATA_BASELINE[FIELD_CARS])[2].flag, static_cast<uint32_t>(AssetOpType::INSERT));
701 
702         std::map<std::string, Assets> expectedList;
703         TagAsset(AssetOpType::INSERT,
704             static_cast<AssetStatus>(AssetStatus::DOWNLOADING | AssetStatus::DOWNLOAD_WITH_NULL), a1);
705         TagAsset(AssetOpType::INSERT,
706             static_cast<AssetStatus>(AssetStatus::DOWNLOADING | AssetStatus::DOWNLOAD_WITH_NULL), a2);
707         TagAsset(AssetOpType::INSERT,
708             static_cast<AssetStatus>(AssetStatus::DOWNLOADING | AssetStatus::DOWNLOAD_WITH_NULL), a3);
709         TagAsset(AssetOpType::INSERT,
710             static_cast<AssetStatus>(AssetStatus::DOWNLOADING | AssetStatus::DOWNLOAD_WITH_NULL), a4);
711         expectedList[FIELD_HOUSE] = { a1 };
712         expectedList[FIELD_CARS] = { a2, a3, a4 };
713         ASSERT_TRUE(CheckAssetDownloadList(FIELD_HOUSE, assetList, expectedList));
714         ASSERT_TRUE(CheckAssetDownloadList(FIELD_CARS, assetList, expectedList));
715     }
716 
717     /**
718      * @tc.name: AssetCmpTest023
719      * @tc.desc:
720      * @tc.type: FUNC
721      * @tc.require:
722      * @tc.author: wanyi
723      */
724     HWTEST_F(DistributedDBCloudAssetCompareTest, AssetCmpTest023, TestSize.Level0)
725     {
726         auto assetList = g_cloudSyncer->TestTagAssetsInSingleRecord(
727             DATA_ASSET_SAME_NAME_BUT_CHANGE, DATA_BASELINE, true);
728         EXPECT_EQ(std::get<Asset>(DATA_ASSET_SAME_NAME_BUT_CHANGE[FIELD_HOUSE]).status,
729             AssetStatus::UPDATE);
730         EXPECT_EQ(std::get<Assets>(DATA_ASSET_SAME_NAME_BUT_CHANGE[FIELD_CARS])[0].status,
731             AssetStatus::NORMAL);
732         EXPECT_EQ(std::get<Assets>(DATA_ASSET_SAME_NAME_BUT_CHANGE[FIELD_CARS])[1].status,
733             AssetStatus::NORMAL);
734         EXPECT_EQ(std::get<Assets>(DATA_ASSET_SAME_NAME_BUT_CHANGE[FIELD_CARS])[2].status,
735             AssetStatus::NORMAL);
736     }
737 
738     /**
739      * @tc.name: AssetCmpTest024
740      * @tc.desc:
741      * @tc.type: FUNC
742      * @tc.require:
743      * @tc.author: wanyi
744      */
745     HWTEST_F(DistributedDBCloudAssetCompareTest, AssetCmpTest024, TestSize.Level0)
746     {
747         auto assetList = g_cloudSyncer->TestTagAssetsInSingleRecord(
748             DATA_ASSETS_DIFFERENT_CHANGED_FIELD, DATA_BASELINE, true);
749         EXPECT_EQ(std::get<Asset>(DATA_ASSETS_DIFFERENT_CHANGED_FIELD[FIELD_HOUSE]).status,
750             AssetStatus::NORMAL);
751         EXPECT_EQ(std::get<Assets>(DATA_ASSETS_DIFFERENT_CHANGED_FIELD[FIELD_CARS])[0].status,
752             AssetStatus::NORMAL);
753         EXPECT_EQ(std::get<Assets>(DATA_ASSETS_DIFFERENT_CHANGED_FIELD[FIELD_CARS])[1].status,
754             AssetStatus::UPDATE);
755         EXPECT_EQ(std::get<Assets>(DATA_ASSETS_DIFFERENT_CHANGED_FIELD[FIELD_CARS])[2].status,
756             AssetStatus::INSERT);
757         EXPECT_EQ(std::get<Assets>(DATA_ASSETS_DIFFERENT_CHANGED_FIELD[FIELD_CARS])[3].status,
758             AssetStatus::DELETE | AssetStatus::HIDDEN);
759     }
760 
761     /**
762      * @tc.name: AssetCmpTest025
763      * @tc.desc: Cloud device contain a record without assets, local device insert an assets and begin to sync.
764      * CloudAsset will be a record without assets. Local data will be a record with assets.
765      * @tc.type: FUNC
766      * @tc.require:
767      * @tc.author: wanyi
768      */
769     HWTEST_F(DistributedDBCloudAssetCompareTest, AssetCmpTest025, TestSize.Level0)
770     {
771         auto assetList = g_cloudSyncer->TestTagAssetsInSingleRecord(DATA_BASELINE, DATA_NULL_ASSETS, true);
772         EXPECT_EQ(std::get<Asset>(DATA_BASELINE[FIELD_HOUSE]).status, AssetStatus::NORMAL);
773         EXPECT_EQ(std::get<Assets>(DATA_BASELINE[FIELD_CARS])[0].status, AssetStatus::INSERT);
774         EXPECT_EQ(std::get<Assets>(DATA_BASELINE[FIELD_CARS])[1].status, AssetStatus::INSERT);
775         EXPECT_EQ(std::get<Assets>(DATA_BASELINE[FIELD_CARS])[2].status, AssetStatus::INSERT);
776     }
777 
778     /**
779      * @tc.name: AssetCmpTest026
780      * @tc.desc: Cloud device contain a record without assets, local device insert an assets and begin to sync.
781      * CloudAsset will be a record without assets. Local data will be a record with assets.
782      * In this case, record do not contain certain asset column
783      * @tc.type: FUNC
784      * @tc.require:
785      * @tc.author: wanyi
786      */
787     HWTEST_F(DistributedDBCloudAssetCompareTest, AssetCmpTest026, TestSize.Level0)
788     {
789         auto assetList = g_cloudSyncer->TestTagAssetsInSingleRecord(DATA_BASELINE, DATA_EMPTY_ASSETS, true);
790         EXPECT_EQ(std::get<Asset>(DATA_BASELINE[FIELD_HOUSE]).status, AssetStatus::NORMAL);
791         EXPECT_EQ(std::get<Assets>(DATA_BASELINE[FIELD_CARS])[0].status, AssetStatus::INSERT);
792         EXPECT_EQ(std::get<Assets>(DATA_BASELINE[FIELD_CARS])[1].status, AssetStatus::INSERT);
793         EXPECT_EQ(std::get<Assets>(DATA_BASELINE[FIELD_CARS])[2].status, AssetStatus::INSERT);
794     }
795 
796     /**
797      * @tc.name: AssetCmpTest027
798      * @tc.desc:
799      * @tc.type: FUNC
800      * @tc.require:
801      * @tc.author: wanyi
802      */
803     HWTEST_F(DistributedDBCloudAssetCompareTest, AssetCmpTest027, TestSize.Level0)
804     {
805         auto assetList = g_cloudSyncer->TestTagAssetsInSingleRecord(
806             DATA_UPDATE_DELTE_NOCHANGE_INSERT, DATA_BASELINE, false);
807         EXPECT_EQ(std::get<Assets>(DATA_UPDATE_DELTE_NOCHANGE_INSERT[FIELD_CARS])[0].flag,
808             static_cast<uint32_t>(AssetOpType::UPDATE));
809         EXPECT_EQ(std::get<Assets>(DATA_UPDATE_DELTE_NOCHANGE_INSERT[FIELD_CARS])[1].flag,
810             static_cast<uint32_t>(AssetOpType::NO_CHANGE));
811         EXPECT_EQ(std::get<Assets>(DATA_UPDATE_DELTE_NOCHANGE_INSERT[FIELD_CARS])[2].flag,
812             static_cast<uint32_t>(AssetOpType::INSERT));
813         EXPECT_EQ(std::get<Assets>(DATA_UPDATE_DELTE_NOCHANGE_INSERT[FIELD_CARS])[3].flag,
814             static_cast<uint32_t>(AssetOpType::DELETE));
815     }
816 
817     /**
818      * @tc.name: AssetCmpTest028
819      * @tc.desc: Two same name asset appears in the assets field, this situation is not allowed
820      * @tc.type: FUNC
821      * @tc.require:
822      * @tc.author: wanyi
823      */
824     HWTEST_F(DistributedDBCloudAssetCompareTest, AssetCmpTest028, TestSize.Level0)
825     {
826         auto assetList = g_cloudSyncer->TestTagAssetsInSingleRecord(
827             DATA_ALL_NULL_ASSETS, DATA_BASELINE, true);
828         EXPECT_EQ(std::get<Assets>(DATA_ALL_NULL_ASSETS[FIELD_CARS])[0].status,
829             AssetStatus::DELETE | AssetStatus::HIDDEN);
830         EXPECT_EQ(std::get<Assets>(DATA_ALL_NULL_ASSETS[FIELD_CARS])[1].status,
831             AssetStatus::DELETE | AssetStatus::HIDDEN);
832         EXPECT_EQ(std::get<Assets>(DATA_ALL_NULL_ASSETS[FIELD_CARS])[2].status,
833             AssetStatus::DELETE | AssetStatus::HIDDEN);
834     }
835 
836     /**
837      * @tc.name: AssetCmpTest029
838      * @tc.desc: Two same name asset appears in the assets field, this situation is not allowed
839      * @tc.type: FUNC
840      * @tc.require:
841      * @tc.author: wanyi
842      */
843     HWTEST_F(DistributedDBCloudAssetCompareTest, AssetCmpTest029, TestSize.Level0)
844     {
845         Field field1 = { FIELD_HOUSE, TYPE_INDEX<Asset> };
846         Field field2 = { FIELD_CARS, TYPE_INDEX<Assets> };
847         std::vector<Field> assetFields = { field1, field2 };
848         ASSERT_TRUE(g_cloudSyncer->TestIsDataContainDuplicateAsset(assetFields, DATA_SAME_NAME_ASSETS));
849         ASSERT_TRUE(g_cloudSyncer->TestIsDataContainDuplicateAsset(assetFields, DATA_BASELINE) == false);
850     }
851 
852     /**
853      * @tc.name: AssetCmpTest030
854      * @tc.desc: Check operator == in the asset structure
855      * @tc.type: FUNC
856      * @tc.require:
857      * @tc.author: chenchaohao
858      */
859     HWTEST_F(DistributedDBCloudAssetCompareTest, AssetCmpTest030, TestSize.Level0)
860     {
861         Asset asset = GenAsset("mansion", "mansion1");
862         EXPECT_TRUE(std::get<Asset>(DATA_BASELINE[FIELD_HOUSE]) == asset);
863     }
864 
865     /**
866      * @tc.name: AssetOperation001
867      * @tc.desc: Different opType with end download action and assets
868      * @tc.type: FUNC
869      * @tc.require:
870      * @tc.author: zhangqiquan
871      */
872     HWTEST_F(DistributedDBCloudAssetCompareTest, AssetOperation001, TestSize.Level0)
873     {
874         VBucket cacheAssets;
875         VBucket dbAssets;
876         Asset asset;
877         asset.status = AssetStatus::DOWNLOADING;
878         asset.name = "name";
879         cacheAssets["field"] = asset;
880         dbAssets["field"] = asset;
881         // check both downloading after download
882         auto res = AssetOperationUtils::CalAssetOperation(cacheAssets, dbAssets,
883             AssetOperationUtils::CloudSyncAction::END_DOWNLOAD);
884         EXPECT_EQ(res["field"].size(), 1u);
885         EXPECT_EQ(res["field"][asset.name], AssetOperationUtils::AssetOpType::HANDLE);
886         // status mask download with null
887         asset.status = (static_cast<uint32_t>(AssetStatus::DOWNLOADING) |
888             static_cast<uint32_t>(AssetStatus::DOWNLOAD_WITH_NULL));
889         cacheAssets["field"] = asset;
890         dbAssets["field"] = asset;
891         res = AssetOperationUtils::CalAssetOperation(cacheAssets, dbAssets,
892             AssetOperationUtils::CloudSyncAction::END_DOWNLOAD);
893         EXPECT_EQ(res["field"].size(), 1u);
894         EXPECT_EQ(res["field"][asset.name], AssetOperationUtils::AssetOpType::HANDLE);
895         // if status not equal, not handle
896         asset.status = AssetStatus::UPDATE;
897         dbAssets["field"] = asset;
898         res = AssetOperationUtils::CalAssetOperation(cacheAssets, dbAssets,
899             AssetOperationUtils::CloudSyncAction::END_DOWNLOAD);
900         EXPECT_EQ(res["field"][asset.name], AssetOperationUtils::AssetOpType::NOT_HANDLE);
901         // if asset not exist, not handle
902         dbAssets.erase("field");
903         res = AssetOperationUtils::CalAssetOperation(cacheAssets, dbAssets,
904             AssetOperationUtils::CloudSyncAction::END_DOWNLOAD);
905         EXPECT_EQ(res["field"][asset.name], AssetOperationUtils::AssetOpType::NOT_HANDLE);
906     }
907 
908     /**
909      * @tc.name: AssetOperation002
910      * @tc.desc: Different opType with start download action and assets
911      * @tc.type: FUNC
912      * @tc.require:
913      * @tc.author: zhangqiquan
914      */
915     HWTEST_F(DistributedDBCloudAssetCompareTest, AssetOperation002, TestSize.Level0)
916     {
917         VBucket cacheAssets;
918         VBucket dbAssets;
919         Asset asset;
920         asset.name = "name";
921         asset.status = AssetStatus::DOWNLOADING;
922         cacheAssets["field"] = asset;
923         dbAssets["field"] = asset;
924         // check both downloading before download
925         auto res = AssetOperationUtils::CalAssetOperation(cacheAssets, dbAssets,
926             AssetOperationUtils::CloudSyncAction::START_DOWNLOAD);
927         EXPECT_EQ(res["field"].size(), 1u);
928         EXPECT_EQ(res["field"][asset.name], AssetOperationUtils::AssetOpType::HANDLE);
929         // if status not equal, not handle
930         asset.status = AssetStatus::UPDATE;
931         dbAssets["field"] = asset;
932         res = AssetOperationUtils::CalAssetOperation(cacheAssets, dbAssets,
933             AssetOperationUtils::CloudSyncAction::START_DOWNLOAD);
934         EXPECT_EQ(res["field"][asset.name], AssetOperationUtils::AssetOpType::NOT_HANDLE);
935         // if db asset not exist, not handle
936         dbAssets.erase("field");
937         res = AssetOperationUtils::CalAssetOperation(cacheAssets, dbAssets,
938             AssetOperationUtils::CloudSyncAction::START_DOWNLOAD);
939         EXPECT_EQ(res["field"][asset.name], AssetOperationUtils::AssetOpType::NOT_HANDLE);
940         // if db asset not exist but cache is delete, handle
941         asset.flag = static_cast<uint32_t>(AssetOpType::DELETE);
942         cacheAssets["field"] = asset;
943         res = AssetOperationUtils::CalAssetOperation(cacheAssets, dbAssets,
944             AssetOperationUtils::CloudSyncAction::START_DOWNLOAD);
945         EXPECT_EQ(res["field"][asset.name], AssetOperationUtils::AssetOpType::HANDLE);
946     }
947 
948     /**
949      * @tc.name: AssetOperation003
950      * @tc.desc: Different opType with start upload action and assets
951      * @tc.type: FUNC
952      * @tc.require:
953      * @tc.author: zhangqiquan
954      */
955     HWTEST_F(DistributedDBCloudAssetCompareTest, AssetOperation003, TestSize.Level0)
956     {
957         Asset asset;
958         VBucket cacheAssets;
959         VBucket dbAssets;
960         asset.name = "name";
961         asset.status = AssetStatus::UPDATE;
962         cacheAssets["field"] = asset;
963         dbAssets["field"] = asset;
964         // check both update before upload
965         auto res = AssetOperationUtils::CalAssetOperation(cacheAssets, dbAssets,
966             AssetOperationUtils::CloudSyncAction::START_UPLOAD);
967         EXPECT_EQ(res["field"].size(), 1u);
968         EXPECT_EQ(res["field"][asset.name], AssetOperationUtils::AssetOpType::HANDLE);
969         // if status not equal, not handle
970         asset.status = AssetStatus::DELETE;
971         dbAssets["field"] = asset;
972         res = AssetOperationUtils::CalAssetOperation(cacheAssets, dbAssets,
973             AssetOperationUtils::CloudSyncAction::START_UPLOAD);
974         EXPECT_EQ(res["field"][asset.name], AssetOperationUtils::AssetOpType::NOT_HANDLE);
975         // if asset not exist, not handle
976         dbAssets.erase("field");
977         res = AssetOperationUtils::CalAssetOperation(cacheAssets, dbAssets,
978             AssetOperationUtils::CloudSyncAction::START_UPLOAD);
979         EXPECT_EQ(res["field"][asset.name], AssetOperationUtils::AssetOpType::NOT_HANDLE);
980     }
981 
982     /**
983      * @tc.name: AssetOperation004
984      * @tc.desc: Different opType with start upload action and assets
985      * @tc.type: FUNC
986      * @tc.require:
987      * @tc.author: zhangqiquan
988      */
989     HWTEST_F(DistributedDBCloudAssetCompareTest, AssetOperation004, TestSize.Level0)
990     {
991         Asset asset;
992         VBucket cacheAssets;
993         VBucket dbAssets;
994         asset.name = "name";
995         asset.status = (static_cast<uint32_t>(AssetStatus::UPDATE) | static_cast<uint32_t>(AssetStatus::UPLOADING));
996         cacheAssets["field"] = asset;
997         dbAssets["field"] = asset;
998         // check both UPLOADING after upload
999         auto res = AssetOperationUtils::CalAssetOperation(cacheAssets, dbAssets,
1000             AssetOperationUtils::CloudSyncAction::END_UPLOAD);
1001         EXPECT_EQ(res["field"].size(), 1u);
1002         EXPECT_EQ(res["field"][asset.name], AssetOperationUtils::AssetOpType::HANDLE);
1003         // if status not equal, not handle
1004         asset.status = AssetStatus::DELETE;
1005         dbAssets["field"] = asset;
1006         res = AssetOperationUtils::CalAssetOperation(cacheAssets, dbAssets,
1007             AssetOperationUtils::CloudSyncAction::END_UPLOAD);
1008         EXPECT_EQ(res["field"][asset.name], AssetOperationUtils::AssetOpType::NOT_HANDLE);
1009         // if asset not exist, not handle
1010         dbAssets.erase("field");
1011         res = AssetOperationUtils::CalAssetOperation(cacheAssets, dbAssets,
1012             AssetOperationUtils::CloudSyncAction::END_UPLOAD);
1013         EXPECT_EQ(res["field"][asset.name], AssetOperationUtils::AssetOpType::NOT_HANDLE);
1014     }
1015 
1016     /**
1017      * @tc.name: SameAssetNotify001
1018      * @tc.desc: Test same asset notify in one batch
1019      * @tc.type: FUNC
1020      * @tc.require:
1021      * @tc.author: zhangqiquan
1022      */
1023     HWTEST_F(DistributedDBCloudAssetCompareTest, SameAssetNotify001, TestSize.Level0)
1024     {
1025         /**
1026          * @tc.steps: step1. prepare two data with same pk
1027          */
1028         ICloudSyncer::SyncParam param;
1029         param.downloadData.opType.push_back(OpType::INSERT);
1030         param.downloadData.opType.push_back(OpType::UPDATE);
1031         const std::string pkField = "pk_asset";
1032         param.changedData.field.push_back(pkField);
1033         VBucket oneRow;
1034         oneRow[pkField] = static_cast<int64_t>(1); // 1 is pk
1035         param.downloadData.data.push_back(oneRow);
1036         param.downloadData.data.push_back(oneRow);
1037         ICloudSyncer::DataInfo dataInfo;
1038         dataInfo.localInfo.logInfo.dataKey = 1;
1039         param.isSinglePrimaryKey = true;
1040         param.pkColNames.push_back(pkField);
1041         /**
1042          * @tc.steps: step2. handle tag assets
1043          * @tc.expected: step2. all type should be INSERT
1044          */
1045         VBucket localAsset;
1046         Key hashKey;
1047         for (size_t i = 0; i < param.downloadData.opType.size(); ++i) {
1048             int errCode = g_cloudSyncer->CallHandleTagAssets(hashKey, dataInfo, i, param, localAsset);
1049             ASSERT_EQ(errCode, E_OK);
1050             auto strategy = std::get<CloudSyncUtils::STRATEGY_INDEX>(param.assetsDownloadList[i]);
1051             EXPECT_EQ(strategy, OpType::INSERT);
1052         }
1053     }
1054 }
1055