• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
16 #include <gtest/gtest.h>
17 
18 #include "cloud/cloud_storage_utils.h"
19 #include "cloud_store_types.h"
20 #include "db_common.h"
21 #include "distributeddb_data_generate_unit_test.h"
22 #include "distributeddb_tools_unit_test.h"
23 #include "icloud_sync_storage_interface.h"
24 #include "mock_relational_sync_able_storage.h"
25 #include "relational_store_instance.h"
26 #include "relational_store_manager.h"
27 #include "relational_sync_able_storage.h"
28 #include "runtime_config.h"
29 #include "sqlite_relational_store.h"
30 #include "storage_proxy.h"
31 #include "virtual_cloud_data_translate.h"
32 
33 using namespace testing::ext;
34 using namespace  DistributedDB;
35 using namespace  DistributedDBUnitTest;
36 
37 namespace {
38     constexpr const char *DB_SUFFIX = ".db";
39     constexpr const char *STORE_ID = "Relational_Store_ID";
40     std::string g_dbDir;
41     std::string g_testDir;
42     std::string g_tableName = "sync_data";
43     std::string g_assetTableName = "asset_sync_data";
44     std::string g_storePath;
45     std::string g_gid = "abcd";
46     DistributedDB::RelationalStoreManager g_mgr(APP_ID, USER_ID);
47     IRelationalStore *g_store = nullptr;
48     RelationalStoreDelegate *g_delegate = nullptr;
49     ICloudSyncStorageInterface *g_cloudStore = nullptr;
50     constexpr const int64_t BASE_MODIFY_TIME = 12345678L;
51     constexpr const int64_t BASE_CREATE_TIME = 12345679L;
52 
53     enum class PrimaryKeyType {
54         NO_PRIMARY_KEY,
55         SINGLE_PRIMARY_KEY,
56         COMPOSITE_PRIMARY_KEY
57     };
58 
59     enum class GidType {
60         GID_EMPTY,
61         GID_MATCH,
62         GID_MISMATCH,
63         GID_INVALID
64     };
65 
66     class DistributedDBCloudSaveCloudDataTest : public testing::Test {
67     public:
68         static void SetUpTestCase(void);
69         static void TearDownTestCase(void);
70         void SetUp() override;
71         void TearDown() override;
72     };
73 
CreatDB()74     void CreatDB()
75     {
76         sqlite3 *db = RelationalTestUtils::CreateDataBase(g_dbDir + STORE_ID + DB_SUFFIX);
77         EXPECT_NE(db, nullptr);
78         EXPECT_EQ(RelationalTestUtils::ExecSql(db, "PRAGMA journal_mode=WAL;"), SQLITE_OK);
79         EXPECT_EQ(sqlite3_close_v2(db), E_OK);
80     }
81 
SetCloudSchema(PrimaryKeyType pkType,bool nullable,bool asset=false)82     void SetCloudSchema(PrimaryKeyType pkType, bool nullable, bool asset = false)
83     {
84         TableSchema tableSchema;
85         bool isIdPk = pkType == PrimaryKeyType::SINGLE_PRIMARY_KEY || pkType == PrimaryKeyType::COMPOSITE_PRIMARY_KEY;
86         Field field1 = { "id", TYPE_INDEX<int64_t>, isIdPk, !isIdPk };
87         Field field2 = { "name", TYPE_INDEX<std::string>, pkType == PrimaryKeyType::COMPOSITE_PRIMARY_KEY, true };
88         Field field3 = { "age", TYPE_INDEX<double>, false, true };
89         Field field4 = { "sex", TYPE_INDEX<bool>, false, nullable };
90         Field field5;
91         if (asset) {
92             field5 = { "image", TYPE_INDEX<Asset>, false, true };
93         } else {
94             field5 = { "image", TYPE_INDEX<Bytes>, false, true };
95         }
96         tableSchema = { g_tableName, g_tableName + "_shared", { field1, field2, field3, field4, field5} };
97         DataBaseSchema dbSchema;
98         dbSchema.tables.push_back(tableSchema);
99         tableSchema = { g_assetTableName, g_assetTableName + "_shared", { field1, field2, field3, field4, field5} };
100         dbSchema.tables.push_back(tableSchema);
101 
102         g_delegate->SetCloudDbSchema(dbSchema);
103     }
104 
PrepareDataBase(const std::string & tableName,PrimaryKeyType pkType,bool nullable=true)105     void PrepareDataBase(const std::string &tableName, PrimaryKeyType pkType, bool nullable = true)
106     {
107         /**
108          * @tc.steps:step1. create table.
109          * @tc.expected: step1. return ok.
110          */
111         sqlite3 *db = RelationalTestUtils::CreateDataBase(g_dbDir + STORE_ID + DB_SUFFIX);
112         EXPECT_NE(db, nullptr);
113         std::string sql;
114         if (pkType == PrimaryKeyType::SINGLE_PRIMARY_KEY) {
115             sql = "create table " + tableName + "(id int primary key, name TEXT, age REAL, sex INTEGER, image BLOB);";
116         } else if (pkType == PrimaryKeyType::NO_PRIMARY_KEY) {
117             sql = "create table " + tableName + "(id int, name TEXT, age REAL, sex INTEGER, image BLOB);";
118         } else {
119             sql = "create table " + tableName + "(id int, name TEXT, age REAL, sex INTEGER, image BLOB," \
120                 " PRIMARY KEY(id, name))";
121         }
122         EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), E_OK);
123 
124         /**
125          * @tc.steps:step2. create distributed table with CLOUD_COOPERATION mode.
126          * @tc.expected: step2. return ok.
127          */
128         EXPECT_EQ(g_delegate->CreateDistributedTable(tableName, DistributedDB::CLOUD_COOPERATION), OK);
129 
130         /**
131          * @tc.steps:step3. insert some row.
132          * @tc.expected: step3. return ok.
133          */
134         if (pkType == PrimaryKeyType::COMPOSITE_PRIMARY_KEY) {
135             sql = "insert into " + tableName + "(id, name, age)" \
136                 " values(1, 'zhangsan1', 10.1), (1, 'zhangsan2', 10.1), (2, 'zhangsan1', 10.0), (3, 'zhangsan3', 30),"
137                 " (4, 'zhangsan4', 40.123), (5, 'zhangsan5', 50.123);";
138         } else {
139             sql = "insert into " + tableName + "(id, name)" \
140                 " values(1, 'zhangsan1'), (2, 'zhangsan2'), (3, 'zhangsan3'), (4, 'zhangsan4'),"
141                 " (5, 'zhangsan5'), (6, 'zhangsan6'), (7, 'zhangsan7');";
142         }
143         EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), E_OK);
144 
145         /**
146          * @tc.steps:step4. preset cloud gid.
147          * @tc.expected: step4. return ok.
148          */
149         for (int i = 0; i < 7; i++) { // update first 7 records
150             if (i == 4) { // 4 is id
151                 sql = "update " + DBCommon::GetLogTableName(tableName) + " set cloud_gid = '" +
152                     g_gid + std::to_string(i) + "', flag = 6 where data_key = " + std::to_string(i + 1);
153             } else {
154                 sql = "update " + DBCommon::GetLogTableName(tableName) + " set cloud_gid = '" +
155                     g_gid + std::to_string(i) + "' where data_key = " + std::to_string(i + 1);
156             }
157             EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), E_OK);
158             if (pkType != PrimaryKeyType::COMPOSITE_PRIMARY_KEY && i == 6) { // 6 is index
159                 sql = "delete from " + tableName + " where id = 7;";
160                 EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), E_OK);
161             }
162         }
163 
164         EXPECT_EQ(sqlite3_close_v2(db), E_OK);
165 
166         SetCloudSchema(pkType, nullable);
167     }
168 
PrepareDataBaseForAsset(const std::string & tableName,bool nullable=true)169     void PrepareDataBaseForAsset(const std::string &tableName, bool nullable = true)
170     {
171         sqlite3 *db = RelationalTestUtils::CreateDataBase(g_dbDir + STORE_ID + DB_SUFFIX);
172         EXPECT_NE(db, nullptr);
173         std::string sql =
174             "create table " + tableName + "(id int, name TEXT, age REAL, sex INTEGER, image BLOB);";
175         EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), E_OK);
176         EXPECT_EQ(g_delegate->CreateDistributedTable(tableName, DistributedDB::CLOUD_COOPERATION), OK);
177 
178         sql = "insert into " + tableName + "(id, name, image) values(1, 'zhangsan1', ?);";
179         sqlite3_stmt *stmt = nullptr;
180         EXPECT_EQ(SQLiteUtils::GetStatement(db, sql, stmt), SQLITE_OK);
181         Asset asset;
182         asset.name = "123";
183         asset.status = static_cast<uint32_t>(AssetStatus::ABNORMAL);
184         VirtualCloudDataTranslate translate;
185         Bytes bytes = translate.AssetToBlob(asset);
186         EXPECT_EQ(SQLiteUtils::BindBlobToStatement(stmt, 1, bytes), E_OK);
187         EXPECT_EQ(SQLiteUtils::StepWithRetry(stmt), SQLiteUtils::MapSQLiteErrno(SQLITE_DONE));
188         int errCode = E_OK;
189         SQLiteUtils::ResetStatement(stmt, true, errCode);
190 
191         EXPECT_EQ(sqlite3_close_v2(db), E_OK);
192         SetCloudSchema(PrimaryKeyType::NO_PRIMARY_KEY, nullable, true);
193     }
194 
InitStoreProp(const std::string & storePath,const std::string & appId,const std::string & userId,RelationalDBProperties & properties)195     void InitStoreProp(const std::string &storePath, const std::string &appId, const std::string &userId,
196         RelationalDBProperties &properties)
197     {
198         properties.SetStringProp(RelationalDBProperties::DATA_DIR, storePath);
199         properties.SetStringProp(RelationalDBProperties::APP_ID, appId);
200         properties.SetStringProp(RelationalDBProperties::USER_ID, userId);
201         properties.SetStringProp(RelationalDBProperties::STORE_ID, STORE_ID);
202         std::string identifier = userId + "-" + appId + "-" + STORE_ID;
203         std::string hashIdentifier = DBCommon::TransferHashString(identifier);
204         properties.SetStringProp(RelationalDBProperties::IDENTIFIER_DATA, hashIdentifier);
205     }
206 
GetRelationalStore()207     const RelationalSyncAbleStorage *GetRelationalStore()
208     {
209         RelationalDBProperties properties;
210         InitStoreProp(g_storePath, APP_ID, USER_ID, properties);
211         int errCode = E_OK;
212         g_store = RelationalStoreInstance::GetDataBase(properties, errCode);
213         if (g_store == nullptr) {
214             LOGE("Get db failed:%d", errCode);
215             return nullptr;
216         }
217         return static_cast<SQLiteRelationalStore *>(g_store)->GetStorageEngine();
218     }
219 
SetUpTestCase(void)220     void DistributedDBCloudSaveCloudDataTest::SetUpTestCase(void)
221     {
222         DistributedDBToolsUnitTest::TestDirInit(g_testDir);
223         LOGD("Test dir is %s", g_testDir.c_str());
224         g_dbDir = g_testDir + "/";
225         g_storePath = g_dbDir + STORE_ID + DB_SUFFIX;
226         DistributedDBToolsUnitTest::RemoveTestDbFiles(g_testDir);
227     }
228 
TearDownTestCase(void)229     void DistributedDBCloudSaveCloudDataTest::TearDownTestCase(void)
230     {
231     }
232 
SetUp()233     void DistributedDBCloudSaveCloudDataTest::SetUp()
234     {
235         CreatDB();
236         DBStatus status = g_mgr.OpenStore(g_dbDir + STORE_ID + DB_SUFFIX, STORE_ID, {}, g_delegate);
237         EXPECT_EQ(status, OK);
238         ASSERT_NE(g_delegate, nullptr);
239         g_cloudStore = (ICloudSyncStorageInterface *) GetRelationalStore();
240         ASSERT_NE(g_cloudStore, nullptr);
241     }
242 
TearDown()243     void DistributedDBCloudSaveCloudDataTest::TearDown()
244     {
245         RefObject::DecObjRef(g_store);
246         EXPECT_EQ(g_mgr.CloseStore(g_delegate), OK);
247         g_delegate = nullptr;
248         DistributedDBToolsUnitTest::RemoveTestDbFiles(g_testDir);
249     }
250 
GetStorageProxy(ICloudSyncStorageInterface * store)251     std::shared_ptr<StorageProxy> GetStorageProxy(ICloudSyncStorageInterface *store)
252     {
253         return StorageProxy::GetCloudDb(store);
254     }
255 
GetInfoByPrimaryKeyOrGidTest(PrimaryKeyType pkType,const std::string & gidStr,int64_t id,int expectCode,bool compositePkMatch=false)256     void GetInfoByPrimaryKeyOrGidTest(PrimaryKeyType pkType, const std::string &gidStr, int64_t id,
257         int expectCode, bool compositePkMatch = false)
258     {
259         /**
260          * @tc.steps:step1. create db, create table.
261          * @tc.expected: step1. return ok.
262          */
263         PrepareDataBase(g_tableName, pkType);
264 
265         /**
266          * @tc.steps:step2. call GetInfoByPrimaryKeyOrGid.
267          * @tc.expected: step2. return expectCode.
268          */
269         std::shared_ptr<StorageProxy> storageProxy = GetStorageProxy(g_cloudStore);
270         ASSERT_NE(storageProxy, nullptr);
271         EXPECT_EQ(storageProxy->StartTransaction(), E_OK);
272         VBucket vBucket;
273         vBucket["id"] = id ;
274         if (compositePkMatch) {
275             std::string name = "zhangsan1";
276             vBucket["name"] = name;
277             vBucket["age"] = 10.1; // 10.1 is test age
278         } else {
279             std::string name = "zhangsan100";
280             vBucket["name"] = name;
281             vBucket["age"] = 10.11; // 10.11 is test age
282         }
283         vBucket[CloudDbConstant::GID_FIELD] = gidStr;
284         DataInfoWithLog dataInfoWithLog;
285         VBucket assetInfo;
286         EXPECT_EQ(storageProxy->GetInfoByPrimaryKeyOrGid(g_tableName, vBucket, true, dataInfoWithLog, assetInfo), expectCode);
287         if (expectCode == E_OK) {
288             if (pkType == PrimaryKeyType::SINGLE_PRIMARY_KEY) {
289                 int64_t val = -1;
290                 // id is pk
291                 EXPECT_EQ(CloudStorageUtils::GetValueFromVBucket("id", dataInfoWithLog.primaryKeys, val), E_OK);
292             } else if (pkType == PrimaryKeyType::COMPOSITE_PRIMARY_KEY) {
293                 EXPECT_TRUE(dataInfoWithLog.primaryKeys.find("id") != dataInfoWithLog.primaryKeys.end());
294                 std::string name;
295                 EXPECT_EQ(CloudStorageUtils::GetValueFromVBucket("name", dataInfoWithLog.primaryKeys, name), E_OK);
296                 LOGD("name = %s", name.c_str());
297             } else {
298                 EXPECT_EQ(dataInfoWithLog.primaryKeys.size(), 0u);
299             }
300             Timestamp eraseTime = dataInfoWithLog.logInfo.timestamp / CloudDbConstant::TEN_THOUSAND *
301                 CloudDbConstant::TEN_THOUSAND;
302             Timestamp eraseWTime = dataInfoWithLog.logInfo.wTimestamp / CloudDbConstant::TEN_THOUSAND *
303                 CloudDbConstant::TEN_THOUSAND;
304             EXPECT_EQ(dataInfoWithLog.logInfo.timestamp, eraseTime);
305             EXPECT_EQ(dataInfoWithLog.logInfo.wTimestamp, eraseWTime);
306         }
307         EXPECT_EQ(storageProxy->Commit(), E_OK);
308     }
309 
310     /**
311      * @tc.name: GetInfoByPrimaryKeyOrGidTest001
312      * @tc.desc: Test GetInfoByPrimaryKeyOrGid when table has single primary key and gid = "", id = 100;
313      * @tc.type: FUNC
314      * @tc.require:
315      * @tc.author: zhangshijie
316      */
317     HWTEST_F(DistributedDBCloudSaveCloudDataTest, GetInfoByPrimaryKeyOrGidTest001, TestSize.Level0)
318     {
319         GetInfoByPrimaryKeyOrGidTest(PrimaryKeyType::SINGLE_PRIMARY_KEY, "", 100L, -E_NOT_FOUND);
320     }
321 
322     /**
323      * @tc.name: GetInfoByPrimaryKeyOrGidTest002
324      * @tc.desc: Test GetInfoByPrimaryKeyOrGid when table has single primary key and gid = "", id = 1;
325      * @tc.type: FUNC
326      * @tc.require:
327      * @tc.author: zhangshijie
328      */
329     HWTEST_F(DistributedDBCloudSaveCloudDataTest, GetInfoByPrimaryKeyOrGidTest002, TestSize.Level0)
330     {
331         GetInfoByPrimaryKeyOrGidTest(PrimaryKeyType::SINGLE_PRIMARY_KEY, "", 1, E_OK);
332     }
333 
334     /**
335      * @tc.name: GetInfoByPrimaryKeyOrGidTest003
336      * @tc.desc: Test GetInfoByPrimaryKeyOrGid when table has single primary key and gid = abcd0, id = 100;
337      * @tc.type: FUNC
338      * @tc.require:
339      * @tc.author: zhangshijie
340      */
341     HWTEST_F(DistributedDBCloudSaveCloudDataTest, GetInfoByPrimaryKeyOrGidTest003, TestSize.Level0)
342     {
343         GetInfoByPrimaryKeyOrGidTest(PrimaryKeyType::SINGLE_PRIMARY_KEY, g_gid + std::to_string(0), 100L, E_OK);
344     }
345 
346     /**
347      * @tc.name: GetInfoByPrimaryKeyOrGidTest004
348      * @tc.desc: Test GetInfoByPrimaryKeyOrGid when table has single primary key and gid = abcd0, id = 2, which will
349      * match two records;
350      * @tc.type: FUNC
351      * @tc.require:
352      * @tc.author: zhangshijie
353      */
354     HWTEST_F(DistributedDBCloudSaveCloudDataTest, GetInfoByPrimaryKeyOrGidTest004, TestSize.Level0)
355     {
356         GetInfoByPrimaryKeyOrGidTest(PrimaryKeyType::SINGLE_PRIMARY_KEY, g_gid + std::to_string(0), 2L,
357             -E_CLOUD_ERROR);
358     }
359 
360     /**
361      * @tc.name: GetInfoByPrimaryKeyOrGidTest005
362      * @tc.desc: Test GetInfoByPrimaryKeyOrGid when table has single primary key and gid = abcd100, id = 100;
363      * @tc.type: FUNC
364      * @tc.require:
365      * @tc.author: zhangshijie
366      */
367     HWTEST_F(DistributedDBCloudSaveCloudDataTest, GetInfoByPrimaryKeyOrGidTest005, TestSize.Level0)
368     {
369         GetInfoByPrimaryKeyOrGidTest(PrimaryKeyType::SINGLE_PRIMARY_KEY, g_gid + std::to_string(100), 100L,
370             -E_NOT_FOUND);
371     }
372 
373     /**
374      * @tc.name: GetInfoByPrimaryKeyOrGidTest006
375      * @tc.desc: Test GetInfoByPrimaryKeyOrGid when table has no primary key and gid = abcd0, id = 100;
376      * @tc.type: FUNC
377      * @tc.require:
378      * @tc.author: zhangshijie
379      */
380     HWTEST_F(DistributedDBCloudSaveCloudDataTest, GetInfoByPrimaryKeyOrGidTest006, TestSize.Level0)
381     {
382         GetInfoByPrimaryKeyOrGidTest(PrimaryKeyType::NO_PRIMARY_KEY, g_gid + std::to_string(0), 100L, E_OK);
383     }
384 
385     /**
386      * @tc.name: GetInfoByPrimaryKeyOrGidTest007
387      * @tc.desc: Test GetInfoByPrimaryKeyOrGid when table has no primary key and gid = "", id = 1;
388      * @tc.type: FUNC
389      * @tc.require:
390      * @tc.author: zhangshijie
391      */
392     HWTEST_F(DistributedDBCloudSaveCloudDataTest, GetInfoByPrimaryKeyOrGidTest007, TestSize.Level0)
393     {
394         GetInfoByPrimaryKeyOrGidTest(PrimaryKeyType::NO_PRIMARY_KEY, "", 1L, -E_CLOUD_ERROR);
395     }
396 
397     /**
398      * @tc.name: GetInfoByPrimaryKeyOrGidTest008
399      * @tc.desc: Test GetInfoByPrimaryKeyOrGid when table has no primary key and gid = abcd100, id = 1;
400      * @tc.type: FUNC
401      * @tc.require:
402      * @tc.author: zhangshijie
403      */
404     HWTEST_F(DistributedDBCloudSaveCloudDataTest, GetInfoByPrimaryKeyOrGidTest008, TestSize.Level0)
405     {
406         GetInfoByPrimaryKeyOrGidTest(PrimaryKeyType::NO_PRIMARY_KEY, g_gid + std::to_string(100), 1L,
407             -E_NOT_FOUND);
408     }
409 
410     /**
411      * @tc.name: GetInfoByPrimaryKeyOrGidTest009
412      * @tc.desc: Test GetInfoByPrimaryKeyOrGid when table has composite primary key and gid = "", primary key match;
413      * @tc.type: FUNC
414      * @tc.require:
415      * @tc.author: zhangshijie
416      */
417     HWTEST_F(DistributedDBCloudSaveCloudDataTest, GetInfoByPrimaryKeyOrGidTest009, TestSize.Level0)
418     {
419         GetInfoByPrimaryKeyOrGidTest(PrimaryKeyType::COMPOSITE_PRIMARY_KEY, "", 1L, E_OK, true);
420     }
421 
422     /**
423      * @tc.name: GetInfoByPrimaryKeyOrGidTest010
424      * @tc.desc: Test GetInfoByPrimaryKeyOrGid when table has composite primary key and gid = "",
425      * primary key mismatch;
426      * @tc.type: FUNC
427      * @tc.require:
428      * @tc.author: zhangshijie
429      */
430     HWTEST_F(DistributedDBCloudSaveCloudDataTest, GetInfoByPrimaryKeyOrGidTest010, TestSize.Level0)
431     {
432         GetInfoByPrimaryKeyOrGidTest(PrimaryKeyType::COMPOSITE_PRIMARY_KEY, "", 1L, -E_NOT_FOUND, false);
433     }
434 
435     /**
436      * @tc.name: GetInfoByPrimaryKeyOrGidTest011
437      * @tc.desc: Test GetInfoByPrimaryKeyOrGid when table has composite primary key and gid match,
438      * primary key mismatch
439      * @tc.type: FUNC
440      * @tc.require:
441      * @tc.author: zhangshijie
442      */
443     HWTEST_F(DistributedDBCloudSaveCloudDataTest, GetInfoByPrimaryKeyOrGidTest011, TestSize.Level0)
444     {
445         GetInfoByPrimaryKeyOrGidTest(PrimaryKeyType::COMPOSITE_PRIMARY_KEY, "abcd0", 11L, E_OK, false);
446     }
447 
VbucketWithoutPrimaryDataTest(PrimaryKeyType pkType)448     void VbucketWithoutPrimaryDataTest(PrimaryKeyType pkType)
449     {
450         /**
451          * @tc.steps:step1. create db, create table.
452          * @tc.expected: step1. return ok.
453          */
454         PrepareDataBase(g_tableName, pkType);
455 
456         /**
457          * @tc.steps:step2. call GetInfoByPrimaryKeyOrGid.
458          * @tc.expected: step2. return E_OK.
459          */
460         std::shared_ptr<StorageProxy> storageProxy = GetStorageProxy(g_cloudStore);
461         ASSERT_NE(storageProxy, nullptr);
462         EXPECT_EQ(storageProxy->StartTransaction(), E_OK);
463         VBucket vBucket;
464         std::string gid = g_gid + std::to_string(0);
465         vBucket[CloudDbConstant::GID_FIELD] = gid;
466         DataInfoWithLog dataInfoWithLog;
467         VBucket assetInfo;
468         EXPECT_EQ(storageProxy->GetInfoByPrimaryKeyOrGid(g_tableName, vBucket, true, dataInfoWithLog, assetInfo), E_OK);
469         EXPECT_EQ(storageProxy->Commit(), E_OK);
470     }
471 
472     /**
473      * @tc.name: GetInfoByPrimaryKeyOrGidTest012
474      * @tc.desc: Test GetInfoByPrimaryKeyOrGid when vbucket doesn't contain pk data and gid match,
475      * @tc.type: FUNC
476      * @tc.require:
477      * @tc.author: zhangshijie
478      */
479     HWTEST_F(DistributedDBCloudSaveCloudDataTest, GetInfoByPrimaryKeyOrGidTest012, TestSize.Level0)
480     {
481         VbucketWithoutPrimaryDataTest(PrimaryKeyType::SINGLE_PRIMARY_KEY);
482     }
483 
484     /**
485      * @tc.name: GetInfoByPrimaryKeyOrGidTest013
486      * @tc.desc: Test GetInfoByPrimaryKeyOrGid when vbucket doesn't contain pk(composite pk) data and gid match,
487      * @tc.type: FUNC
488      * @tc.require:
489      * @tc.author: zhangshijie
490      */
491     HWTEST_F(DistributedDBCloudSaveCloudDataTest, GetInfoByPrimaryKeyOrGidTest013, TestSize.Level1)
492     {
493         VbucketWithoutPrimaryDataTest(PrimaryKeyType::COMPOSITE_PRIMARY_KEY);
494     }
495 
SetCloudSchemaForCollate(bool ageIsPrimaryKey)496     void SetCloudSchemaForCollate(bool ageIsPrimaryKey)
497     {
498         TableSchema tableSchema;
499         Field field1 = { "name", TYPE_INDEX<std::string>, true, false };
500         Field field2 = { "age", TYPE_INDEX<std::string>, ageIsPrimaryKey, false };
501         tableSchema = { g_tableName, g_tableName + "_shared", { field1, field2 } };
502 
503         DataBaseSchema dbSchema;
504         dbSchema.tables = { tableSchema };
505         g_delegate->SetCloudDbSchema(dbSchema);
506     }
507 
PrimaryKeyCollateTest(const std::string & createSql,const std::string & insertSql,const std::vector<std::string> & pkStr,bool ageIsPrimaryKey,int expectCode=E_OK)508     void PrimaryKeyCollateTest(const std::string &createSql, const std::string &insertSql,
509         const std::vector<std::string> &pkStr, bool ageIsPrimaryKey, int expectCode = E_OK)
510     {
511         /**
512          * @tc.steps:step1. create table.
513          * @tc.expected: step1. return ok.
514          */
515         sqlite3 *db = RelationalTestUtils::CreateDataBase(g_dbDir + STORE_ID + DB_SUFFIX);
516         EXPECT_NE(db, nullptr);
517         EXPECT_EQ(RelationalTestUtils::ExecSql(db, createSql), E_OK);
518         SetCloudSchemaForCollate(ageIsPrimaryKey);
519 
520         /**
521          * @tc.steps:step2. create distributed table with CLOUD_COOPERATION mode.
522          * @tc.expected: step2. return ok.
523          */
524         EXPECT_EQ(g_delegate->CreateDistributedTable(g_tableName, DistributedDB::CLOUD_COOPERATION), OK);
525 
526         /**
527          * @tc.steps:step3. insert data in lower case.
528          * @tc.expected: step3. return ok.
529          */
530         EXPECT_EQ(RelationalTestUtils::ExecSql(db, insertSql), E_OK);
531         EXPECT_EQ(sqlite3_close_v2(db), E_OK);
532 
533         /**
534          * @tc.steps:step4. construct cloud data in upper case, call GetInfoByPrimaryKeyOrGid
535          * @tc.expected: step4. return expectCode.
536          */
537         std::shared_ptr<StorageProxy> storageProxy = GetStorageProxy(g_cloudStore);
538         ASSERT_NE(storageProxy, nullptr);
539         EXPECT_EQ(storageProxy->StartTransaction(), E_OK);
540         VBucket vBucket;
541         std::string gid = g_gid + std::to_string(0);
542         vBucket["name"] = pkStr[0];
543         if (ageIsPrimaryKey) {
544             vBucket["age"] = pkStr[1];
545         }
546         vBucket[CloudDbConstant::GID_FIELD] = gid;
547         DataInfoWithLog dataInfoWithLog;
548         VBucket assetInfo;
549         EXPECT_EQ(storageProxy->GetInfoByPrimaryKeyOrGid(g_tableName, vBucket, true, dataInfoWithLog, assetInfo),
550             expectCode);
551         EXPECT_EQ(storageProxy->Commit(), E_OK);
552     }
553 
554     /**
555      * @tc.name: GetInfoByPrimaryKeyOrGidTest014
556      * @tc.desc: Test collate nocase for primary key(NOCASE followed by ','), case mismatch
557      * @tc.type: FUNC
558      * @tc.require:
559      * @tc.author: zhangshijie
560      */
561     HWTEST_F(DistributedDBCloudSaveCloudDataTest, GetInfoByPrimaryKeyOrGidTest014, TestSize.Level0)
562     {
563         std::string createSql = "create table " + g_tableName + "(name text primary key COLLATE NOCASE, age text);";
564         std::string insertSql = "insert into " + g_tableName + " values('abcd', '10');";
565         std::vector<std::string> pkStr = { "aBcD" };
566         PrimaryKeyCollateTest(createSql, insertSql, pkStr, false);
567     }
568 
569     /**
570      * @tc.name: GetInfoByPrimaryKeyOrGidTest015
571      * @tc.desc: Test collate nocase for primary key, case match
572      * @tc.type: FUNC
573      * @tc.require:
574      * @tc.author: zhangshijie
575      */
576     HWTEST_F(DistributedDBCloudSaveCloudDataTest, GetInfoByPrimaryKeyOrGidTest015, TestSize.Level0)
577     {
578         std::string createSql = "create table " + g_tableName + "(name text primary key COLLATE NOCASE, age text);";
579         std::string insertSql = "insert into " + g_tableName + " values('abcd', '10');";
580         std::vector<std::string> pkStr = { "abcd" };
581         PrimaryKeyCollateTest(createSql, insertSql, pkStr, false);
582     }
583 
584     /**
585      * @tc.name: GetInfoByPrimaryKeyOrGidTest016
586      * @tc.desc: Test collate nocase for primary key(NOCASE followed by ')'), case mismatch
587      * @tc.type: FUNC
588      * @tc.require:
589      * @tc.author: zhangshijie
590      */
591     HWTEST_F(DistributedDBCloudSaveCloudDataTest, GetInfoByPrimaryKeyOrGidTest016, TestSize.Level0)
592     {
593         std::string createSql = "create table " + g_tableName + "(name text primary key COLLATE NOCASE);";
594         std::string insertSql = "insert into " + g_tableName + " values('abcd');";
595         std::vector<std::string> pkStr = { "aBcD" };
596         PrimaryKeyCollateTest(createSql, insertSql, pkStr, false);
597     }
598 
599     /**
600      * @tc.name: GetInfoByPrimaryKeyOrGidTest017
601      * @tc.desc: Test collate nocase for primary key(NOCASE followed by ' '), case mismatch
602      * @tc.type: FUNC
603      * @tc.require:
604      * @tc.author: zhangshijie
605      */
606     HWTEST_F(DistributedDBCloudSaveCloudDataTest, GetInfoByPrimaryKeyOrGidTest017, TestSize.Level0)
607     {
608         std::string createSql = "create table " + g_tableName + "(name text primary key COLLATE NOCASE , age int);";
609         std::string insertSql = "insert into " + g_tableName + " values('abcd', 10);";
610         std::vector<std::string> pkStr = { "aBcD" };
611         PrimaryKeyCollateTest(createSql, insertSql, pkStr, false);
612     }
613 
614     /**
615      * @tc.name: GetInfoByPrimaryKeyOrGidTest018
616      * @tc.desc: Test collate nocase NOT for primary key, case mismatch
617      * @tc.type: FUNC
618      * @tc.require:
619      * @tc.author: zhangshijie
620      */
621     HWTEST_F(DistributedDBCloudSaveCloudDataTest, GetInfoByPrimaryKeyOrGidTest018, TestSize.Level1)
622     {
623         std::string createSql = "create table " + g_tableName + "(name text primary key, age TEXT COLLATE NOCASE);";
624         std::string insertSql = "insert into " + g_tableName + " values('abcd', '10');";
625         std::vector<std::string> pkStr = { "aBcD" };
626         PrimaryKeyCollateTest(createSql, insertSql, pkStr, false, -E_NOT_FOUND);
627     }
628 
629     /**
630      * @tc.name: GetInfoByPrimaryKeyOrGidTest019
631      * @tc.desc: Test collate nocase for one primary key, one pk case mismatch
632      * @tc.type: FUNC
633      * @tc.require:
634      * @tc.author: zhangshijie
635      */
636     HWTEST_F(DistributedDBCloudSaveCloudDataTest, GetInfoByPrimaryKeyOrGidTest019, TestSize.Level1)
637     {
638         std::string createSql = "create table " + g_tableName + "(NAME text collate NOCASE, age text," +
639             "primary key(name, age));";
640         std::string insertSql = "insert into " + g_tableName + " values('abcd', 'ab');";
641         std::vector<std::string> pkStr = { "aBcD", "ab" };
642         PrimaryKeyCollateTest(createSql, insertSql, pkStr, true);
643     }
644 
645     /**
646      * @tc.name: GetInfoByPrimaryKeyOrGidTest020
647      * @tc.desc: Test collate nocase for one primary key, two pk case mismatch
648      * @tc.type: FUNC
649      * @tc.require:
650      * @tc.author: zhangshijie
651      */
652     HWTEST_F(DistributedDBCloudSaveCloudDataTest, GetInfoByPrimaryKeyOrGidTest020, TestSize.Level1)
653     {
654         std::string createSql = "create table " + g_tableName + "(NAME text collate NOCASE, age text," +
655             "primary key(name, age));";
656         std::string insertSql = "insert into " + g_tableName + " values('abcd', 'aB');";
657         std::vector<std::string> pkStr = { "aBcD", "AB" };
658         PrimaryKeyCollateTest(createSql, insertSql, pkStr, true, -E_NOT_FOUND);
659     }
660 
661     /**
662      * @tc.name: GetInfoByPrimaryKeyOrGidTest021
663      * @tc.desc: Test collate nocase for two primary key, two pk case mismatch
664      * @tc.type: FUNC
665      * @tc.require:
666      * @tc.author: zhangshijie
667      */
668     HWTEST_F(DistributedDBCloudSaveCloudDataTest, GetInfoByPrimaryKeyOrGidTest021, TestSize.Level1)
669     {
670         std::string createSql = "create table " + g_tableName + "(NAME text collate NOCASE, age text collate nocase," +
671             "primary key(name, age));";
672         std::string insertSql = "insert into " + g_tableName + " values('abcd', 'aB');";
673         std::vector<std::string> pkStr = { "aBcD", "ab" };
674         PrimaryKeyCollateTest(createSql, insertSql, pkStr, true);
675     }
676 
677     /**
678     * @tc.name: GetInfoByPrimaryKeyOrGidTest022
679     * @tc.desc: Test collate rtrim for primary key(NOCASE followed by ','), trim mismatch
680     * @tc.type: FUNC
681     * @tc.require:
682     * @tc.author: zhangshijie
683     */
684     HWTEST_F(DistributedDBCloudSaveCloudDataTest, GetInfoByPrimaryKeyOrGidTest022, TestSize.Level1)
685     {
686         std::string createSql = "create table " + g_tableName + "(name text primary key COLLATE RTRIM, age text);";
687         std::string insertSql = "insert into " + g_tableName + " values('abcd ', '10');";
688         std::vector<std::string> pkStr = { "abcd" };
689         PrimaryKeyCollateTest(createSql, insertSql, pkStr, false);
690     }
691 
692     /**
693      * @tc.name: GetInfoByPrimaryKeyOrGidTest023
694      * @tc.desc: Test collate nocase for primary key, trim match
695      * @tc.type: FUNC
696      * @tc.require:
697      * @tc.author: zhangshijie
698      */
699     HWTEST_F(DistributedDBCloudSaveCloudDataTest, GetInfoByPrimaryKeyOrGidTest023, TestSize.Level1)
700     {
701         std::string createSql = "create table " + g_tableName + "(name text primary key COLLATE RTRIM, age text);";
702         std::string insertSql = "insert into " + g_tableName + " values('abcd_', '10');";
703         std::vector<std::string> pkStr = { "abcd_" };
704         PrimaryKeyCollateTest(createSql, insertSql, pkStr, false);
705     }
706 
707     /**
708      * @tc.name: GetInfoByPrimaryKeyOrGidTest024
709      * @tc.desc: Test collate rtrim for primary key(NOCASE followed by ')'), rtrim mismatch
710      * @tc.type: FUNC
711      * @tc.require:
712      * @tc.author: zhangshijie
713      */
714     HWTEST_F(DistributedDBCloudSaveCloudDataTest, GetInfoByPrimaryKeyOrGidTest024, TestSize.Level1)
715     {
716         std::string createSql = "create table " + g_tableName + "(name text primary key COLLATE rtrim);";
717         std::string insertSql = "insert into " + g_tableName + " values('abcd ');";
718         std::vector<std::string> pkStr = { "abcd" };
719         PrimaryKeyCollateTest(createSql, insertSql, pkStr, false);
720     }
721 
722     /**
723      * @tc.name: GetInfoByPrimaryKeyOrGidTest025
724      * @tc.desc: Test collate rtrim NOT for primary key, rtrim mismatch
725      * @tc.type: FUNC
726      * @tc.require:
727      * @tc.author: zhangshijie
728      */
729     HWTEST_F(DistributedDBCloudSaveCloudDataTest, GetInfoByPrimaryKeyOrGidTest025, TestSize.Level1)
730     {
731         std::string createSql = "create table " + g_tableName + "(name text primary key, age TEXT COLLATE rtrim);";
732         std::string insertSql = "insert into " + g_tableName + " values('abcd ', '10');";
733         std::vector<std::string> pkStr = { "abcd" };
734         PrimaryKeyCollateTest(createSql, insertSql, pkStr, false, -E_NOT_FOUND);
735     }
736 
737     /**
738      * @tc.name: GetInfoByPrimaryKeyOrGidTest026
739      * @tc.desc: Test collate rtrim for one primary key, one pk rtrim mismatch
740      * @tc.type: FUNC
741      * @tc.require:
742      * @tc.author: zhangshijie
743      */
744     HWTEST_F(DistributedDBCloudSaveCloudDataTest, GetInfoByPrimaryKeyOrGidTest026, TestSize.Level1)
745     {
746         std::string createSql = "create table " + g_tableName + "(NAME text collate RTRIM, age text," +
747             "primary key(name, age));";
748         std::string insertSql = "insert into " + g_tableName + " values('abcd ', 'ab');";
749         std::vector<std::string> pkStr = { "abcd", "ab" };
750         PrimaryKeyCollateTest(createSql, insertSql, pkStr, true);
751     }
752 
753     /**
754      * @tc.name: GetInfoByPrimaryKeyOrGidTest026
755      * @tc.desc: Test collate rtrim for one primary key, two pk rttim mismatch
756      * @tc.type: FUNC
757      * @tc.require:
758      * @tc.author: zhangshijie
759      */
760     HWTEST_F(DistributedDBCloudSaveCloudDataTest, GetInfoByPrimaryKeyOrGidTest027, TestSize.Level1)
761     {
762         std::string createSql = "create table " + g_tableName + "(NAME text collate rtrim, age text," +
763             "primary key(name, age));";
764         std::string insertSql = "insert into " + g_tableName + " values('abcd ', 'aB ');";
765         std::vector<std::string> pkStr = { "abcd", "aB" };
766         PrimaryKeyCollateTest(createSql, insertSql, pkStr, true, -E_NOT_FOUND);
767     }
768 
769     /**
770      * @tc.name: GetInfoByPrimaryKeyOrGidTest027
771      * @tc.desc: Test collate rtrim for two primary key, two pk rtrim mismatch
772      * @tc.type: FUNC
773      * @tc.require:
774      * @tc.author: zhangshijie
775      */
776     HWTEST_F(DistributedDBCloudSaveCloudDataTest, GetInfoByPrimaryKeyOrGidTest028, TestSize.Level1)
777     {
778         std::string createSql = "create table " + g_tableName + "(NAME text collate rtrim, age text collate rtrim," +
779             "primary key(name, age));";
780         std::string insertSql = "insert into " + g_tableName + " values('abcd ', 'ab');";
781         std::vector<std::string> pkStr = { "abcd ", "ab " };
782         PrimaryKeyCollateTest(createSql, insertSql, pkStr, true);
783     }
784 
ConstructDownloadData(DownloadData & downloadData,GidType gidType,bool nullable,bool vBucketContains)785     void ConstructDownloadData(DownloadData &downloadData, GidType gidType, bool nullable, bool vBucketContains)
786     {
787         for (int i = 0; i < 7; i++) { // 7 is record counts
788             VBucket vBucket;
789             if (i == 3) { // 3 is record index
790                 vBucket["id"] = 4L + i; // id = 5, 6 already pre_insert
791             } else {
792                 vBucket["id"] = 1L + i;
793             }
794 
795             std::string name = "lisi" + std::to_string(i);
796             vBucket["name"] = name;
797             vBucket["age"] = 100.0 + i; // 100.0 is offset for cloud data
798             if (vBucketContains) {
799                 vBucket["sex"] = i % 2 ? true : false; // 2 is mod
800             }
801 
802             vBucket["image"] = std::vector<uint8_t>(1, i);
803             std::string gid;
804             if (gidType == GidType::GID_MATCH) {
805                 gid = g_gid + std::to_string(i);
806             } else if (gidType == GidType::GID_EMPTY) {
807                 std::string emptyGid = "";
808                 gid = emptyGid;
809             } else if (gidType == GidType::GID_INVALID) {
810                 std::string invalidGid = "abc'd";
811                 gid = invalidGid;
812             } else {
813                 gid = std::to_string(i) + g_gid;
814             }
815 
816             vBucket[CloudDbConstant::GID_FIELD] = gid;
817             int64_t cTime = 12345678L + i;
818             vBucket[CloudDbConstant::CREATE_FIELD] = cTime;
819             int64_t mTime = 12345679L + i;
820             vBucket[CloudDbConstant::MODIFY_FIELD] = mTime;
821             downloadData.data.push_back(vBucket);
822         }
823 
824         downloadData.opType = { OpType::UPDATE, OpType::DELETE, OpType::ONLY_UPDATE_GID, OpType::INSERT,
825             OpType::SET_CLOUD_FORCE_PUSH_FLAG_ZERO, OpType::SET_CLOUD_FORCE_PUSH_FLAG_ONE, OpType::NOT_HANDLE };
826     }
827 
SaveCloudDataTest(PrimaryKeyType pkType,GidType gidType=GidType::GID_MATCH,bool nullable=true,bool vBucketContains=true,int expectCode=E_OK)828     void SaveCloudDataTest(PrimaryKeyType pkType, GidType gidType = GidType::GID_MATCH, bool nullable = true,
829         bool vBucketContains = true, int expectCode = E_OK)
830     {
831         /**
832          * @tc.steps:step1. create db, create table.
833          * @tc.expected: step1. return ok.
834          */
835         PrepareDataBase(g_tableName, pkType, nullable);
836 
837         /**
838          * @tc.steps:step2. call PutCloudSyncData
839          * @tc.expected: step2. return ok.
840          */
841         std::shared_ptr<StorageProxy> storageProxy = GetStorageProxy(g_cloudStore);
842         ASSERT_NE(storageProxy, nullptr);
843         EXPECT_EQ(storageProxy->StartTransaction(TransactType::IMMEDIATE), E_OK);
844 
845         DownloadData downloadData;
846         ConstructDownloadData(downloadData, gidType, nullable, vBucketContains);
847         EXPECT_EQ(storageProxy->PutCloudSyncData(g_tableName, downloadData), expectCode);
848         if (expectCode == E_OK) {
849             for (size_t i = 0; i < downloadData.opType.size(); i++) {
850                 if (downloadData.opType[i] == OpType::INSERT) {
851                     EXPECT_TRUE(downloadData.data[i].find(DBConstant::ROWID) !=
852                         downloadData.data[i].end());
853                 }
854             }
855         }
856         EXPECT_EQ(storageProxy->Commit(), E_OK);
857     }
858 
859     /**
860      * @tc.name: PutCloudSyncDataTest001
861      * @tc.desc: Test save cloud data into table with no primary key, gid match
862      * @tc.type: FUNC
863      * @tc.require:
864      * @tc.author: zhangshijie
865      */
866     HWTEST_F(DistributedDBCloudSaveCloudDataTest, PutCloudSyncDataTest001, TestSize.Level1)
867     {
868         SaveCloudDataTest(PrimaryKeyType::NO_PRIMARY_KEY);
869         // there is one log record with cloud_gid = abcd3(id = 7 will delete first, then insert again)
870         std::string sql = "select count(data_key) from " + DBCommon::GetLogTableName(g_tableName) +
871             " where cloud_gid = '" + g_gid + std::to_string(3) + "'"; // 3 is gid index
872         sqlite3 *db = RelationalTestUtils::CreateDataBase(g_dbDir + STORE_ID + DB_SUFFIX);
873         EXPECT_NE(db, nullptr);
__anon18a6fa2c0202(sqlite3_stmt *stmt) 874         int errCode = RelationalTestUtils::ExecSql(db, sql, nullptr, [] (sqlite3_stmt *stmt) {
875             EXPECT_EQ(sqlite3_column_int64(stmt, 0), 1); // will get only 1 log record
876             return E_OK;
877         });
878         EXPECT_EQ(errCode, SQLITE_OK);
879         EXPECT_EQ(sqlite3_close_v2(db), E_OK);
880     }
881 
882     /**
883      * @tc.name: PutCloudSyncDataTest002
884      * @tc.desc: Test save cloud data into table with no primary key, gid mismatch
885      * @tc.type: FUNC
886      * @tc.require:
887      * @tc.author: zhangshijie
888      */
889     HWTEST_F(DistributedDBCloudSaveCloudDataTest, PutCloudSyncDataTest002, TestSize.Level1)
890     {
891         SaveCloudDataTest(PrimaryKeyType::NO_PRIMARY_KEY, GidType::GID_MISMATCH);
892     }
893 
894     /**
895      * @tc.name: PutCloudSyncDataTest003
896      * @tc.desc: Test save cloud data into table with no primary key, gid is empty
897      * @tc.type: FUNC
898      * @tc.require:
899      * @tc.author: zhangshijie
900      */
901     HWTEST_F(DistributedDBCloudSaveCloudDataTest, PutCloudSyncDataTest003, TestSize.Level1)
902     {
903         SaveCloudDataTest(PrimaryKeyType::NO_PRIMARY_KEY, GidType::GID_EMPTY, true, true, -E_CLOUD_ERROR);
904     }
905 
906     /**
907      * @tc.name: PutCloudSyncDataTest004
908      * @tc.desc: Test save cloud data into table with single primary key, gid match
909      * @tc.type: FUNC
910      * @tc.require:
911      * @tc.author: zhangshijie
912      */
913     HWTEST_F(DistributedDBCloudSaveCloudDataTest, PutCloudSyncDataTest004, TestSize.Level1)
914     {
915         SaveCloudDataTest(PrimaryKeyType::SINGLE_PRIMARY_KEY);
916     }
917 
918     /**
919      * @tc.name: PutCloudSyncDataTest005
920      * @tc.desc: Test save cloud data into table with single primary key, gid mismatch
921      * @tc.type: FUNC
922      * @tc.require:
923      * @tc.author: zhangshijie
924      */
925     HWTEST_F(DistributedDBCloudSaveCloudDataTest, PutCloudSyncDataTest005, TestSize.Level1)
926     {
927         SaveCloudDataTest(PrimaryKeyType::SINGLE_PRIMARY_KEY, GidType::GID_MISMATCH);
928     }
929 
930     /**
931      * @tc.name: PutCloudSyncDataTest006
932      * @tc.desc: Test save cloud data into table with single primary key, gid is empty
933      * @tc.type: FUNC
934      * @tc.require:
935      * @tc.author: zhangshijie
936      */
937     HWTEST_F(DistributedDBCloudSaveCloudDataTest, PutCloudSyncDataTest006, TestSize.Level1)
938     {
939         SaveCloudDataTest(PrimaryKeyType::SINGLE_PRIMARY_KEY, GidType::GID_EMPTY, true, true, -E_CLOUD_ERROR);
940     }
941 
942     /**
943      * @tc.name: PutCloudSyncDataTest007
944      * @tc.desc: Test save cloud data into table with single primary key, gid is empty, cloud field less than schema,
945      * field can be null
946      * @tc.type: FUNC
947      * @tc.require:
948      * @tc.author: zhangshijie
949      */
950     HWTEST_F(DistributedDBCloudSaveCloudDataTest, PutCloudSyncDataTest007, TestSize.Level0)
951     {
952         SaveCloudDataTest(PrimaryKeyType::SINGLE_PRIMARY_KEY, GidType::GID_MATCH, true, false);
953     }
954 
955     /**
956      * @tc.name: PutCloudSyncDataTest008
957      * @tc.desc: Test save cloud data into table with single primary key, gid is empty, cloud field less than schema,
958      * field can not be null
959      * @tc.type: FUNC
960      * @tc.require:
961      * @tc.author: zhangshijie
962      */
963     HWTEST_F(DistributedDBCloudSaveCloudDataTest, PutCloudSyncDataTest008, TestSize.Level0)
964     {
965         SaveCloudDataTest(PrimaryKeyType::SINGLE_PRIMARY_KEY, GidType::GID_EMPTY, false, false, -E_CLOUD_ERROR);
966     }
967 
968     /**
969      * @tc.name: PutCloudSyncDataTest009
970      * @tc.desc: Test save cloud data into table with composite primary key, gid match, primary key mismatch
971      * @tc.type: FUNC
972      * @tc.require:
973      * @tc.author: zhangshijie
974      */
975     HWTEST_F(DistributedDBCloudSaveCloudDataTest, PutCloudSyncDataTest009, TestSize.Level0)
976     {
977         SaveCloudDataTest(PrimaryKeyType::COMPOSITE_PRIMARY_KEY);
978     }
979 
980     /**
981      * @tc.name: PutCloudSyncDataTest010
982      * @tc.desc: Test save cloud data into table with composite primary key, gid mismatch, primary key mismatch
983      * @tc.type: FUNC
984      * @tc.require:
985      * @tc.author: zhangshijie
986      */
987     HWTEST_F(DistributedDBCloudSaveCloudDataTest, PutCloudSyncDataTest010, TestSize.Level0)
988     {
989         SaveCloudDataTest(PrimaryKeyType::COMPOSITE_PRIMARY_KEY, GidType::GID_MISMATCH);
990     }
991 
992     /**
993      * @tc.name: PutCloudSyncDataTest011
994      * @tc.desc: Test save cloud data into table with composite primary key, invalid gid
995      * @tc.type: FUNC
996      * @tc.require:
997      * @tc.author: zhangshijie
998      */
999     HWTEST_F(DistributedDBCloudSaveCloudDataTest, PutCloudSyncDataTest011, TestSize.Level0)
1000     {
1001         SaveCloudDataTest(PrimaryKeyType::COMPOSITE_PRIMARY_KEY, GidType::GID_INVALID, true, true, -E_CLOUD_ERROR);
1002     }
1003 
ConstructMultiDownloadData(DownloadData & downloadData,GidType gidType)1004     void ConstructMultiDownloadData(DownloadData &downloadData, GidType gidType)
1005     {
1006         for (int i = 0; i < 6; i++) { // 6 is record counts
1007             VBucket vBucket;
1008             if (i < 1) { // UPDATE_TIMESTAMP doesn't contain pk
1009                 vBucket["id"] = 1L + i;
1010             } else if (i > 1) {
1011                 vBucket["id"] = 10L + i; // 10 is id offset for cloud data
1012             }
1013 
1014             std::string name = "lisi" + std::to_string(i);
1015             vBucket["name"] = name;
1016             vBucket["age"] = 100.0 + i; // 100.0 is offset for cloud data
1017             vBucket["sex"] = i % 2 ? true : false; // 2 is mod
1018 
1019             vBucket["image"] = std::vector<uint8_t>(1, i);
1020             std::string gid;
1021             if (gidType == GidType::GID_MATCH) {
1022                 if (i <= 1) { // first 2 exists in local
1023                     gid = g_gid + std::to_string(i);
1024                 } else {
1025                     gid = g_gid + std::to_string(10 + i); // 10 is id offset for cloud data
1026                 }
1027             } else if (gidType == GidType::GID_EMPTY) {
1028                 std::string emptyGid = "";
1029                 gid = emptyGid;
1030             } else {
1031                 gid = std::to_string(i) + g_gid;
1032             }
1033 
1034             vBucket[CloudDbConstant::GID_FIELD] = gid;
1035             int64_t cTime = BASE_CREATE_TIME + i;
1036             vBucket[CloudDbConstant::CREATE_FIELD] = cTime;
1037             int64_t mTime = BASE_MODIFY_TIME + i;
1038             vBucket[CloudDbConstant::MODIFY_FIELD] = mTime;
1039             downloadData.data.push_back(vBucket);
1040         }
1041 
1042         downloadData.opType = { OpType::UPDATE, OpType::UPDATE_TIMESTAMP, OpType::INSERT, OpType::INSERT,
1043             OpType::INSERT, OpType::NOT_HANDLE };
1044     }
1045 
1046     /**
1047      * @tc.name: PutCloudSyncDataTest012
1048      * @tc.desc: Test save cloud data into table with no primary key, multi cloud data
1049      * @tc.type: FUNC
1050      * @tc.require:
1051      * @tc.author: zhangshijie
1052      */
1053     HWTEST_F(DistributedDBCloudSaveCloudDataTest, PutCloudSyncDataTest012, TestSize.Level0)
1054     {
1055         /**
1056          * @tc.steps:step1. create db, create table.
1057          * @tc.expected: step1. return ok.
1058          */
1059         PrepareDataBase(g_tableName, PrimaryKeyType::NO_PRIMARY_KEY, true);
1060 
1061         /**
1062          * @tc.steps:step2. call PutCloudSyncData
1063          * @tc.expected: step2. return ok.
1064          */
1065         std::shared_ptr<StorageProxy> storageProxy = GetStorageProxy(g_cloudStore);
1066         ASSERT_NE(storageProxy, nullptr);
1067         EXPECT_EQ(storageProxy->StartTransaction(TransactType::IMMEDIATE), E_OK);
1068 
1069         DownloadData downloadData;
1070         ConstructMultiDownloadData(downloadData, GidType::GID_MATCH);
1071         EXPECT_EQ(storageProxy->PutCloudSyncData(g_tableName, downloadData), E_OK);
1072         EXPECT_EQ(storageProxy->Commit(), E_OK);
1073     }
1074 
1075     /**
1076      * @tc.name: PutCloudSyncDataTest013
1077      * @tc.desc: Test save cloud data with type = update_timestamp
1078      * @tc.type: FUNC
1079      * @tc.require:
1080      * @tc.author: zhangshijie
1081      */
1082     HWTEST_F(DistributedDBCloudSaveCloudDataTest, PutCloudSyncDataTest013, TestSize.Level0)
1083     {
1084         /**
1085          * @tc.steps:step1. create db, create table.
1086          * @tc.expected: step1. return ok.
1087          */
1088         PrepareDataBase(g_tableName, PrimaryKeyType::SINGLE_PRIMARY_KEY, true);
1089 
1090         std::string sql = "delete from " + g_tableName + " where id = 2";
1091         sqlite3 *db = RelationalTestUtils::CreateDataBase(g_dbDir + STORE_ID + DB_SUFFIX);
1092         EXPECT_NE(db, nullptr);
1093         EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), E_OK);
1094         /**
1095          * @tc.steps:step2. call PutCloudSyncData
1096          * @tc.expected: step2. return ok.
1097          */
1098         std::shared_ptr<StorageProxy> storageProxy = GetStorageProxy(g_cloudStore);
1099         ASSERT_NE(storageProxy, nullptr);
1100         EXPECT_EQ(storageProxy->StartTransaction(TransactType::IMMEDIATE), E_OK);
1101 
1102         DownloadData downloadData;
1103         ConstructMultiDownloadData(downloadData, GidType::GID_MATCH);
1104         EXPECT_EQ(storageProxy->PutCloudSyncData(g_tableName, downloadData), E_OK);
1105         EXPECT_EQ(storageProxy->Commit(), E_OK);
1106 
1107         /**
1108          * @tc.steps:step3. verify data
1109          * @tc.expected: step3. verify data ok.
1110          */
1111         sql = "select device, timestamp, flag from " + DBCommon::GetLogTableName(g_tableName) +
1112             " where data_key = -1 and cloud_gid = ''";
1113         int count = 0;
__anon18a6fa2c0302(sqlite3_stmt *stmt) 1114         int errCode = RelationalTestUtils::ExecSql(db, sql, nullptr, [&count] (sqlite3_stmt *stmt) {
1115             std::string device = "cloud";
1116             std::vector<uint8_t> deviceVec;
1117             (void)SQLiteUtils::GetColumnBlobValue(stmt, 0, deviceVec);    // 0 is device
1118             std::string getDevice;
1119             DBCommon::VectorToString(deviceVec, getDevice);
1120             EXPECT_EQ(device, getDevice);
1121             EXPECT_EQ(sqlite3_column_int64(stmt, 1), BASE_MODIFY_TIME + 1);
1122             EXPECT_EQ(sqlite3_column_int(stmt, 2), 0x20|0x01); // 2 is flag
1123             count++;
1124             return E_OK;
1125         });
1126         EXPECT_EQ(errCode, E_OK);
1127         EXPECT_EQ(count, 1);
1128         EXPECT_EQ(sqlite3_close_v2(db), E_OK);
1129     }
1130 
1131     /**
1132      * @tc.name: PutCloudSyncDataTest014
1133      * @tc.desc: Test PutCloudSyncData when vbucket doesn't contain pk data and gid match,
1134      * @tc.type: FUNC
1135      * @tc.require:
1136      * @tc.author: zhangshijie
1137      */
1138     HWTEST_F(DistributedDBCloudSaveCloudDataTest, PutCloudSyncDataTest014, TestSize.Level0)
1139     {
1140         /**
1141          * @tc.steps:step1. create db, create table.
1142          * @tc.expected: step1. return ok.
1143          */
1144         PrepareDataBase(g_tableName, PrimaryKeyType::SINGLE_PRIMARY_KEY);
1145 
1146         /**
1147          * @tc.steps:step2. construct data without primary key value, call PutCloudSyncData.
1148          * @tc.expected: step2. return E_OK.
1149          */
1150         std::shared_ptr<StorageProxy> storageProxy = GetStorageProxy(g_cloudStore);
1151         ASSERT_NE(storageProxy, nullptr);
1152         EXPECT_EQ(storageProxy->StartTransaction(TransactType::IMMEDIATE), E_OK);
1153 
1154         DownloadData downloadData;
1155         VBucket vBucket;
1156         std::string gid = g_gid + std::to_string(0);
1157         vBucket[CloudDbConstant::GID_FIELD] = gid;
1158         vBucket[CloudDbConstant::MODIFY_FIELD] = BASE_MODIFY_TIME;
1159         downloadData.data.push_back(vBucket);
1160         downloadData.opType = { OpType::DELETE };
1161         EXPECT_EQ(storageProxy->PutCloudSyncData(g_tableName, downloadData), E_OK);
1162         EXPECT_EQ(storageProxy->Commit(), E_OK);
1163     }
1164 
1165     /**
1166      * @tc.name: PutCloudSyncDataTest015
1167      * @tc.desc: Test clear gid and ONLY_UPDATE_GID
1168      * @tc.type: FUNC
1169      * @tc.require:
1170      * @tc.author: zhangshijie
1171      */
1172     HWTEST_F(DistributedDBCloudSaveCloudDataTest, PutCloudSyncDataTest015, TestSize.Level0)
1173     {
1174         /**
1175          * @tc.steps:step1. create db, create table.
1176          * @tc.expected: step1. return ok.
1177          */
1178         PrepareDataBase(g_tableName, PrimaryKeyType::SINGLE_PRIMARY_KEY);
1179 
1180         /**
1181          * @tc.steps:step2. construct data type = clear_gid, call PutCloudSyncData.
1182          * @tc.expected: step2. return E_OK.
1183          */
1184         std::shared_ptr<StorageProxy> storageProxy = GetStorageProxy(g_cloudStore);
1185         ASSERT_NE(storageProxy, nullptr);
1186         EXPECT_EQ(storageProxy->StartTransaction(TransactType::IMMEDIATE), E_OK);
1187 
1188         DownloadData downloadData;
1189         for (int i = 0; i < 2; i++) { // 2 is record count
1190             VBucket vBucket;
1191             std::string gid = g_gid + std::to_string(i * 4); // 4 is data index
1192             vBucket[CloudDbConstant::GID_FIELD] = gid;
1193             vBucket[CloudDbConstant::MODIFY_FIELD] = BASE_MODIFY_TIME;
1194             downloadData.data.push_back(vBucket);
1195         }
1196         downloadData.opType = { OpType::ONLY_UPDATE_GID, OpType::CLEAR_GID };
1197         EXPECT_EQ(storageProxy->PutCloudSyncData(g_tableName, downloadData), E_OK);
1198         EXPECT_EQ(storageProxy->Commit(), E_OK);
1199 
1200         /**
1201          * @tc.steps:step3. verify data
1202          * @tc.expected: step3. verify data ok.
1203          */
1204         std::string sql = "select cloud_gid, flag from " + DBCommon::GetLogTableName(g_tableName) +
1205             " where data_key = 1 or data_key = 5";
1206         int count = 0;
1207         sqlite3 *db = RelationalTestUtils::CreateDataBase(g_dbDir + STORE_ID + DB_SUFFIX);
1208         EXPECT_NE(db, nullptr);
__anon18a6fa2c0402(sqlite3_stmt *stmt) 1209         int errCode = RelationalTestUtils::ExecSql(db, sql, nullptr, [&count] (sqlite3_stmt *stmt) {
1210             std::string gid = "";
1211             if (count == 0) {
1212                 gid = g_gid + "0";
1213             }
1214             const unsigned char *val = sqlite3_column_text(stmt, 0);
1215             EXPECT_TRUE(val != nullptr);
1216             std::string getGid = reinterpret_cast<const char *>(val);
1217             LOGD("GET GID = %s", getGid.c_str());
1218             EXPECT_EQ(getGid, gid);
1219             if (count == 1) {
1220                 int flag = sqlite3_column_int(stmt, 1);
1221                 // 0x04 is binay num of b100, clear gid will clear 2th bit of flag
1222                 EXPECT_EQ(static_cast<uint16_t>(flag) & 0x04, 0);
1223             }
1224             count++;
1225             return E_OK;
1226         });
1227         EXPECT_EQ(errCode, E_OK);
1228         EXPECT_EQ(count, 2); // 2 is result count
1229         EXPECT_EQ(sqlite3_close_v2(db), E_OK);
1230     }
1231 
DeleteWithPkTest(PrimaryKeyType pkType)1232     void DeleteWithPkTest(PrimaryKeyType pkType)
1233     {
1234         /**
1235          * @tc.steps:step1. create db, create table.
1236          * @tc.expected: step1. return ok.
1237          */
1238         PrepareDataBase(g_tableName, pkType, false);
1239 
1240         /**
1241          * @tc.steps:step2. call PutCloudSyncData
1242          * @tc.expected: step2. return ok.
1243          */
1244         std::shared_ptr<StorageProxy> storageProxy = GetStorageProxy(g_cloudStore);
1245         ASSERT_NE(storageProxy, nullptr);
1246         EXPECT_EQ(storageProxy->StartTransaction(TransactType::IMMEDIATE), E_OK);
1247 
1248         DownloadData downloadData;
1249         VBucket vBucket;
1250         vBucket["id"] = 1L;
1251         if (pkType == PrimaryKeyType::COMPOSITE_PRIMARY_KEY) {
1252             std::string name = "zhangsan1";
1253             vBucket["name"] = name;
1254         }
1255 
1256         std::string gid = g_gid + "_not_exist"; // gid mismatch
1257         vBucket[CloudDbConstant::GID_FIELD] = gid;
1258         vBucket[CloudDbConstant::MODIFY_FIELD] = BASE_MODIFY_TIME;
1259         downloadData.data.push_back(vBucket);
1260         downloadData.opType = { OpType::DELETE };
1261         EXPECT_EQ(storageProxy->PutCloudSyncData(g_tableName, downloadData), E_OK);
1262         EXPECT_EQ(storageProxy->Commit(), E_OK);
1263 
1264         /**
1265          * @tc.steps:step3. verify data
1266          * @tc.expected: step3. verify data ok.
1267          */
1268         std::string sql;
1269         if (pkType == PrimaryKeyType::SINGLE_PRIMARY_KEY) {
1270             sql = "select count(1) from " + g_tableName + " where id = 1";
1271         } else {
1272             sql = "select count(1) from " + g_tableName + " where id = 1 and name = 'zhangsan'";
1273         }
1274         int count = 0;
1275         sqlite3 *db = RelationalTestUtils::CreateDataBase(g_dbDir + STORE_ID + DB_SUFFIX);
1276         EXPECT_NE(db, nullptr);
1277         int errCode = RelationalTestUtils::ExecSql(db, sql, nullptr, [&count] (sqlite3_stmt *stmt) {
1278             EXPECT_EQ(sqlite3_column_int(stmt, 0), 0);
1279             count++;
1280             return E_OK;
1281         });
1282         EXPECT_EQ(errCode, E_OK);
1283         EXPECT_EQ(count, 1);
1284         EXPECT_EQ(sqlite3_close_v2(db), E_OK);
1285     }
1286 
1287     /**
1288      * @tc.name: PutCloudSyncDataTest016
1289      * @tc.desc: Test delete data with pk in cloud data(normally there is no pk in cloud data when it is delete)
1290      * @tc.type: FUNC
1291      * @tc.require:
1292      * @tc.author: zhangshijie
1293      */
1294     HWTEST_F(DistributedDBCloudSaveCloudDataTest, PutCloudSyncDataTest016, TestSize.Level1)
1295     {
1296         DeleteWithPkTest(PrimaryKeyType::SINGLE_PRIMARY_KEY);
1297     }
1298 
1299     /**
1300      * @tc.name: PutCloudSyncDataTest017
1301      * @tc.desc: Test delete data with pk in cloud data(normally there is no pk in cloud data when it is delete)
1302      * primary key is COMPOSITE_PRIMARY_KEY
1303      * @tc.type: FUNC
1304      * @tc.require:
1305      * @tc.author: zhangshijie
1306      */
1307     HWTEST_F(DistributedDBCloudSaveCloudDataTest, PutCloudSyncDataTest017, TestSize.Level1)
1308     {
1309         DeleteWithPkTest(PrimaryKeyType::COMPOSITE_PRIMARY_KEY);
1310     }
1311 
1312     /**
1313      * @tc.name: DropTableTest001
1314      * @tc.desc: Test drop table
1315      * @tc.type: FUNC
1316      * @tc.require:
1317      * @tc.author: zhangshijie
1318      */
1319     HWTEST_F(DistributedDBCloudSaveCloudDataTest, DropTableTest001, TestSize.Level1)
1320     {
1321         /**
1322          * @tc.steps:step1. create db, create table, prepare data.
1323          * @tc.expected: step1. ok.
1324          */
1325         sqlite3 *db = RelationalTestUtils::CreateDataBase(g_dbDir + STORE_ID + DB_SUFFIX);
1326         EXPECT_NE(db, nullptr);
1327         EXPECT_EQ(RelationalTestUtils::ExecSql(db, "PRAGMA journal_mode=WAL;"), SQLITE_OK);
1328 
1329         std::string sql = "create table t_device(key int, value text);create table t_cloud(key int, value text);";
1330         EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), SQLITE_OK);
1331         EXPECT_EQ(g_delegate->CreateDistributedTable("t_device", DistributedDB::DEVICE_COOPERATION), OK);
1332         EXPECT_EQ(g_delegate->CreateDistributedTable("t_cloud", DistributedDB::CLOUD_COOPERATION), OK);
1333 
1334         sql = "insert into t_device values(1, 'zhangsan');insert into t_cloud values(1, 'zhangsan');";
1335         EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), SQLITE_OK);
1336         sql = "update " + DBCommon::GetLogTableName("t_cloud") + " set flag = 0";
1337         EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), SQLITE_OK);
1338 
1339         /**
1340          * @tc.steps:step2. drop table t_cloud, check log data
1341          * @tc.expected: step2. success.
1342          */
1343         sql = "drop table t_cloud;";
1344         EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), SQLITE_OK);
1345         sql = "select flag from " + DBCommon::GetLogTableName("t_cloud") + " where data_key = -1;";
1346         int count = 0;
__anon18a6fa2c0602(sqlite3_stmt *stmt) 1347         int errCode = RelationalTestUtils::ExecSql(db, sql, nullptr, [&count] (sqlite3_stmt *stmt) {
1348             EXPECT_EQ(sqlite3_column_int(stmt, 0), 3); // 3 mean local delete
1349             count++;
1350             return E_OK;
1351         });
1352         EXPECT_EQ(errCode, E_OK);
1353         EXPECT_EQ(count, 1);
1354 
1355         /**
1356          * @tc.steps:step3. drop table t_device, check log data
1357          * @tc.expected: step3. success.
1358          */
1359         sql = "drop table t_device;";
1360         EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), SQLITE_OK);
1361         sql = "select flag from " + DBCommon::GetLogTableName("t_device") + " where flag = 0x03;";
1362         count = 0;
__anon18a6fa2c0702(sqlite3_stmt *stmt) 1363         errCode = RelationalTestUtils::ExecSql(db, sql, nullptr, [&count] (sqlite3_stmt *stmt) {
1364             count++;
1365             return E_OK;
1366         });
1367         EXPECT_EQ(errCode, E_OK);
1368         EXPECT_EQ(count, 1);
1369         EXPECT_EQ(sqlite3_close_v2(db), E_OK);
1370     }
1371 
1372     /**
1373      * @tc.name: GetDataWithAsset001
1374      * @tc.desc: Test get data with abnormal asset
1375      * @tc.type: FUNC
1376      * @tc.require:
1377      * @tc.author: zhangqiquan
1378      */
1379     HWTEST_F(DistributedDBCloudSaveCloudDataTest, GetDataWithAsset001, TestSize.Level0)
1380     {
1381         /**
1382          * @tc.steps:step1. create db, create table, prepare data.
1383          * @tc.expected: step1. success.
1384          */
1385         PrepareDataBaseForAsset(g_assetTableName, true);
1386         RuntimeConfig::SetCloudTranslate(std::make_shared<VirtualCloudDataTranslate>());
1387         std::shared_ptr<StorageProxy> storageProxy = GetStorageProxy(g_cloudStore);
1388         ASSERT_NE(storageProxy, nullptr);
1389         int errCode = storageProxy->StartTransaction();
1390         EXPECT_EQ(errCode, E_OK);
1391         /**
1392          * @tc.steps:step2. create db, create table, prepare data.
1393          * @tc.expected: step2. success.
1394          */
1395         ContinueToken token = nullptr;
1396         CloudSyncData data(g_assetTableName);
1397         errCode = storageProxy->GetCloudData(g_assetTableName, 0u, token, data);
1398         EXPECT_EQ(errCode, E_OK);
1399         EXPECT_EQ(data.ignoredCount, 1);
1400 
1401         EXPECT_EQ(storageProxy->Commit(), E_OK);
1402         EXPECT_EQ(token, nullptr);
1403         RuntimeConfig::SetCloudTranslate(nullptr);
1404     }
1405 
CheckCloudBatchData(CloudSyncBatch & batchData,bool existRef)1406     void CheckCloudBatchData(CloudSyncBatch &batchData, bool existRef)
1407     {
1408         for (size_t i = 0u; i < batchData.rowid.size(); ++i) {
1409             int64_t rowid = batchData.rowid[i];
1410             auto &extend = batchData.extend[i];
1411             ASSERT_EQ(extend.find(CloudDbConstant::REFERENCE_FIELD) != extend.end(), existRef);
1412             if (!existRef) {
1413                 continue;
1414             }
1415             Entries entries = std::get<Entries>(extend[CloudDbConstant::REFERENCE_FIELD]);
1416             EXPECT_EQ(std::to_string(rowid), entries["targetTable"]);
1417         }
1418     }
1419 
1420     /**
1421      * @tc.name: FillReferenceGid001
1422      * @tc.desc: Test fill gid data with normal
1423      * @tc.type: FUNC
1424      * @tc.require:
1425      * @tc.author: zhangqiquan
1426      */
1427     HWTEST_F(DistributedDBCloudSaveCloudDataTest, FillReferenceGid001, TestSize.Level0)
1428     {
1429         auto storage = new(std::nothrow) MockRelationalSyncAbleStorage();
1430         CloudSyncData syncData("FillReferenceGid001");
1431         EXPECT_CALL(*storage, GetReferenceGid).WillRepeatedly([&syncData](const std::string &tableName,
__anon18a6fa2c0802(const std::string &tableName, const CloudSyncBatch &syncBatch, std::map<int64_t, Entries> &referenceGid) 1432             const CloudSyncBatch &syncBatch, std::map<int64_t, Entries> &referenceGid) {
1433             EXPECT_EQ(syncData.tableName, tableName);
1434             EXPECT_EQ(syncBatch.rowid.size(), 1u); // has 1 record
1435             for (auto rowid : syncBatch.rowid) {
1436                 Entries entries;
1437                 entries["targetTable"] = std::to_string(rowid);
1438                 referenceGid[rowid] = entries;
1439             }
1440             return E_OK;
1441         });
1442         syncData.insData.rowid.push_back(1); // rowid is 1
1443         syncData.insData.extend.resize(1);   // has 1 record
1444         syncData.updData.rowid.push_back(2); // rowid is 2
1445         syncData.updData.extend.resize(1);   // has 1 record
1446         syncData.delData.rowid.push_back(3); // rowid is 3
1447         syncData.delData.extend.resize(1);   // has 1 record
1448         EXPECT_EQ(storage->CallFillReferenceData(syncData), E_OK);
1449         CheckCloudBatchData(syncData.insData, true);
1450         CheckCloudBatchData(syncData.updData, true);
1451         CheckCloudBatchData(syncData.delData, false);
1452         RefObject::KillAndDecObjRef(storage);
1453     }
1454 
1455     /**
1456      * @tc.name: FillReferenceGid002
1457      * @tc.desc: Test fill gid data with abnormal
1458      * @tc.type: FUNC
1459      * @tc.require:
1460      * @tc.author: zhangqiquan
1461      */
1462     HWTEST_F(DistributedDBCloudSaveCloudDataTest, FillReferenceGid002, TestSize.Level0)
1463     {
1464         auto storage = new(std::nothrow) MockRelationalSyncAbleStorage();
1465         CloudSyncData syncData("FillReferenceGid002");
1466         syncData.insData.rowid.push_back(1); // rowid is 1
1467         EXPECT_CALL(*storage, GetReferenceGid).WillRepeatedly([](const std::string &,
__anon18a6fa2c0902(const std::string &, const CloudSyncBatch &, std::map<int64_t, Entries> &referenceGid) 1468             const CloudSyncBatch &, std::map<int64_t, Entries> &referenceGid) {
1469             referenceGid[0] = {}; // create default
1470             return E_OK;
1471         });
1472         EXPECT_EQ(storage->CallFillReferenceData(syncData), -E_UNEXPECTED_DATA);
1473         syncData.insData.extend.resize(1); // rowid is 1
1474         EXPECT_EQ(storage->CallFillReferenceData(syncData), E_OK);
1475         RefObject::KillAndDecObjRef(storage);
1476     }
1477 
1478     /**
1479      * @tc.name: ConsistentFlagTest001
1480      * @tc.desc: Check the 0x20 bit of flag changed from the trigger
1481      * @tc.type: FUNC
1482      * @tc.require:
1483      * @tc.author: bty
1484      */
1485     HWTEST_F(DistributedDBCloudSaveCloudDataTest, ConsistentFlagTest001, TestSize.Level1)
1486     {
1487         /**
1488          * @tc.steps:step1. create db, create table, prepare data.
1489          * @tc.expected: step1. success.
1490          */
1491         PrepareDataBase(g_tableName, PrimaryKeyType::SINGLE_PRIMARY_KEY, true);
1492         sqlite3 *db = RelationalTestUtils::CreateDataBase(g_dbDir + STORE_ID + DB_SUFFIX);
1493         ASSERT_NE(db, nullptr);
1494         std::string sql = "insert into " + g_tableName + "(id, name) values(10, 'xx1'), (11, 'xx2')";
1495         EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), E_OK);
1496         sql = "delete from " + g_tableName + "  where id=11;";
1497         EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), E_OK);
1498 
1499         /**
1500          * @tc.steps:step2 query inserted and updated data, check flag
1501          * @tc.expected: step2. success.
1502          */
1503         sql = "select flag from " + DBCommon::GetLogTableName(g_tableName) +
1504             " where data_key in('10', '1')";
__anon18a6fa2c0a02(sqlite3_stmt *stmt) 1505         int errCode = RelationalTestUtils::ExecSql(db, sql, nullptr, [] (sqlite3_stmt *stmt) {
1506             EXPECT_EQ(sqlite3_column_int(stmt, 0), 0x20|0x02);
1507             return E_OK;
1508         });
1509         EXPECT_EQ(errCode, E_OK);
1510 
1511         /**
1512          * @tc.steps:step3 query deleted data which gid is not empty, check flag
1513          * @tc.expected: step3. success.
1514          */
1515         sql = "select flag from " + DBCommon::GetLogTableName(g_tableName) +
1516             " where data_key=-1 and cloud_gid !='';";
__anon18a6fa2c0b02(sqlite3_stmt *stmt) 1517         errCode = RelationalTestUtils::ExecSql(db, sql, nullptr, [] (sqlite3_stmt *stmt) {
1518             EXPECT_EQ(sqlite3_column_int(stmt, 0), 0x20|0x03);
1519             return E_OK;
1520         });
1521         EXPECT_EQ(errCode, E_OK);
1522 
1523         /**
1524          * @tc.steps:step4 query deleted data which gid is empty, check flag
1525          * @tc.expected: step4. success.
1526          */
1527         sql = "select flag from " + DBCommon::GetLogTableName(g_tableName) +
1528               " where data_key=-1 and cloud_gid ='';";
__anon18a6fa2c0c02(sqlite3_stmt *stmt) 1529         errCode = RelationalTestUtils::ExecSql(db, sql, nullptr, [] (sqlite3_stmt *stmt) {
1530             EXPECT_EQ(sqlite3_column_int(stmt, 0), 0x03);
1531             return E_OK;
1532         });
1533         EXPECT_EQ(errCode, E_OK);
1534         EXPECT_EQ(sqlite3_close_v2(db), SQLITE_OK);
1535     }
1536 }
1537