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 #ifdef RELATIONAL_STORE
16 #include <gtest/gtest.h>
17 #include <iostream>
18 #include "cloud/cloud_storage_utils.h"
19 #include "cloud/cloud_db_constant.h"
20 #include "distributeddb_data_generate_unit_test.h"
21 #include "distributeddb_tools_unit_test.h"
22 #include "process_system_api_adapter_impl.h"
23 #include "relational_store_client.h"
24 #include "relational_store_instance.h"
25 #include "relational_store_manager.h"
26 #include "runtime_config.h"
27 #include "sqlite_relational_store.h"
28 #include "sqlite_relational_utils.h"
29 #include "store_observer.h"
30 #include "time_helper.h"
31 #include "virtual_asset_loader.h"
32 #include "virtual_cloud_data_translate.h"
33 #include "virtual_cloud_db.h"
34 #include "virtual_communicator_aggregator.h"
35 #include "mock_asset_loader.h"
36 #include "cloud_db_sync_utils_test.h"
37 
38 using namespace testing::ext;
39 using namespace DistributedDB;
40 using namespace DistributedDBUnitTest;
41 using namespace std;
42 
43 namespace {
44     string g_storeID = "Relational_Store_SYNC";
45     const string g_tableName1 = "worker1";
46     const string g_tableName2 = "worker2";
47     const string g_tableName3 = "worker3";
48     const string g_tableName4 = "worker4";
49     const string DEVICE_CLOUD = "cloud_dev";
50     const string DB_SUFFIX = ".db";
51     const int64_t g_syncWaitTime = 60;
52     const int g_arrayHalfSub = 2;
53     int g_syncIndex = 0;
54     string g_testDir;
55     string g_storePath;
56     std::mutex g_processMutex;
57     std::condition_variable g_processCondition;
58     std::shared_ptr<VirtualCloudDb> g_virtualCloudDb;
59     std::shared_ptr<VirtualAssetLoader> g_virtualAssetLoader;
60     DistributedDB::RelationalStoreManager g_mgr(APP_ID, USER_ID);
61     RelationalStoreObserverUnitTest *g_observer = nullptr;
62     RelationalStoreDelegate *g_delegate = nullptr;
63     VirtualCommunicatorAggregator *communicatorAggregator_ = nullptr;
64     SyncProcess g_syncProcess;
65     using CloudSyncStatusCallback = std::function<void(const std::map<std::string, SyncProcess> &onProcess)>;
66     const std::string CREATE_LOCAL_TABLE_SQL =
67             "CREATE TABLE IF NOT EXISTS " + g_tableName1 + "(" \
68     "name TEXT PRIMARY KEY," \
69     "height REAL ," \
70     "married BOOLEAN ," \
71     "photo BLOB NOT NULL," \
72     "assert BLOB," \
73     "age INT);";
74     const std::string INTEGER_PRIMARY_KEY_TABLE_SQL =
75             "CREATE TABLE IF NOT EXISTS " + g_tableName2 + "(" \
76     "id INTEGER PRIMARY KEY," \
77     "name TEXT ," \
78     "height REAL ," \
79     "photo BLOB ," \
80     "asserts BLOB," \
81     "age INT);";
82     const std::string DROP_INTEGER_PRIMARY_KEY_TABLE_SQL = "DROP TABLE " + g_tableName2 + ";";
83     const std::string CREATE_LOCAL_TABLE_WITHOUT_PRIMARY_KEY_SQL =
84             "CREATE TABLE IF NOT EXISTS " + g_tableName3 + "(" \
85     "name TEXT," \
86     "height REAL ," \
87     "married BOOLEAN ," \
88     "photo BLOB NOT NULL," \
89     "assert BLOB," \
90     "age INT);";
91     const std::string INTEGER_PRIMARY_KEY_TABLE_SQL_WRONG_SYNC_MODE =
92             "CREATE TABLE IF NOT EXISTS " + g_tableName4 + "(" \
93     "id INTEGER PRIMARY KEY," \
94     "name TEXT ," \
95     "height REAL ," \
96     "photo BLOB ," \
97     "asserts BLOB," \
98     "age INT);";
99     const std::vector<Field> g_cloudFiled1 = {
100         {"name", TYPE_INDEX<std::string>, true}, {"height", TYPE_INDEX<double>},
101         {"married", TYPE_INDEX<bool>}, {"photo", TYPE_INDEX<Bytes>, false, false},
102         {"assert", TYPE_INDEX<Asset>}, {"age", TYPE_INDEX<int64_t>}
103     };
104     const std::vector<Field> g_invalidCloudFiled1 = {
105         {"name", TYPE_INDEX<std::string>, true}, {"height", TYPE_INDEX<int>},
106         {"married", TYPE_INDEX<bool>}, {"photo", TYPE_INDEX<Bytes>, false, false},
107         {"assert", TYPE_INDEX<Bytes>}, {"age", TYPE_INDEX<int64_t>}
108     };
109     const std::vector<Field> g_cloudFiled2 = {
110         {"id", TYPE_INDEX<int64_t>, true}, {"name", TYPE_INDEX<std::string>},
111         {"height", TYPE_INDEX<double>},  {"photo", TYPE_INDEX<Bytes>},
112         {"asserts", TYPE_INDEX<Assets>}, {"age", TYPE_INDEX<int64_t>}
113     };
114     const std::vector<Field> g_cloudFiledWithOutPrimaryKey3 = {
115         {"name", TYPE_INDEX<std::string>, false, true}, {"height", TYPE_INDEX<double>},
116         {"married", TYPE_INDEX<bool>}, {"photo", TYPE_INDEX<Bytes>, false, false},
117         {"assert", TYPE_INDEX<Bytes>}, {"age", TYPE_INDEX<int64_t>}
118     };
119     const std::vector<std::string> g_tables = {g_tableName1, g_tableName2};
120     const std::vector<std::string> g_shareTables = {g_tableName1 + CloudDbConstant::SHARED,
121         g_tableName2 + CloudDbConstant::SHARED};
122     const std::vector<std::string> g_tablesPKey = {g_cloudFiled1[0].colName, g_cloudFiled2[0].colName};
123     const std::vector<string> g_prefix = {"Local", ""};
124     const Asset g_localAsset = {
125         .version = 1, .name = "Phone", .assetId = "0", .subpath = "/local/sync", .uri = "/local/sync",
126         .modifyTime = "123456", .createTime = "", .size = "256", .hash = "ASE"
127     };
128     const Asset g_cloudAsset = {
129         .version = 2, .name = "Phone", .assetId = "0", .subpath = "/local/sync", .uri = "/cloud/sync",
130         .modifyTime = "123456", .createTime = "0", .size = "1024", .hash = "DEC"
131     };
132 
CreateUserDBAndTable(sqlite3 * & db)133     void CreateUserDBAndTable(sqlite3 *&db)
134     {
135         EXPECT_EQ(RelationalTestUtils::ExecSql(db, "PRAGMA journal_mode=WAL;"), SQLITE_OK);
136         EXPECT_EQ(RelationalTestUtils::ExecSql(db, CREATE_LOCAL_TABLE_SQL), SQLITE_OK);
137         EXPECT_EQ(RelationalTestUtils::ExecSql(db, INTEGER_PRIMARY_KEY_TABLE_SQL), SQLITE_OK);
138         EXPECT_EQ(RelationalTestUtils::ExecSql(db, CREATE_LOCAL_TABLE_WITHOUT_PRIMARY_KEY_SQL), SQLITE_OK);
139     }
140 
InsertUserTableRecord(sqlite3 * & db,int64_t begin,int64_t count,int64_t photoSize,bool assetIsNull)141     void InsertUserTableRecord(sqlite3 *&db, int64_t begin, int64_t count, int64_t photoSize, bool assetIsNull)
142     {
143         std::string photo(photoSize, 'v');
144         int errCode;
145         std::vector<uint8_t> assetBlob;
146         for (int64_t i = begin; i < begin + count; ++i) {
147             Asset asset = g_localAsset;
148             asset.name = asset.name + std::to_string(i);
149             RuntimeContext::GetInstance()->AssetToBlob(asset, assetBlob);
150             string sql = "INSERT OR REPLACE INTO " + g_tableName1
151                          + " (name, height, married, photo, assert, age) VALUES ('Local" + std::to_string(i) +
152                          "', '175.8', '0', '" + photo + "', ? , '18');";
153             sqlite3_stmt *stmt = nullptr;
154             ASSERT_EQ(SQLiteUtils::GetStatement(db, sql, stmt), E_OK);
155             if (assetIsNull) {
156                 ASSERT_EQ(sqlite3_bind_null(stmt, 1), SQLITE_OK);
157             } else {
158                 ASSERT_EQ(SQLiteUtils::BindBlobToStatement(stmt, 1, assetBlob, false), E_OK);
159             }
160             EXPECT_EQ(SQLiteUtils::StepWithRetry(stmt), SQLiteUtils::MapSQLiteErrno(SQLITE_DONE));
161             SQLiteUtils::ResetStatement(stmt, true, errCode);
162         }
163         for (int64_t i = begin; i < begin + count; ++i) {
164             std::vector<Asset> assets;
165             Asset asset = g_localAsset;
166             asset.name = g_localAsset.name + std::to_string(i);
167             assets.push_back(asset);
168             asset.name = g_localAsset.name + std::to_string(i + 1);
169             assets.push_back(asset);
170             RuntimeContext::GetInstance()->AssetsToBlob(assets, assetBlob);
171             string sql = "INSERT OR REPLACE INTO " + g_tableName2
172                          + " (id, name, height, photo, asserts, age) VALUES ('" + std::to_string(i) + "', 'Local"
173                          + std::to_string(i) + "', '155.10', '"+ photo + "',  ? , '21');";
174             sqlite3_stmt *stmt = nullptr;
175             ASSERT_EQ(SQLiteUtils::GetStatement(db, sql, stmt), E_OK);
176             if (assetIsNull) {
177                 ASSERT_EQ(sqlite3_bind_null(stmt, 1), E_OK);
178             } else {
179                 ASSERT_EQ(SQLiteUtils::BindBlobToStatement(stmt, 1, assetBlob, false), E_OK);
180             }
181             EXPECT_EQ(SQLiteUtils::StepWithRetry(stmt), SQLiteUtils::MapSQLiteErrno(SQLITE_DONE));
182             SQLiteUtils::ResetStatement(stmt, true, errCode);
183         }
184         LOGD("insert user record worker1[primary key]:[Local%" PRId64 " - Local%" PRId64
185             ") , worker2[primary key]:[%" PRId64 "- %" PRId64")", begin, count, begin, count);
186     }
187 
InsertCloudTableRecord(int64_t begin,int64_t count,int64_t photoSize,bool assetIsNull)188     void InsertCloudTableRecord(int64_t begin, int64_t count, int64_t photoSize, bool assetIsNull)
189     {
190         std::vector<uint8_t> photo(photoSize, 'v');
191         std::vector<VBucket> record1;
192         std::vector<VBucket> extend1;
193         std::vector<VBucket> record2;
194         std::vector<VBucket> extend2;
195         Timestamp now = TimeHelper::GetSysCurrentTime();
196         for (int64_t i = begin; i < begin + count; ++i) {
197             VBucket data;
198             data.insert_or_assign("name", "Cloud" + std::to_string(i));
199             data.insert_or_assign("height", 166.0); // 166.0 is random double value
200             data.insert_or_assign("married", false);
201             data.insert_or_assign("photo", photo);
202             data.insert_or_assign("age", 13L);
203             Asset asset = g_cloudAsset;
204             asset.name = asset.name + std::to_string(i);
205             assetIsNull ? data.insert_or_assign("assert", Nil()) : data.insert_or_assign("assert", asset);
206             record1.push_back(data);
207             VBucket log;
208             log.insert_or_assign(CloudDbConstant::CREATE_FIELD, (int64_t)now / CloudDbConstant::TEN_THOUSAND + i);
209             log.insert_or_assign(CloudDbConstant::MODIFY_FIELD, (int64_t)now / CloudDbConstant::TEN_THOUSAND + i);
210             log.insert_or_assign(CloudDbConstant::DELETE_FIELD, false);
211             extend1.push_back(log);
212 
213             std::vector<Asset> assets;
214             data.insert_or_assign("id", i);
215             data.insert_or_assign("height", 180.3); // 180.3 is random double value
216             for (int64_t j = i; j <= i + 2; j++) { // 2 extra num
217                 asset.name = g_cloudAsset.name + std::to_string(j);
218                 assets.push_back(asset);
219             }
220             data.erase("assert");
221             data.erase("married");
222             assetIsNull ? data.insert_or_assign("asserts", Nil()) : data.insert_or_assign("asserts", assets);
223             record2.push_back(data);
224             extend2.push_back(log);
225         }
226         ASSERT_EQ(g_virtualCloudDb->BatchInsert(g_tableName1, std::move(record1), extend1), DBStatus::OK);
227         ASSERT_EQ(g_virtualCloudDb->BatchInsert(g_tableName2, std::move(record2), extend2), DBStatus::OK);
228         LOGD("insert cloud record worker1[primary key]:[cloud%" PRId64 " - cloud%" PRId64
229             ") , worker2[primary key]:[%" PRId64 "- %" PRId64")", begin, count, begin, count);
230         std::this_thread::sleep_for(std::chrono::milliseconds(count));
231     }
232 
DeleteUserTableRecord(sqlite3 * & db,int64_t begin,int64_t count)233     void DeleteUserTableRecord(sqlite3 *&db, int64_t begin, int64_t count)
234     {
235         for (size_t i = 0; i < g_tables.size(); i++) {
236             string updateAge = "Delete from " + g_tables[i] + " where " + g_tablesPKey[i] + " in (";
237             for (int64_t j = begin; j < count; ++j) {
238                 updateAge += "'" + g_prefix[i] + std::to_string(j) + "',";
239             }
240             updateAge.pop_back();
241             updateAge += ");";
242             ASSERT_EQ(RelationalTestUtils::ExecSql(db, updateAge), SQLITE_OK);
243         }
244         LOGD("delete local record worker1[primary key]:[local%" PRId64 " - local%" PRId64
245             ") , worker2[primary key]:[%" PRId64 "- %" PRId64")", begin, count, begin, count);
246     }
247 
UpdateUserTableRecord(sqlite3 * & db,int64_t begin,int64_t count)248     void UpdateUserTableRecord(sqlite3 *&db, int64_t begin, int64_t count)
249     {
250         for (size_t i = 0; i < g_tables.size(); i++) {
251             string updateAge = "UPDATE " + g_tables[i] + " SET height = 111.11 where " + g_tablesPKey[i] + " in (";
252             for (int64_t j = begin; j < count; ++j) {
253                 updateAge += "'" + g_prefix[i] + std::to_string(j) + "',";
254             }
255             updateAge.pop_back();
256             updateAge += ");";
257             ASSERT_EQ(RelationalTestUtils::ExecSql(db, updateAge), SQLITE_OK);
258         }
259         LOGD("update local record worker1[primary key]:[local%" PRId64 " - local%" PRId64
260             ") , worker2[primary key]:[%" PRId64 "- %" PRId64")", begin, count, begin, count);
261     }
262 
DeleteCloudTableRecordByGid(int64_t begin,int64_t count)263     void DeleteCloudTableRecordByGid(int64_t begin, int64_t count)
264     {
265         for (int64_t i = begin; i < begin + count; ++i) {
266             VBucket data;
267             data.insert_or_assign(CloudDbConstant::GID_FIELD, std::to_string(i));
268             ASSERT_EQ(g_virtualCloudDb->DeleteByGid(g_tableName1, data), DBStatus::OK);
269         }
270         LOGD("delete cloud record worker[primary key]:[cloud%" PRId64 " - cloud%" PRId64")", begin, count);
271         std::this_thread::sleep_for(std::chrono::milliseconds(count));
272     }
273 
GetCloudDbSchema(DataBaseSchema & dataBaseSchema)274     void GetCloudDbSchema(DataBaseSchema &dataBaseSchema)
275     {
276         TableSchema tableSchema1 = {
277             .name = g_tableName1,
278             .sharedTableName = g_tableName1 + "_shared",
279             .fields = g_cloudFiled1
280         };
281         TableSchema tableSchema2 = {
282             .name = g_tableName2,
283             .sharedTableName = g_tableName2 + "_shared",
284             .fields = g_cloudFiled2
285         };
286         TableSchema tableSchemaWithOutPrimaryKey = {
287             .name = g_tableName3,
288             .sharedTableName = g_tableName3 + "_shared",
289             .fields = g_cloudFiledWithOutPrimaryKey3
290         };
291         TableSchema tableSchema4 = {
292             .name = g_tableName4,
293             .sharedTableName = g_tableName4 + "_shared",
294             .fields = g_cloudFiled2
295         };
296         dataBaseSchema.tables.push_back(tableSchema1);
297         dataBaseSchema.tables.push_back(tableSchema2);
298         dataBaseSchema.tables.push_back(tableSchemaWithOutPrimaryKey);
299         dataBaseSchema.tables.push_back(tableSchema4);
300     }
301 
QueryCountCallback(void * data,int count,char ** colValue,char ** colName)302     int QueryCountCallback(void *data, int count, char **colValue, char **colName)
303     {
304         if (count != 1) {
305             return 0;
306         }
307         auto expectCount = reinterpret_cast<int64_t>(data);
308         EXPECT_EQ(strtol(colValue[0], nullptr, 10), expectCount); // 10: decimal
309         return 0;
310     }
311 
CheckCloudTotalCount(const std::vector<std::string> & tableNames,std::vector<int64_t> expectCounts)312     void CheckCloudTotalCount(const std::vector<std::string> &tableNames, std::vector<int64_t> expectCounts)
313     {
314         VBucket extend;
315         for (size_t i = 0; i < tableNames.size(); ++i) {
316             extend[CloudDbConstant::CURSOR_FIELD] = std::to_string(0);
317             int64_t realCount = 0;
318             std::vector<VBucket> data;
319             g_virtualCloudDb->Query(tableNames[i], extend, data);
320             for (size_t j = 0; j < data.size(); ++j) {
321                 auto entry = data[j].find(CloudDbConstant::DELETE_FIELD);
322                 if (entry != data[j].end() && std::get<bool>(entry->second)) {
323                     continue;
324                 }
325                 realCount++;
326             }
327             EXPECT_EQ(realCount, expectCounts[i]); // ExpectCount represents the total amount of cloud data.
328         }
329     }
330 
CheckCloudRecordNum(sqlite3 * & db,std::vector<std::string> tableList,std::vector<int> countList)331     void CheckCloudRecordNum(sqlite3 *&db, std::vector<std::string> tableList, std::vector<int> countList)
332     {
333         int i = 0;
334         for (const auto &tableName: tableList) {
335             std::string sql = "select count(*) from " + DBCommon::GetLogTableName(tableName) +" where device = 'cloud'";
336             sql += " and cloud_gid is not null and cloud_gid != '' and (flag & 0x2 = 0 or flag & 0x20 = 0);";
337             EXPECT_EQ(sqlite3_exec(db, sql.c_str(), QueryCountCallback,
338                 reinterpret_cast<void *>(countList[i]), nullptr), SQLITE_OK);
339             i++;
340         }
341     }
342 
CheckCompensatedNum(sqlite3 * & db,std::vector<std::string> tableList,std::vector<int> countList)343     void CheckCompensatedNum(sqlite3 *&db, std::vector<std::string> tableList, std::vector<int> countList)
344     {
345         int i = 0;
346         for (const auto &tableName: tableList) {
347             std::string sql = "select count(*) from " + DBCommon::GetLogTableName(tableName) +
348                 " where flag & 0x10 != 0;";
349             EXPECT_EQ(sqlite3_exec(db, sql.c_str(), QueryCountCallback,
350                 reinterpret_cast<void *>(countList[i]), nullptr), SQLITE_OK);
351             i++;
352         }
353     }
354 
CheckLocalLogCount(sqlite3 * & db,const std::vector<std::string> & tableList,const std::vector<int> & countList)355     void CheckLocalLogCount(sqlite3 *&db, const std::vector<std::string> &tableList, const std::vector<int> &countList)
356     {
357         int i = 0;
358         for (const auto &tableName: tableList) {
359             std::string sql = "select count(*) from " + DBCommon::GetLogTableName(tableName);
360             EXPECT_EQ(sqlite3_exec(db, sql.c_str(), QueryCountCallback,
361                 reinterpret_cast<void *>(countList[i]), nullptr), SQLITE_OK);
362             i++;
363         }
364     }
365 
CheckLogoutLogCount(sqlite3 * & db,const std::vector<std::string> & tableList,const std::vector<int> & countList)366     void CheckLogoutLogCount(sqlite3 *&db, const std::vector<std::string> &tableList, const std::vector<int> &countList)
367     {
368         int i = 0;
369         for (const auto &tableName: tableList) {
370             std::string sql = "select count(*) from " + DBCommon::GetLogTableName(tableName) +
371                 " where flag & 0x800 = 0x800";
372             EXPECT_EQ(sqlite3_exec(db, sql.c_str(), QueryCountCallback,
373                 reinterpret_cast<void *>(countList[i]), nullptr), SQLITE_OK);
374             i++;
375         }
376     }
377 
CheckCleanLogNum(sqlite3 * & db,const std::vector<std::string> tableList,int count)378     void CheckCleanLogNum(sqlite3 *&db, const std::vector<std::string> tableList, int count)
379     {
380         for (const auto &tableName: tableList) {
381             std::string sql1 = "select count(*) from " + DBCommon::GetLogTableName(tableName) +
382                 " where device = 'cloud';";
383             EXPECT_EQ(sqlite3_exec(db, sql1.c_str(), QueryCountCallback,
384                 reinterpret_cast<void *>(count), nullptr), SQLITE_OK);
385             std::string sql2 = "select count(*) from " + DBCommon::GetLogTableName(tableName) +
386                 " where cloud_gid " + " is not null and cloud_gid != '';";
387             EXPECT_EQ(sqlite3_exec(db, sql2.c_str(), QueryCountCallback,
388                 reinterpret_cast<void *>(count), nullptr), SQLITE_OK);
389             std::string sql3 = "select count(*) from " + DBCommon::GetLogTableName(tableName) +
390                 " where (flag & 0x02 = 0 or flag & 0x20 = 0);";
391             EXPECT_EQ(sqlite3_exec(db, sql3.c_str(), QueryCountCallback,
392                 reinterpret_cast<void *>(count), nullptr), SQLITE_OK);
393         }
394     }
395 
CheckCleanDataNum(sqlite3 * & db,const std::vector<std::string> & tableList,const std::vector<int> & countList)396     void CheckCleanDataNum(sqlite3 *&db, const std::vector<std::string> &tableList, const std::vector<int> &countList)
397     {
398         int i = 0;
399         for (const auto &tableName: tableList) {
400             std::string sql = "select count(*) from " + tableName;
401             EXPECT_EQ(sqlite3_exec(db, sql.c_str(), QueryCountCallback,
402                 reinterpret_cast<void *>(countList[i]), nullptr), SQLITE_OK);
403             i++;
404         }
405     }
406 
CheckCleanDataAndLogNum(sqlite3 * & db,const std::vector<std::string> tableList,int count,std::vector<int> localNum)407     void CheckCleanDataAndLogNum(sqlite3 *&db, const std::vector<std::string> tableList, int count,
408         std::vector<int> localNum)
409     {
410         int i = 0;
411         for (const auto &tableName: tableList) {
412             std::string sql1 = "select count(*) from " + DBCommon::GetLogTableName(tableName) +
413                 " where device = 'cloud';";
414             EXPECT_EQ(sqlite3_exec(db, sql1.c_str(), QueryCountCallback,
415                 reinterpret_cast<void *>(count), nullptr), SQLITE_OK);
416             std::string sql2 = "select count(*) from " + DBCommon::GetLogTableName(tableName) + " where cloud_gid "
417                 " is not null and cloud_gid != '';";
418             EXPECT_EQ(sqlite3_exec(db, sql2.c_str(), QueryCountCallback,
419                 reinterpret_cast<void *>(count), nullptr), SQLITE_OK);
420             std::string sql3 = "select count(*) from " + DBCommon::GetLogTableName(tableName) +
421                 " where (flag & 0x02 = 0 or flag & 0x20 = 0);";
422             EXPECT_EQ(sqlite3_exec(db, sql3.c_str(), QueryCountCallback,
423                 reinterpret_cast<void *>(count), nullptr), SQLITE_OK);
424             std::string local_sql = "select count(*) from " + tableName +";";
425             EXPECT_EQ(sqlite3_exec(db, local_sql.c_str(), QueryCountCallback,
426                 reinterpret_cast<void *>(localNum[i]), nullptr), SQLITE_OK);
427             i++;
428         }
429     }
430 
InitProcessForCleanCloudData1(const uint32_t & cloudCount,std::vector<SyncProcess> & expectProcess)431     void InitProcessForCleanCloudData1(const uint32_t &cloudCount, std::vector<SyncProcess> &expectProcess)
432     {
433         // cloudCount also means data count in one batch
434         expectProcess.clear();
435         std::vector<TableProcessInfo> infos;
436         uint32_t index = 1;
437         infos.push_back(TableProcessInfo{
438             FINISHED, {index, cloudCount, cloudCount, 0}, {0, 0, 0, 0}
439         });
440         infos.push_back(TableProcessInfo{
441             PREPARED, {0, 0, 0, 0}, {0, 0, 0, 0}
442         });
443 
444         infos.push_back(TableProcessInfo{
445             FINISHED, {index, cloudCount, cloudCount, 0}, {0, 0, 0, 0}
446         });
447         infos.push_back(TableProcessInfo{
448             FINISHED, {index, cloudCount, cloudCount, 0}, {0, 0, 0, 0}
449         });
450 
451         for (size_t i = 0; i < infos.size() / g_arrayHalfSub; ++i) {
452             SyncProcess syncProcess;
453             syncProcess.errCode = OK;
454             syncProcess.process = i == infos.size() ? FINISHED : PROCESSING;
455             syncProcess.tableProcess.insert_or_assign(g_tables[0], std::move(infos[g_arrayHalfSub * i]));
456             syncProcess.tableProcess.insert_or_assign(g_tables[1], std::move(infos[g_arrayHalfSub * i + 1]));
457             expectProcess.push_back(syncProcess);
458         }
459     }
460 
GetCallback(SyncProcess & syncProcess,CloudSyncStatusCallback & callback,std::vector<SyncProcess> & expectProcess)461     void GetCallback(SyncProcess &syncProcess, CloudSyncStatusCallback &callback,
462         std::vector<SyncProcess> &expectProcess)
463     {
464         g_syncIndex = 0;
465         callback = [&syncProcess, &expectProcess](const std::map<std::string, SyncProcess> &process) {
466             LOGI("devices size = %d", process.size());
467             ASSERT_EQ(process.size(), 1u);
468             syncProcess = std::move(process.begin()->second);
469             ASSERT_EQ(process.begin()->first, DEVICE_CLOUD);
470             ASSERT_NE(syncProcess.tableProcess.empty(), true);
471             LOGI("current sync process status:%d, db status:%d ", syncProcess.process, syncProcess.errCode);
472             std::for_each(g_tables.begin(), g_tables.end(), [&](const auto &item) {
473                 auto table1 = syncProcess.tableProcess.find(item);
474                 if (table1 != syncProcess.tableProcess.end()) {
475                     LOGI("table[%s], table process status:%d, [downloadInfo](batchIndex:%u, total:%u, successCount:%u, "
476                          "failCount:%u) [uploadInfo](batchIndex:%u, total:%u, successCount:%u,failCount:%u",
477                          item.c_str(), table1->second.process, table1->second.downLoadInfo.batchIndex,
478                          table1->second.downLoadInfo.total, table1->second.downLoadInfo.successCount,
479                          table1->second.downLoadInfo.failCount, table1->second.upLoadInfo.batchIndex,
480                          table1->second.upLoadInfo.total, table1->second.upLoadInfo.successCount,
481                          table1->second.upLoadInfo.failCount);
482                 }
483             });
484             if (expectProcess.empty()) {
485                 if (syncProcess.process == FINISHED) {
486                     g_processCondition.notify_one();
487                 }
488                 return;
489             }
490             ASSERT_LE(static_cast<size_t>(g_syncIndex), expectProcess.size());
491             for (size_t i = 0; i < g_tables.size() && static_cast<size_t>(g_syncIndex) < expectProcess.size(); ++i) {
492                 SyncProcess head = expectProcess[g_syncIndex];
493                 for (auto &expect : head.tableProcess) {
494                     auto real = syncProcess.tableProcess.find(expect.first);
495                     ASSERT_NE(real, syncProcess.tableProcess.end());
496                     EXPECT_EQ(expect.second.process, real->second.process);
497                     EXPECT_EQ(expect.second.downLoadInfo.batchIndex, real->second.downLoadInfo.batchIndex);
498                     EXPECT_EQ(expect.second.downLoadInfo.total, real->second.downLoadInfo.total);
499                     EXPECT_EQ(expect.second.downLoadInfo.successCount, real->second.downLoadInfo.successCount);
500                     EXPECT_EQ(expect.second.downLoadInfo.failCount, real->second.downLoadInfo.failCount);
501                     EXPECT_EQ(expect.second.upLoadInfo.batchIndex, real->second.upLoadInfo.batchIndex);
502                     EXPECT_EQ(expect.second.upLoadInfo.total, real->second.upLoadInfo.total);
503                     EXPECT_EQ(expect.second.upLoadInfo.successCount, real->second.upLoadInfo.successCount);
504                     EXPECT_EQ(expect.second.upLoadInfo.failCount, real->second.upLoadInfo.failCount);
505                 }
506             }
507             g_syncIndex++;
508             if (syncProcess.process == FINISHED) {
509                 g_processCondition.notify_one();
510             }
511         };
512     }
513 
CopySharedDataFromOriginalTable(sqlite3 * & db,const std::vector<std::string> & tableNames)514     void CopySharedDataFromOriginalTable(sqlite3 *&db, const std::vector<std::string> &tableNames)
515     {
516         for (const auto &tableName: tableNames) {
517             std::string sql = "INSERT OR REPLACE INTO " + tableName + CloudDbConstant::SHARED + " SELECT " +
518                 "*," + std::string(DBConstant::SQLITE_INNER_ROWID) + ",''" + " FROM " + tableName;
519             EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), SQLITE_OK);
520         }
521     }
522 
CheckCloudSharedRecordNum(sqlite3 * & db,std::vector<std::string> tableList,std::vector<int> countList)523     void CheckCloudSharedRecordNum(sqlite3 *&db, std::vector<std::string> tableList, std::vector<int> countList)
524     {
525         int i = 0;
526         for (const auto &tableName: tableList) {
527             std::string sql = "select count(*) from " + DBCommon::GetLogTableName(tableName);
528             EXPECT_EQ(sqlite3_exec(db, sql.c_str(), QueryCountCallback,
529                 reinterpret_cast<void *>(countList[i]), nullptr), SQLITE_OK);
530             sql = "select count(*) from " + tableName;
531             EXPECT_EQ(sqlite3_exec(db, sql.c_str(), QueryCountCallback,
532                 reinterpret_cast<void *>(countList[i]), nullptr), SQLITE_OK);
533             i++;
534         }
535     }
536 
WaitForSyncFinish(SyncProcess & syncProcess,const int64_t & waitTime)537     void WaitForSyncFinish(SyncProcess &syncProcess, const int64_t &waitTime)
538     {
539         std::unique_lock<std::mutex> lock(g_processMutex);
540         bool result = g_processCondition.wait_for(lock, std::chrono::seconds(waitTime), [&syncProcess]() {
541             return syncProcess.process == FINISHED;
542         });
543         ASSERT_EQ(result, true);
544         LOGD("-------------------sync end--------------");
545     }
546 
CloseDb()547     void CloseDb()
548     {
549         g_delegate->UnRegisterObserver(g_observer);
550         delete g_observer;
551         g_virtualCloudDb = nullptr;
552         if (g_delegate != nullptr) {
553             EXPECT_EQ(g_mgr.CloseStore(g_delegate), DBStatus::OK);
554             g_delegate = nullptr;
555         }
556     }
557 
558     class DistributedDBCloudInterfacesRelationalRemoveDeviceDataTest : public testing::Test {
559     public:
560         static void SetUpTestCase(void);
561         static void TearDownTestCase(void);
562         void SetUp();
563         void TearDown();
564     protected:
565         sqlite3 *db = nullptr;
566     };
567 
SetUpTestCase(void)568     void DistributedDBCloudInterfacesRelationalRemoveDeviceDataTest::SetUpTestCase(void)
569     {
570         DistributedDBToolsUnitTest::TestDirInit(g_testDir);
571         g_storePath = g_testDir + "/" + g_storeID + DB_SUFFIX;
572         LOGI("The test db is:%s", g_testDir.c_str());
573         RuntimeConfig::SetCloudTranslate(std::make_shared<VirtualCloudDataTranslate>());
574     }
575 
TearDownTestCase(void)576     void DistributedDBCloudInterfacesRelationalRemoveDeviceDataTest::TearDownTestCase(void)
577     {}
578 
SetUp(void)579     void DistributedDBCloudInterfacesRelationalRemoveDeviceDataTest::SetUp(void)
580     {
581         if (DistributedDBToolsUnitTest::RemoveTestDbFiles(g_testDir) != 0) {
582             LOGE("rm test db files error.");
583         }
584         DistributedDBToolsUnitTest::PrintTestCaseInfo();
585         LOGD("Test dir is %s", g_testDir.c_str());
586         db = RelationalTestUtils::CreateDataBase(g_storePath);
587         ASSERT_NE(db, nullptr);
588         CreateUserDBAndTable(db);
589         g_observer = new (std::nothrow) RelationalStoreObserverUnitTest();
590         ASSERT_NE(g_observer, nullptr);
591         ASSERT_EQ(g_mgr.OpenStore(g_storePath, g_storeID, RelationalStoreDelegate::Option { .observer = g_observer },
592             g_delegate), DBStatus::OK);
593         ASSERT_NE(g_delegate, nullptr);
594         ASSERT_EQ(g_delegate->CreateDistributedTable(g_tableName1, CLOUD_COOPERATION), DBStatus::OK);
595         ASSERT_EQ(g_delegate->CreateDistributedTable(g_tableName2, CLOUD_COOPERATION), DBStatus::OK);
596         ASSERT_EQ(g_delegate->CreateDistributedTable(g_tableName3, CLOUD_COOPERATION), DBStatus::OK);
597         g_virtualCloudDb = make_shared<VirtualCloudDb>();
598         g_virtualAssetLoader = make_shared<VirtualAssetLoader>();
599         g_syncProcess = {};
600         ASSERT_EQ(g_delegate->SetCloudDB(g_virtualCloudDb), DBStatus::OK);
601         ASSERT_EQ(g_delegate->SetIAssetLoader(g_virtualAssetLoader), DBStatus::OK);
602         // sync before setting cloud db schema,it should return SCHEMA_MISMATCH
603         Query query = Query::Select().FromTable(g_tables);
604         CloudSyncStatusCallback callback;
605         ASSERT_EQ(g_delegate->Sync({DEVICE_CLOUD}, SYNC_MODE_CLOUD_MERGE, query, callback, g_syncWaitTime),
606             DBStatus::SCHEMA_MISMATCH);
607         DataBaseSchema dataBaseSchema;
608         GetCloudDbSchema(dataBaseSchema);
609         ASSERT_EQ(g_delegate->SetCloudDbSchema(dataBaseSchema), DBStatus::OK);
610         communicatorAggregator_ = new (std::nothrow) VirtualCommunicatorAggregator();
611         ASSERT_TRUE(communicatorAggregator_ != nullptr);
612         RuntimeContext::GetInstance()->SetCommunicatorAggregator(communicatorAggregator_);
613     }
614 
TearDown(void)615     void DistributedDBCloudInterfacesRelationalRemoveDeviceDataTest::TearDown(void)
616     {
617         EXPECT_EQ(sqlite3_close_v2(db), SQLITE_OK);
618         if (DistributedDBToolsUnitTest::RemoveTestDbFiles(g_testDir) != 0) {
619             LOGE("rm test db files error.");
620         }
621         RuntimeContext::GetInstance()->SetCommunicatorAggregator(nullptr);
622         communicatorAggregator_ = nullptr;
623         RuntimeContext::GetInstance()->SetProcessSystemApiAdapter(nullptr);
624     }
625 
626 /*
627  * @tc.name: CleanCloudDataTest001
628  * @tc.desc: Test FLAG_ONLY mode of RemoveDeviceData, and invalid mode else.
629  * @tc.type: FUNC
630  * @tc.require:
631  * @tc.author: huangboxin
632  */
633 HWTEST_F(DistributedDBCloudInterfacesRelationalRemoveDeviceDataTest, CleanCloudDataTest001, TestSize.Level0)
634 {
635     int64_t paddingSize = 10;
636     int localCount = 10;
637     int cloudCount = 20;
638     InsertCloudTableRecord(0, cloudCount, paddingSize, false);
639     InsertUserTableRecord(db, 0, localCount, paddingSize, false);
640     Query query = Query::Select().FromTable(g_tables);
641     std::vector<SyncProcess> expectProcess;
642     InitProcessForCleanCloudData1(cloudCount, expectProcess);
643     CloudSyncStatusCallback callback;
644     GetCallback(g_syncProcess, callback, expectProcess);
645     ASSERT_EQ(g_delegate->Sync({DEVICE_CLOUD}, SYNC_MODE_CLOUD_FORCE_PULL, query, callback, g_syncWaitTime),
646         DBStatus::OK);
647     WaitForSyncFinish(g_syncProcess, g_syncWaitTime);
648     std::string device = "";
649     CheckCloudRecordNum(db, g_tables, {20, 20});
650     ASSERT_EQ(g_delegate->RemoveDeviceData(device, FLAG_ONLY), DBStatus::OK);
651     CheckCleanLogNum(db, g_tables, 0);
652 
653     ASSERT_EQ(g_delegate->RemoveDeviceData(device, ClearMode(BUTT + 1)), DBStatus::INVALID_ARGS);
654     ASSERT_EQ(g_delegate->RemoveDeviceData(device, ClearMode(-1)), DBStatus::INVALID_ARGS);
655 
656     CloseDb();
657 }
658 
659 /*
660  * @tc.name: CleanCloudDataTest002
661  * @tc.desc: Test FLAG_AND_DATA mode of RemoveDeviceData
662  * @tc.type: FUNC
663  * @tc.require:
664  * @tc.author: huangboxin
665  */
666 HWTEST_F(DistributedDBCloudInterfacesRelationalRemoveDeviceDataTest, CleanCloudDataTest002, TestSize.Level0)
667 {
668     int64_t paddingSize = 10;
669     int localCount = 10;
670     int cloudCount = 20;
671     InsertCloudTableRecord(0, cloudCount, paddingSize, false);
672     InsertUserTableRecord(db, 0, localCount, paddingSize, false);
673     Query query = Query::Select().FromTable(g_tables);
674     std::vector<SyncProcess> expectProcess;
675     InitProcessForCleanCloudData1(cloudCount, expectProcess);
676     CloudSyncStatusCallback callback;
677     GetCallback(g_syncProcess, callback, expectProcess);
678     ASSERT_EQ(g_delegate->Sync({DEVICE_CLOUD}, SYNC_MODE_CLOUD_FORCE_PULL, query, callback, g_syncWaitTime),
679         DBStatus::OK);
680     WaitForSyncFinish(g_syncProcess, g_syncWaitTime);
681     std::string device = "";
682     CheckCloudRecordNum(db, g_tables, {20, 20});    // 20 means cloud data num
683     ASSERT_EQ(g_delegate->RemoveDeviceData(device, FLAG_AND_DATA), DBStatus::OK);
684     CheckCleanDataAndLogNum(db, g_tables, 0, {localCount, 0});
685     CloseDb();
686 }
687 
688 /*
689  * @tc.name: CleanCloudDataTest003
690  * @tc.desc: Test FLAG_ONLY mode of RemoveDeviceData concurrently with Sync
691  * @tc.type: FUNC
692  * @tc.require:
693  * @tc.author: huangboxin
694  */
695 HWTEST_F(DistributedDBCloudInterfacesRelationalRemoveDeviceDataTest, CleanCloudDataTest003, TestSize.Level0)
696 {
697     /**
698      * @tc.steps: step1. make data: 10 records on local and 20 records on cloud
699      */
700     int64_t paddingSize = 10;
701     int localCount = 10;
702     int cloudCount = 20;
703     InsertCloudTableRecord(0, cloudCount, paddingSize, false);
704     InsertUserTableRecord(db, 0, localCount, paddingSize, false);
705     /**
706      * @tc.steps: step2. call Sync with cloud force pull strategy, and after that, local will has 20 records.
707      */
708     Query query = Query::Select().FromTable(g_tables);
709     std::vector<SyncProcess> expectProcess;
710     InitProcessForCleanCloudData1(cloudCount, expectProcess);
711     CloudSyncStatusCallback callback;
712     GetCallback(g_syncProcess, callback, expectProcess);
713     ASSERT_EQ(g_delegate->Sync({DEVICE_CLOUD}, SYNC_MODE_CLOUD_FORCE_PULL, query, callback, g_syncWaitTime),
714         DBStatus::OK);
715     WaitForSyncFinish(g_syncProcess, g_syncWaitTime);
716     CheckCloudRecordNum(db, g_tables, {20, 20});    // 20 means cloud data num
717 
718     /**
719      * @tc.steps: step3. insert 10 records into local, so local will has 20 local records and 20 cloud records.
720      */
721     InsertUserTableRecord(db, 21, localCount, paddingSize, false);  // 21 means insert start index
722     /**
723      * @tc.steps: step4. call RemoveDeviceData synchronize with Sync with cloud force push strategy.
724      */
725     g_syncProcess = {};
726     std::vector<SyncProcess> expectProcess2;
727     InitProcessForCleanCloudData1(cloudCount, expectProcess2);
728     CloudSyncStatusCallback callback2;
729     GetCallback(g_syncProcess, callback2, expectProcess2);
730     std::string device = "";
731 
__anonca7e63500502() 732     std::thread thread1([&]() {
733         ASSERT_EQ(g_delegate->RemoveDeviceData(device, FLAG_AND_DATA), DBStatus::OK);
734     });
__anonca7e63500602() 735     std::thread thread2([&]() {
736         ASSERT_EQ(g_delegate->Sync({DEVICE_CLOUD}, SYNC_MODE_CLOUD_FORCE_PULL, query, callback2, g_syncWaitTime),
737             DBStatus::OK);
738         LOGD("-------------------sync end--------------");
739     });
740     thread1.join();
741     thread2.join();
742     WaitForSyncFinish(g_syncProcess, g_syncWaitTime);
743     CheckCleanLogNum(db, g_tables, 20);
744     LOGD("================================== test clean cloud data 003 end ===================================");
745     CloseDb();
746 }
747 
InitGetCloudSyncTaskCountTest001(sqlite3 * & db)748 static void InitGetCloudSyncTaskCountTest001(sqlite3 *&db)
749 {
750     int64_t localCount = 20;
751     int64_t cloudCount = 10;
752     int64_t paddingSize = 100;
753     InsertUserTableRecord(db, 0, localCount, paddingSize, false);
754     InsertCloudTableRecord(0, cloudCount, paddingSize, false);
755 }
756 
GetSyncOption()757 static CloudSyncOption GetSyncOption()
758 {
759     CloudSyncOption option;
760     option.devices = {DEVICE_CLOUD};
761     std::vector<std::string> pk = {"test"};
762     option.query = Query::Select().From(g_tableName1).In("name", pk);
763     option.priorityTask = true;
764     option.waitTime = g_syncWaitTime;
765     return option;
766 }
767 
768 /*
769  * @tc.name: GetCloudSyncTaskCountTest001
770  * @tc.desc: Test FLAG_ONLY mode of RemoveDeviceData concurrently with Sync
771  * @tc.type: FUNC
772  * @tc.require:
773  * @tc.author: huangboxin
774  */
775 HWTEST_F(DistributedDBCloudInterfacesRelationalRemoveDeviceDataTest, GetCloudSyncTaskCountTest001, TestSize.Level0)
776 {
777     InitGetCloudSyncTaskCountTest001(db);
778     Query query = Query::Select().FromTable(g_tables);
779     std::mutex dataMutex1, dataMutex2;
780     std::condition_variable cv1, cv2;
781     bool finish1 = false, finish2 = false;
782     /**
783      * @tc.steps: step1. Call Sync once.
784      * @tc.expected: OK.
785      */
786     CloudSyncStatusCallback callback1 = [&dataMutex1, &cv1, &finish1](
__anonca7e63500702( const std::map<std::string, SyncProcess> &process) 787         const std::map<std::string, SyncProcess> &process) {
788         std::map<std::string, SyncProcess> syncProcess;
789         {
790             std::lock_guard<std::mutex> autoLock(dataMutex1);
791             syncProcess = process;
792             if (syncProcess[DEVICE_CLOUD].process == FINISHED) {
793                 finish1 = true;
794             }
795         }
796         cv1.notify_one();
797     };
798     /**
799      * @tc.steps: step2. Call Sync twice.
800      * @tc.expected: OK.
801      */
802     ASSERT_EQ(g_delegate->Sync({DEVICE_CLOUD}, SYNC_MODE_CLOUD_MERGE, query, callback1, g_syncWaitTime), DBStatus::OK);
803 
804     CloudSyncStatusCallback callback2 = [&dataMutex2, &cv2, &finish2](
__anonca7e63500802( const std::map<std::string, SyncProcess> &process) 805         const std::map<std::string, SyncProcess> &process) {
806         std::map<std::string, SyncProcess> syncProcess;
807         {
808             std::lock_guard<std::mutex> autoLock(dataMutex2);
809             syncProcess = process;
810             if (syncProcess[DEVICE_CLOUD].process == FINISHED) {
811                 finish2 = true;
812             }
813         }
814         cv2.notify_one();
815     };
816     ASSERT_EQ(g_delegate->Sync(GetSyncOption(), callback2), DBStatus::OK);
817     /**
818      * @tc.steps: step3. Call Get Cloud Sync Task Count
819      * @tc.expected: OK.
820      */
821     EXPECT_EQ(g_delegate->GetCloudSyncTaskCount(), 2);  // 2 is task count
822     /**
823      * @tc.steps: step3. Wait For Sync Task Finished
824      * @tc.expected: OK.
825      */
826     {
827         std::unique_lock<std::mutex> uniqueLock(dataMutex1);
__anonca7e63500902null828         cv1.wait(uniqueLock, [&finish1] {
829             return finish1;
830         });
831     }
832     {
833         std::unique_lock<std::mutex> uniqueLock(dataMutex2);
__anonca7e63500a02null834         cv2.wait(uniqueLock, [&finish2] {
835             return finish2;
836         });
837     }
838     CloseDb();
839 }
840 
841 /*
842  * @tc.name: CleanCloudDataTest004
843  * @tc.desc: Test  RemoveDeviceData when cloudSchema doesn't have local table
844  * @tc.type: FUNC
845  * @tc.require:
846  * @tc.author: huangboxin
847  */
848 HWTEST_F(DistributedDBCloudInterfacesRelationalRemoveDeviceDataTest, CleanCloudDataTest004, TestSize.Level0)
849 {
850     DataBaseSchema dataBaseSchema;
851     TableSchema tableSchema1 = {
852         .name = "table_not_existed",
853         .sharedTableName = "table_not_existed_shared",
854         .fields = g_cloudFiled1
855     };
856     dataBaseSchema.tables.push_back(tableSchema1);
857     GetCloudDbSchema(dataBaseSchema);
858     ASSERT_EQ(g_delegate->SetCloudDbSchema(dataBaseSchema), DBStatus::OK);
859     std::string device = "";
860     ASSERT_EQ(g_delegate->RemoveDeviceData(device, FLAG_AND_DATA), DBStatus::OK);
861     CloseDb();
862 }
863 
864 /*
865  * @tc.name: CleanCloudDataTest005
866  * @tc.desc: Test RemoveDeviceData when cloud data is deleted
867  * @tc.type: FUNC
868  * @tc.require:
869  * @tc.author: chenchaohao
870  */
871 HWTEST_F(DistributedDBCloudInterfacesRelationalRemoveDeviceDataTest, CleanCloudDataTest005, TestSize.Level0)
872 {
873     /**
874      * @tc.steps: step1. cloud and device data is same
875      * @tc.expected: OK.
876      */
877     int64_t paddingSize = 10; // 10 is padding size
878     int64_t cloudCount = 10; // 10 is cloud count
879     InsertCloudTableRecord(0, cloudCount, paddingSize, true);
880     CloudDBSyncUtilsTest::callSync(g_tables, SYNC_MODE_CLOUD_MERGE, DBStatus::OK, g_delegate);
881 
882     /**
883      * @tc.steps: step2. cloud delete data and merge
884      * @tc.expected: OK.
885      */
886     DeleteCloudTableRecordByGid(0, cloudCount);
887     CloudDBSyncUtilsTest::callSync(g_tables, SYNC_MODE_CLOUD_MERGE, DBStatus::OK, g_delegate);
888     CheckCloudRecordNum(db, g_tables, {0, 10}); // 10 is cloud record num in table2 log
889     CheckCloudTotalCount(g_tables, {0, 10}); // // 10 is cloud data num in table2
890 
891     /**
892      * @tc.steps: step3. removedevicedata FLAG_AND_DATA and check log
893      * @tc.expected: OK.
894      */
895     std::string device = "";
896     ASSERT_EQ(g_delegate->RemoveDeviceData(device, FLAG_AND_DATA), DBStatus::OK);
897     CheckCleanDataAndLogNum(db, g_tables, 0, {0, 0});
898     CloseDb();
899 }
900 
901 /*
902  * @tc.name: CleanCloudDataTest006
903  * @tc.desc: Test FLAG_ONLY mode of RemoveDeviceData before Sync
904  * @tc.type: FUNC
905  * @tc.require:
906  * @tc.author: zhangqiquan
907  */
908 HWTEST_F(DistributedDBCloudInterfacesRelationalRemoveDeviceDataTest, CleanCloudDataTest006, TestSize.Level0)
909 {
910     /**
911      * @tc.steps: step1. make data: 10 records on local
912      */
913     int64_t paddingSize = 10;
914     int localCount = 10;
915     InsertUserTableRecord(db, 0, localCount, paddingSize, false);
916     /**
917      * @tc.steps: step2. call Sync with cloud merge strategy, and after that, local will has 20 records.
918      */
919     CloudDBSyncUtilsTest::callSync(g_tables, SYNC_MODE_CLOUD_MERGE, DBStatus::OK, g_delegate);
920     LOGW("check 10-10");
921     CheckCloudTotalCount(g_tables, {10, 10}); // 10 is cloud data num in table2
922     g_virtualCloudDb->ClearAllData();
923     LOGW("check 0-0");
924     CheckCloudTotalCount(g_tables, {0, 0}); // 0 is cloud data num in table2
925     /**
926      * @tc.steps: step3. removedevicedata FLAG_AND_DATA and sync again
927      * @tc.expected: OK.
928      */
929     std::string device;
930     ASSERT_EQ(g_delegate->RemoveDeviceData(device, DistributedDB::FLAG_ONLY), DBStatus::OK);
931     CloudDBSyncUtilsTest::callSync(g_tables, SYNC_MODE_CLOUD_MERGE, DBStatus::OK, g_delegate);
932     LOGW("check 10-10");
933     CheckCloudTotalCount(g_tables, {10, 10}); // 10 is cloud data num in table2
934     CloseDb();
935 }
936 
937 /*
938  * @tc.name: CleanCloudDataTest007
939  * @tc.desc: Test CLEAR_SHARED_TABLE mode of RemoveDeviceData before Sync
940  * @tc.type: FUNC
941  * @tc.require:
942  * @tc.author: bty
943  */
944 HWTEST_F(DistributedDBCloudInterfacesRelationalRemoveDeviceDataTest, CleanCloudDataTest007, TestSize.Level0)
945 {
946     /**
947      * @tc.steps: step1. make data: 10 records on local
948      */
949     int64_t paddingSize = 1;
950     int localCount = 10;
951     InsertUserTableRecord(db, 0, localCount, paddingSize, false);
952     /**
953      * @tc.steps: step2. call Sync with cloud merge strategy, and after that, local will has 20 records.
954      */
955     CloudDBSyncUtilsTest::callSync(g_tables, SYNC_MODE_CLOUD_MERGE, DBStatus::OK, g_delegate);
956     CheckCloudTotalCount(g_tables, {10, 10}); // 10 is cloud data num
957     g_virtualCloudDb->ClearAllData();
958     CheckCloudTotalCount(g_tables, {0, 0});
959     /**
960      * @tc.steps: step3. removedevicedata in CLEAR_SHARED_TABLE mode will not delete unShare table data
961      * @tc.expected: OK.
962      */
963     std::string device;
964     ASSERT_EQ(g_delegate->RemoveDeviceData(device, DistributedDB::CLEAR_SHARED_TABLE), DBStatus::OK);
965     CloudDBSyncUtilsTest::callSync(g_tables, SYNC_MODE_CLOUD_MERGE, DBStatus::OK, g_delegate);
966     CheckCloudTotalCount(g_tables, {0, 0});
967     /**
968      * @tc.steps: step4. copy db data to share table,then sync to check total count
969      * @tc.expected: OK.
970      */
971     CopySharedDataFromOriginalTable(db, g_tables);
972     CloudDBSyncUtilsTest::callSync(g_shareTables, SYNC_MODE_CLOUD_MERGE, DBStatus::OK, g_delegate);
973     CheckCloudTotalCount(g_tables, {0, 0});
974     CheckCloudTotalCount(g_shareTables, {10, 10}); // 10 is cloud data num
975     g_virtualCloudDb->ClearAllData();
976     CheckCloudTotalCount(g_shareTables, {0, 0});
977     /**
978      * @tc.steps: step5. removedevicedata in CLEAR_SHARED_TABLE mode,then sync and check data
979      * @tc.expected: OK.
980      */
981     ASSERT_EQ(g_delegate->RemoveDeviceData(device, DistributedDB::CLEAR_SHARED_TABLE), DBStatus::OK);
982     CheckCloudSharedRecordNum(db, g_shareTables, {0, 0, 0, 0});
983     CloudDBSyncUtilsTest::callSync(g_shareTables, SYNC_MODE_CLOUD_MERGE, DBStatus::OK, g_delegate);
984     CheckCloudTotalCount(g_shareTables, {0, 0});
985     CloseDb();
986 }
987 
988 /*
989  * @tc.name: CleanCloudDataTest008
990  * @tc.desc: Test CLEAR_SHARED_TABLE mode of RemoveDeviceData after close DB
991  * @tc.type: FUNC
992  * @tc.require:
993  * @tc.author: chenchaohao
994  */
995 HWTEST_F(DistributedDBCloudInterfacesRelationalRemoveDeviceDataTest, CleanCloudDataTest008, TestSize.Level0)
996 {
997     /**
998      * @tc.steps: step1. make data: 10 records on local
999      */
1000     int64_t paddingSize = 1;
1001     int localCount = 10;
1002     InsertUserTableRecord(db, 0, localCount, paddingSize, false);
1003     /**
1004      * @tc.steps: step2. call Sync with cloud merge strategy, and after that, local will has 20 records.
1005      */
1006     CloudDBSyncUtilsTest::callSync(g_tables, SYNC_MODE_CLOUD_MERGE, DBStatus::OK, g_delegate);
1007     CheckCloudTotalCount(g_tables, {10, 10}); // 10 is cloud data num
1008     g_virtualCloudDb->ClearAllData();
1009     CheckCloudTotalCount(g_tables, {0, 0});
1010     /**
1011      * @tc.steps: step3. removedevicedata in CLEAR_SHARED_TABLE mode will not delete unShare table data
1012      * @tc.expected: OK.
1013      */
1014     std::string device;
1015     ASSERT_EQ(g_delegate->RemoveDeviceData(device, DistributedDB::CLEAR_SHARED_TABLE), DBStatus::OK);
1016     CloudDBSyncUtilsTest::callSync(g_tables, SYNC_MODE_CLOUD_MERGE, DBStatus::OK, g_delegate);
1017     CheckCloudTotalCount(g_tables, {0, 0});
1018     /**
1019      * @tc.steps: step4. copy db data to share table,then sync to check total count
1020      * @tc.expected: OK.
1021      */
1022     CopySharedDataFromOriginalTable(db, g_tables);
1023     CloudDBSyncUtilsTest::callSync(g_shareTables, SYNC_MODE_CLOUD_MERGE, DBStatus::OK, g_delegate);
1024     CheckCloudTotalCount(g_tables, {0, 0});
1025     CheckCloudTotalCount(g_shareTables, {10, 10}); // 10 is cloud data num
1026     g_virtualCloudDb->ClearAllData();
1027     CheckCloudTotalCount(g_shareTables, {0, 0});
1028     /**
1029      * @tc.steps: step5. removedevicedata in CLEAR_SHARED_TABLE mode after close db, then sync and check data
1030      * @tc.expected: OK.
1031      */
1032     CloseDb();
1033     g_observer = new (std::nothrow) RelationalStoreObserverUnitTest();
1034     ASSERT_NE(g_observer, nullptr);
1035     ASSERT_EQ(g_mgr.OpenStore(g_storePath, g_storeID, RelationalStoreDelegate::Option { .observer = g_observer },
1036         g_delegate), DBStatus::OK);
1037     ASSERT_NE(g_delegate, nullptr);
1038     ASSERT_EQ(g_delegate->RemoveDeviceData(device, DistributedDB::CLEAR_SHARED_TABLE), DBStatus::OK);
1039     CheckCloudSharedRecordNum(db, g_shareTables, {0, 0, 0, 0});
1040     CloseDb();
1041 }
1042 
1043 /*
1044  * @tc.name: CleanCloudDataTest008
1045  * @tc.desc: Test RemoveDeviceData after Sync
1046  * @tc.type: FUNC
1047  * @tc.require:
1048  * @tc.author: zhangqiquan
1049  */
1050 HWTEST_F(DistributedDBCloudInterfacesRelationalRemoveDeviceDataTest, CleanCloudDataTest009, TestSize.Level0)
1051 {
1052     /**
1053      * @tc.steps: step1. make data: 10 records on local
1054      */
1055     int64_t paddingSize = 10;
1056     int localCount = 10;
1057     InsertUserTableRecord(db, 0, localCount, paddingSize, false);
1058     /**
1059      * @tc.steps: step2. call Sync with cloud merge strategy, and after that, local will has 10 records.
1060      */
1061     CloudDBSyncUtilsTest::callSync(g_tables, SYNC_MODE_CLOUD_MERGE, DBStatus::OK, g_delegate);
1062     LOGW("check 10-10");
1063     CheckCloudTotalCount(g_tables, {10, 10}); // 10 is cloud data num in table2
1064     /**
1065      * @tc.steps: step3. remove cloud and sync again
1066      * @tc.expected: OK.
1067      */
1068     DeleteCloudTableRecordByGid(0, localCount);
1069     CloudDBSyncUtilsTest::callSync(g_tables, SYNC_MODE_CLOUD_MERGE, DBStatus::OK, g_delegate);
1070     g_delegate->RemoveDeviceData();
1071     CheckLocalLogCount(db, { g_tableName1 }, { localCount });
1072     CloseDb();
1073 }
1074 
1075 /*
1076  * @tc.name: CleanCloudDataTest010
1077  * @tc.desc: Test if log is delete when removedevicedata after sync
1078  * @tc.type: FUNC
1079  * @tc.require:
1080  * @tc.author: chenchaohao
1081  */
1082 HWTEST_F(DistributedDBCloudInterfacesRelationalRemoveDeviceDataTest, CleanCloudDataTest010, TestSize.Level0)
1083 {
1084     /**
1085      * @tc.steps: step1. make data: 10 records on local
1086      */
1087     int64_t paddingSize = 10;
1088     int localCount = 10;
1089     InsertUserTableRecord(db, 0, localCount, paddingSize, false);
1090     /**
1091      * @tc.steps: step2. call Sync with cloud merge strategy, and after that, local will has 10 records.
1092      */
1093     CloudDBSyncUtilsTest::callSync(g_tables, SYNC_MODE_CLOUD_MERGE, DBStatus::OK, g_delegate);
1094     LOGW("check 10-10");
1095     CheckCloudTotalCount(g_tables, {10, 10}); // 10 is cloud data num in table2
1096     /**
1097      * @tc.steps: step3. remove cloud and sync again
1098      * @tc.expected: OK.
1099      */
1100     int deleteCount = 5;
1101     DeleteCloudTableRecordByGid(0, deleteCount);
1102     DeleteUserTableRecord(db, deleteCount, localCount);
1103     CloudDBSyncUtilsTest::callSync(g_tables, SYNC_MODE_CLOUD_MERGE, DBStatus::OK, g_delegate);
1104     std::string device;
1105     ASSERT_EQ(g_delegate->RemoveDeviceData(device, DistributedDB::FLAG_ONLY), DBStatus::OK);
1106     CheckLocalLogCount(db, { g_tableName1 }, { deleteCount });
1107     CloseDb();
1108 }
1109 
1110 /*
1111  * @tc.name: CleanCloudDataTest011
1112  * @tc.desc: Test if the version in the log table has been cleared after RemoveDeviceData.
1113  * @tc.type: FUNC
1114  * @tc.require:
1115  * @tc.author: liaoyonghuang
1116  */
1117 HWTEST_F(DistributedDBCloudInterfacesRelationalRemoveDeviceDataTest, CleanCloudDataTest011, TestSize.Level0)
1118 {
1119     /**
1120      * @tc.steps: step1. make data: 10 records on local
1121      */
1122     int64_t paddingSize = 10;
1123     int localCount = 10;
1124     InsertUserTableRecord(db, 0, localCount, paddingSize, false);
1125     std::string device;
1126     /**
1127      * @tc.steps: step2. call Sync with cloud merge strategy, and after that, local will has 10 records.
1128      */
1129     CloudDBSyncUtilsTest::callSync(g_tables, SYNC_MODE_CLOUD_MERGE, DBStatus::OK, g_delegate);
1130     LOGW("check 10-10");
1131     CheckCloudTotalCount(g_tables, {10, 10}); // 10 is cloud data num in table2
1132     /**
1133      * @tc.steps: step3. remove device data
1134      * @tc.expected: OK.
1135      */
1136     ASSERT_EQ(g_delegate->RemoveDeviceData(device, DistributedDB::FLAG_AND_DATA), DBStatus::OK);
1137     /**
1138      * @tc.steps: step4. Check if the version in the log table has been cleared.
1139      * @tc.expected: OK.
1140      */
1141     for (auto tableName : g_tables) {
1142         std::string sql = "select count(*) from " + DBCommon::GetLogTableName(tableName) +
1143             " where ((flag & 0x08 != 0) or cloud_gid is null or cloud_gid == '') and version != '';";
1144         EXPECT_EQ(sqlite3_exec(db, sql.c_str(), QueryCountCallback,
1145                     reinterpret_cast<void *>(0), nullptr), SQLITE_OK);
1146     }
1147     CloseDb();
1148 }
1149 
1150 /*
1151  * @tc.name: CleanCloudDataTest012
1152  * @tc.desc: Test modify data will not be deleted before upload to cloud when remove device data.
1153  * @tc.type: FUNC
1154  * @tc.require:
1155  * @tc.author: wangxiangdong
1156  */
1157 HWTEST_F(DistributedDBCloudInterfacesRelationalRemoveDeviceDataTest, CleanCloudDataTest012, TestSize.Level0)
1158 {
1159     /**
1160      * @tc.steps: step1. make data: 20 records on local
1161      */
1162     int64_t paddingSize = 20;
1163     int localCount = 20;
1164     InsertUserTableRecord(db, 0, localCount, paddingSize, false);
1165     /**
1166      * @tc.steps: step2. call Sync with cloud merge strategy, and after that, local will has 20 records.
1167      */
1168     CloudDBSyncUtilsTest::callSync(g_tables, SYNC_MODE_CLOUD_MERGE, DBStatus::OK, g_delegate);
1169     /**
1170      * @tc.steps: step3. modify local data
1171      * @tc.expected: OK.
1172      */
1173     InsertUserTableRecord(db, 20, localCount, paddingSize, false);
1174     UpdateUserTableRecord(db, 5, 10);
1175     DeleteUserTableRecord(db, 10, 15);
1176     /**
1177      * @tc.steps: step4. check cloud record data and remove device data.
1178      * @tc.expected: OK.
1179      */
1180     CheckCloudRecordNum(db, g_tables, {0, 0});
1181     std::string device;
1182     ASSERT_EQ(g_delegate->RemoveDeviceData(device, DistributedDB::FLAG_AND_DATA), DBStatus::OK);
1183     CheckCleanDataNum(db, g_tables, {25, 25});
1184     CheckLocalLogCount(db, g_tables, {30, 30});
1185     /**
1186      * @tc.steps: step5. do sync again and remove device data, then check local data and log.
1187      * @tc.expected: OK.
1188      */
1189     CloudDBSyncUtilsTest::callSync(g_tables, SYNC_MODE_CLOUD_MERGE, DBStatus::OK, g_delegate);
1190     ASSERT_EQ(g_delegate->RemoveDeviceData(device, DistributedDB::FLAG_AND_DATA), DBStatus::OK);
1191     CheckCleanDataNum(db, g_tables, {0, 0});
1192     CheckLocalLogCount(db, g_tables, {0, 0});
1193     CloseDb();
1194 }
1195 
1196 /*
1197  * @tc.name: CleanCloudDataTest013
1198  * @tc.desc: Test modify data will not be deleted before upload to cloud when remove device data when set logicDelete.
1199  * @tc.type: FUNC
1200  * @tc.require:
1201  * @tc.author: wangxiangdong
1202  */
1203 HWTEST_F(DistributedDBCloudInterfacesRelationalRemoveDeviceDataTest, CleanCloudDataTest013, TestSize.Level0)
1204 {
1205     /**
1206      * @tc.steps: step1. Set data is logicDelete
1207      */
1208     bool logicDelete = true;
1209     auto data = static_cast<PragmaData>(&logicDelete);
1210     g_delegate->Pragma(LOGIC_DELETE_SYNC_DATA, data);
1211     /**
1212      * @tc.steps: step2. make data: 20 records on local
1213      */
1214     int64_t paddingSize = 20;
1215     int localCount = 20;
1216     InsertUserTableRecord(db, 0, localCount, paddingSize, false);
1217     /**
1218      * @tc.steps: step3. call Sync with cloud merge strategy, and after that, local will has 20 records.
1219      */
1220     CloudDBSyncUtilsTest::callSync(g_tables, SYNC_MODE_CLOUD_MERGE, DBStatus::OK, g_delegate);
1221     /**
1222      * @tc.steps: step4. modify local data
1223      * @tc.expected: OK.
1224      */
1225     InsertUserTableRecord(db, 20, localCount, paddingSize, false);
1226     UpdateUserTableRecord(db, 5, 10);
1227     DeleteUserTableRecord(db, 10, 15);
1228     /**
1229      * @tc.steps: step5. check cloud record data and remove device data.
1230      * @tc.expected: OK.
1231      */
1232     CheckCloudRecordNum(db, g_tables, {0, 0});
1233     std::string device;
1234     ASSERT_EQ(g_delegate->RemoveDeviceData(device, DistributedDB::FLAG_AND_DATA), DBStatus::OK);
1235     CheckCleanDataNum(db, g_tables, {35, 35});
1236     CheckLocalLogCount(db, g_tables, {40, 40});
1237     /**
1238      * @tc.steps: step6. do sync again and remove device data, then check local data and log.
1239      * @tc.expected: OK.
1240      */
1241     CloudDBSyncUtilsTest::callSync(g_tables, SYNC_MODE_CLOUD_MERGE, DBStatus::OK, g_delegate);
1242     ASSERT_EQ(g_delegate->RemoveDeviceData(device, DistributedDB::FLAG_AND_DATA), DBStatus::OK);
1243     CheckCleanDataNum(db, g_tables, {40, 35});
1244     CheckLocalLogCount(db, g_tables, {40, 40});
1245     CloseDb();
1246 }
1247 
1248 /*
1249  * @tc.name: CleanCloudDataTest015
1250  * @tc.desc: Test get schema from db is ok when local has not been set.
1251  * @tc.type: FUNC
1252  * @tc.require:
1253  * @tc.author: wangxiangdong
1254 **/
1255 HWTEST_F(DistributedDBCloudInterfacesRelationalRemoveDeviceDataTest, CleanCloudDataTest015, TestSize.Level0)
1256 {
1257     /**
1258      * @tc.steps: step1. Set data is logicDelete
1259      */
1260     bool logicDelete = true;
1261     auto data = static_cast<PragmaData>(&logicDelete);
1262     g_delegate->Pragma(LOGIC_DELETE_SYNC_DATA, data);
1263     /**
1264      * @tc.steps: step2. make data: 10 records on local
1265      */
1266     int64_t paddingSize = 20;
1267     int localCount = 10;
1268     InsertUserTableRecord(db, 0, localCount, paddingSize, false);
1269     /**
1270      * @tc.steps: step3. call Sync with cloud merge strategy, and after that, local will has 20 records.
1271      */
1272     CloudDBSyncUtilsTest::callSync(g_tables, SYNC_MODE_CLOUD_MERGE, DBStatus::OK, g_delegate);
1273     /**
1274      * @tc.steps: step4. remove and check
1275      * @tc.expected: OK.
1276      */
1277     CheckCloudRecordNum(db, g_tables, {0, 0});
1278     std::string device;
1279     ASSERT_EQ(g_delegate->RemoveDeviceData(device, DistributedDB::FLAG_AND_DATA), DBStatus::OK);
1280     CheckCleanDataNum(db, g_tables, {10, 10});
1281     CheckLocalLogCount(db, g_tables, {10, 10});
1282     CheckLogoutLogCount(db, g_tables, {10, 10});
1283     CloseDb();
1284 }
1285 
1286 /*
1287  * @tc.name: CleanCloudDataTest016
1288  * @tc.desc: Test compensated flag should be clear after remove device data.
1289  * @tc.type: FUNC
1290  * @tc.require:
1291  * @tc.author: wangxiangdong
1292  */
1293 HWTEST_F(DistributedDBCloudInterfacesRelationalRemoveDeviceDataTest, CleanCloudDataTest016, TestSize.Level0)
1294 {
1295     /**
1296      * @tc.steps: step1. Set data is logicDelete
1297      */
1298     bool logicDelete = true;
1299     auto data = static_cast<PragmaData>(&logicDelete);
1300     g_delegate->Pragma(LOGIC_DELETE_SYNC_DATA, data);
1301     /**
1302      * @tc.steps: step2. make data: 20 records on local
1303      */
1304     int64_t paddingSize = 20;
1305     int localCount = 20;
1306     InsertUserTableRecord(db, 0, localCount, paddingSize, false);
1307     /**
1308      * @tc.steps: step3. make 2th data exist
1309      */
1310     int upIdx = 0;
__anonca7e63500b02(const std::string &tableName, VBucket &extend) 1311     g_virtualCloudDb->ForkUpload([&upIdx](const std::string &tableName, VBucket &extend) {
1312         LOGD("cloud db upload index:%d", ++upIdx);
1313         if (upIdx == 2) { // 2 is index
1314             extend[CloudDbConstant::ERROR_FIELD] = static_cast<int64_t>(DBStatus::CLOUD_RECORD_ALREADY_EXISTED);
1315         }
1316     });
1317     /**
1318      * @tc.steps: step4. call Sync with cloud merge strategy, and check flag before and after.
1319      */
1320     CloudDBSyncUtilsTest::callSync(g_tables, SYNC_MODE_CLOUD_MERGE, DBStatus::OK, g_delegate);
1321     g_virtualCloudDb->ForkUpload(nullptr);
1322     CheckCompensatedNum(db, g_tables, {1, 0});
1323 
1324     /**
1325      * @tc.steps: step5. remove device data and check flag do not has compensated.
1326      * @tc.expected: OK.
1327      */
1328     std::string device;
1329     ASSERT_EQ(g_delegate->RemoveDeviceData(device, DistributedDB::FLAG_ONLY), DBStatus::OK);
1330     CheckCompensatedNum(db, g_tables, {0, 0});
1331     CloseDb();
1332 }
1333 
1334 /*
1335  * @tc.name: CleanCloudDataTest018
1336  * @tc.desc: Test remove device data then sync, check cursor do not increase twice.
1337  * @tc.type: FUNC
1338  * @tc.require:
1339  * @tc.author: wangxiangdong
1340  */
1341 HWTEST_F(DistributedDBCloudInterfacesRelationalRemoveDeviceDataTest, CleanCloudDataTest018, TestSize.Level0)
1342 {
1343     /**
1344      * @tc.steps: step1. Set data is logicDelete
1345      */
1346     bool logicDelete = true;
1347     auto data = static_cast<PragmaData>(&logicDelete);
1348     g_delegate->Pragma(LOGIC_DELETE_SYNC_DATA, data);
1349     /**
1350      * @tc.steps: step2. make data: 10 records on local
1351      */
1352     int64_t paddingSize = 10;
1353     int localCount = 10;
1354     InsertUserTableRecord(db, 0, localCount, paddingSize, false);
1355     /**
1356      * @tc.steps: step3. call Sync with cloud merge strategy, and check flag before and after.
1357      */
1358     CloudDBSyncUtilsTest::callSync(g_tables, SYNC_MODE_CLOUD_MERGE, DBStatus::OK, g_delegate);
1359 
1360     /**
1361      * @tc.steps: step4. remove device data.
1362      * @tc.expected: OK.
1363      */
1364     std::string device;
1365     ASSERT_EQ(g_delegate->RemoveDeviceData(device, DistributedDB::FLAG_AND_DATA), DBStatus::OK);
1366     /**
1367      * @tc.steps: step5.call Sync then check cursor.
1368      */
1369     CloudDBSyncUtilsTest::callSync(g_tables, SYNC_MODE_CLOUD_MERGE, DBStatus::OK, g_delegate);
1370     std::string sql = "select count(*) from " + DBCommon::GetLogTableName(g_tables[0]) +
1371         " where cursor='40';";
1372     EXPECT_EQ(sqlite3_exec(db, sql.c_str(), CloudDBSyncUtilsTest::QueryCountCallback,
1373         reinterpret_cast<void *>(1), nullptr), SQLITE_OK);
1374     CloseDb();
1375 }
1376 
1377 /*
1378  * @tc.name: CleanCloudDataTest019
1379  * @tc.desc: Test deleted data  will increase normal.
1380  * @tc.type: FUNC
1381  * @tc.require:
1382  * @tc.author: wangxiangdong
1383  */
1384 HWTEST_F(DistributedDBCloudInterfacesRelationalRemoveDeviceDataTest, CleanCloudDataTest019, TestSize.Level0)
1385 {
1386     /**
1387      * @tc.steps: step1. make data: 20 records on local
1388      */
1389     int64_t paddingSize = 20;
1390     int localCount = 20;
1391     InsertUserTableRecord(db, 0, localCount, paddingSize, false);
1392     /**
1393      * @tc.steps: step2. call Sync with cloud merge strategy, and check flag before and after.
1394      */
1395     CloudDBSyncUtilsTest::callSync(g_tables, SYNC_MODE_CLOUD_MERGE, DBStatus::OK, g_delegate);
1396     /**
1397      * @tc.steps: step3.make logic delete and local delete then call Sync.
1398      */
1399     DeleteCloudTableRecordByGid(0, 5);
1400     CloudDBSyncUtilsTest::callSync(g_tables, SYNC_MODE_CLOUD_MERGE, DBStatus::OK, g_delegate);
1401     std::string sql = "select count(*) from " + DBCommon::GetLogTableName(g_tables[0]) +
1402         " where cursor='20';";
1403     EXPECT_EQ(sqlite3_exec(db, sql.c_str(), CloudDBSyncUtilsTest::QueryCountCallback,
1404         reinterpret_cast<void *>(1), nullptr), SQLITE_OK);
1405     CloseDb();
1406 }
1407 
1408 /*
1409  * @tc.name: CleanCloudDataTest021
1410  * @tc.desc: Test conflict, not found, exist errCode of cloudSpace will deal.
1411  * @tc.type: FUNC
1412  * @tc.require:
1413  * @tc.author: wangxiangdong
1414  */
1415 HWTEST_F(DistributedDBCloudInterfacesRelationalRemoveDeviceDataTest, CleanCloudDataTest021, TestSize.Level0)
1416 {
1417     /**
1418      * @tc.steps: step1. Set data is logicDelete
1419      */
1420     bool logicDelete = true;
1421     auto data = static_cast<PragmaData>(&logicDelete);
1422     g_delegate->Pragma(LOGIC_DELETE_SYNC_DATA, data);
1423     /**
1424      * @tc.steps: step2. make data: 20 records on local.
1425      */
1426     int64_t paddingSize = 20;
1427     int localCount = 20;
1428     InsertUserTableRecord(db, 0, localCount, paddingSize, false);
1429     /**
1430      * @tc.steps: step3. make 2-5th data errCode.
1431      */
1432     int upIdx = 0;
__anonca7e63500c02(const std::string &tableName, VBucket &extend) 1433     g_virtualCloudDb->ForkUpload([&upIdx](const std::string &tableName, VBucket &extend) {
1434         LOGD("cloud db upload index:%d", ++upIdx);
1435         if (upIdx == 2) {
1436             extend[CloudDbConstant::ERROR_FIELD] = static_cast<int64_t>(DBStatus::CLOUD_RECORD_ALREADY_EXISTED);
1437         }
1438         if (upIdx == 3) {
1439             extend[CloudDbConstant::ERROR_FIELD] = static_cast<int64_t>(DBStatus::CLOUD_RECORD_EXIST_CONFLICT);
1440         }
1441         if (upIdx == 4) {
1442             // CLOUD_RECORD_NOT_FOUND means cloud and terminal is consitenct
1443             extend[CloudDbConstant::ERROR_FIELD] = static_cast<int64_t>(DBStatus::CLOUD_RECORD_NOT_FOUND);
1444         }
1445         if (upIdx == 5) {
1446             // CLOUD_RECORD_NOT_FOUND means no error
1447             extend[CloudDbConstant::ERROR_FIELD] = std::string("x");
1448         }
1449     });
1450     /*
1451      * @tc.steps: step4. call Sync, and check consitency.
1452      */
1453     CloudDBSyncUtilsTest::callSync(g_tables, SYNC_MODE_CLOUD_MERGE, DBStatus::OK, g_delegate);
1454     g_virtualCloudDb->ForkUpload(nullptr);
1455     std::string sql = "select count() from " + DBCommon::GetLogTableName(g_tables[0]) +
1456         " where flag & 0x20 = 0;";
1457     EXPECT_EQ(sqlite3_exec(db, sql.c_str(), CloudDBSyncUtilsTest::QueryCountCallback,
1458         reinterpret_cast<void *>(18), nullptr), SQLITE_OK);
1459     CloseDb();
1460 }
1461 
1462 /*
1463  * @tc.name: CleanCloudDataTest022
1464  * @tc.desc: Test deleted data and flag_and_data mode, flag have no logout.
1465  * @tc.type: FUNC
1466  * @tc.require:
1467  * @tc.author: wangxiangdong
1468  */
1469 HWTEST_F(DistributedDBCloudInterfacesRelationalRemoveDeviceDataTest, CleanCloudDataTest022, TestSize.Level0)
1470 {
1471     /**
1472      * @tc.steps: step1. make data: 20 records on local
1473      */
1474     int64_t paddingSize = 20;
1475     int localCount = 20;
1476     InsertUserTableRecord(db, 0, localCount, paddingSize, false);
1477     /**
1478      * @tc.steps: step2. call Sync with cloud merge strategy, and check flag before and after.
1479      */
1480     CloudDBSyncUtilsTest::callSync(g_tables, SYNC_MODE_CLOUD_MERGE, DBStatus::OK, g_delegate);
1481     /**
1482      * @tc.steps: step3. make local delete then call Sync.
1483      */
1484     DeleteUserTableRecord(db, 0, 5);
1485     /**
1486      * @tc.steps: step4. remove device data and check flag has no logout.
1487      * @tc.expected: OK.
1488      */
1489     std::string device;
1490     ASSERT_EQ(g_delegate->RemoveDeviceData(device, DistributedDB::FLAG_AND_DATA), DBStatus::OK);
1491     std::string sql = "select count(*) from " + DBCommon::GetLogTableName(g_tables[0]) +
1492         " where flag & 0x800 == 0;";
1493     EXPECT_EQ(sqlite3_exec(db, sql.c_str(), CloudDBSyncUtilsTest::QueryCountCallback,
1494         reinterpret_cast<void *>(5), nullptr), SQLITE_OK);
1495     sql = "select count(*) from " + DBCommon::GetLogTableName(g_tables[0]) +
1496         " where flag & 0x800 != 0;";
1497     EXPECT_EQ(sqlite3_exec(db, sql.c_str(), CloudDBSyncUtilsTest::QueryCountCallback,
1498         reinterpret_cast<void *>(0), nullptr), SQLITE_OK);
1499     CloseDb();
1500 }
1501 
1502 /*
1503  * @tc.name: CleanCloudDataTest026
1504  * @tc.desc: Test logic deleted data and flag_only.
1505  * @tc.type: FUNC
1506  * @tc.require:
1507  * @tc.author: wangxiangdong
1508  */
1509 HWTEST_F(DistributedDBCloudInterfacesRelationalRemoveDeviceDataTest, CleanCloudDataTest026, TestSize.Level0)
1510 {
1511     /**
1512      * @tc.steps: step1. Set data is logicDelete
1513      * @tc.expected: OK.
1514      */
1515     bool logicDelete = true;
1516     auto data = static_cast<PragmaData>(&logicDelete);
1517     g_delegate->Pragma(LOGIC_DELETE_SYNC_DATA, data);
1518     /**
1519      * @tc.steps: step2. make data: 20 records on cloud
1520      * @tc.expected: OK.
1521      */
1522     int64_t paddingSize = 20;
1523     int cloudCount = 20;
1524     InsertCloudTableRecord(0, cloudCount, paddingSize, false);
1525     /**
1526      * @tc.steps: step3. call Sync with cloud merge strategy.
1527      * @tc.expected: OK.
1528      */
1529     CloudDBSyncUtilsTest::callSync(g_tables, SYNC_MODE_CLOUD_MERGE, DBStatus::OK, g_delegate);
1530     /**
1531      * @tc.steps: step4. after remove device data and check log num.
1532      * @tc.expected: OK.
1533      */
1534     std::string device;
1535     ASSERT_EQ(g_delegate->RemoveDeviceData(device, DistributedDB::FLAG_ONLY), DBStatus::OK);
1536     std::string sql = "select count(*) from " + DBCommon::GetLogTableName(g_tables[0]) +
1537         " where flag & 0x02 == 0x02;";
1538     EXPECT_EQ(sqlite3_exec(db, sql.c_str(), CloudDBSyncUtilsTest::QueryCountCallback,
1539         reinterpret_cast<void *>(0), nullptr), SQLITE_OK);
1540     CloseDb();
1541 }
1542 
1543 /*
1544  * @tc.name: CleanCloudDataTest027
1545  * @tc.desc: Test flag_only not logic delete.
1546  * @tc.type: FUNC
1547  * @tc.require:
1548  * @tc.author: wangxiangdong
1549  */
1550 HWTEST_F(DistributedDBCloudInterfacesRelationalRemoveDeviceDataTest, CleanCloudDataTest027, TestSize.Level0)
1551 {
1552     /**
1553      * @tc.steps: step1. make data: 20 records on cloud
1554      * @tc.expected: OK.
1555      */
1556     int64_t paddingSize = 20;
1557     int cloudCount = 20;
1558     InsertCloudTableRecord(0, cloudCount, paddingSize, false);
1559     /**
1560      * @tc.steps: step2. call Sync with cloud merge strategy.
1561      * @tc.expected: OK.
1562      */
1563     CloudDBSyncUtilsTest::callSync(g_tables, SYNC_MODE_CLOUD_MERGE, DBStatus::OK, g_delegate);
1564     /**
1565      * @tc.steps: step3. after remove device data and check log num.
1566      * @tc.expected: OK.
1567      */
1568     std::string device;
1569     ASSERT_EQ(g_delegate->RemoveDeviceData(device, DistributedDB::FLAG_ONLY), DBStatus::OK);
1570     std::string sql = "select count(*) from " + DBCommon::GetLogTableName(g_tables[0]) +
1571         " where flag & 0x02 == 0x02;";
1572     EXPECT_EQ(sqlite3_exec(db, sql.c_str(), CloudDBSyncUtilsTest::QueryCountCallback,
1573         reinterpret_cast<void *>(cloudCount), nullptr), SQLITE_OK);
1574     CloseDb();
1575 }
1576 
1577 /*
1578  * @tc.name: CleanCloudDataTest025
1579  * @tc.desc: Test sync after dropping logic deleted device data, cursor do not decrease.
1580  * @tc.type: FUNC
1581  * @tc.require:
1582  * @tc.author: suyuchen
1583  */
1584 HWTEST_F(DistributedDBCloudInterfacesRelationalRemoveDeviceDataTest, CleanCloudDataTest025, TestSize.Level0)
1585 {
1586     /**
1587      * @tc.steps: step1. Set logicDelete
1588      */
1589     bool logicDelete = true;
1590     auto data = static_cast<PragmaData>(&logicDelete);
1591     g_delegate->Pragma(LOGIC_DELETE_SYNC_DATA, data);
1592 
1593     /**
1594      * @tc.steps: step2. insert 10 records locally, then sync to cloud
1595      */
1596     int64_t paddingSize = 10;
1597     int localCount = 10;
1598     InsertUserTableRecord(db, 0, localCount, paddingSize, false);
1599     CloudDBSyncUtilsTest::callSync(g_tables, SYNC_MODE_CLOUD_MERGE, DBStatus::OK, g_delegate);
1600 
1601     /**
1602      * @tc.steps: step3. logic delete record 1 and 2 from cloud, then sync
1603      */
1604     DeleteCloudTableRecordByGid(0, 2);
1605     CloudDBSyncUtilsTest::callSync(g_tables, SYNC_MODE_CLOUD_MERGE, DBStatus::OK, g_delegate);
1606 
1607     /**
1608      * @tc.steps: step4. clear logically deleted data
1609      */
1610     DropLogicDeletedData(db, g_tables[0], 0);
1611 
1612     /**
1613      * @tc.steps: step5. logic delete record 3 from cloud, then sync
1614      */
1615     DeleteCloudTableRecordByGid(3, 1);
1616     CloudDBSyncUtilsTest::callSync(g_tables, SYNC_MODE_CLOUD_MERGE, DBStatus::OK, g_delegate);
1617 
1618     /**
1619      * @tc.steps: step6. check cursor
1620      */
1621     std::string sql = "select count(*) from " + DBCommon::GetLogTableName(g_tables[0]) +
1622         " where cursor='13';";
1623     EXPECT_EQ(sqlite3_exec(db, sql.c_str(), CloudDBSyncUtilsTest::QueryCountCallback,
1624         reinterpret_cast<void *>(1), nullptr), SQLITE_OK);
1625 
1626     CloseDb();
1627 }
1628 
1629 /*
1630  * @tc.name: CleanCloudDataTest028
1631  * @tc.desc: Test flag_only and logic delete.
1632  * @tc.type: FUNC
1633  * @tc.require:
1634  * @tc.author: wangxiangdong
1635  */
1636 HWTEST_F(DistributedDBCloudInterfacesRelationalRemoveDeviceDataTest, CleanCloudDataTest028, TestSize.Level0)
1637 {
1638     /**
1639      * @tc.steps: step1. Set data is logicDelete
1640      * @tc.expected: OK.
1641      */
1642     bool logicDelete = true;
1643     auto data = static_cast<PragmaData>(&logicDelete);
1644     g_delegate->Pragma(LOGIC_DELETE_SYNC_DATA, data);
1645     /**
1646      * @tc.steps: step2. make data: 20 records on cloud
1647      * @tc.expected: OK.
1648      */
1649     int64_t paddingSize = 20;
1650     int cloudCount = 20;
1651     InsertCloudTableRecord(0, cloudCount, paddingSize, false);
1652     /**
1653      * @tc.steps: step3. call Sync with cloud merge strategy.
1654      * @tc.expected: OK.
1655      */
1656     CloudDBSyncUtilsTest::callSync(g_tables, SYNC_MODE_CLOUD_MERGE, DBStatus::OK, g_delegate);
1657     /**
1658      * @tc.steps: step4. after remove device data and check log num.
1659      * @tc.expected: OK.
1660      */
1661     std::string device;
1662     ASSERT_EQ(g_delegate->RemoveDeviceData(device, DistributedDB::FLAG_ONLY), DBStatus::OK);
1663     std::string sql = "select count(*) from " + DBCommon::GetLogTableName(g_tables[0]) +
1664         " where flag & 0x02 == 0x02;";
1665     EXPECT_EQ(sqlite3_exec(db, sql.c_str(), CloudDBSyncUtilsTest::QueryCountCallback,
1666         reinterpret_cast<void *>(0), nullptr), SQLITE_OK);
1667     /**
1668      * @tc.steps: step5. call Sync with cloud merge strategy after delete by cloud.
1669      * @tc.expected: OK.
1670      */
1671     DeleteCloudTableRecordByGid(0, 2);
1672     CloudDBSyncUtilsTest::callSync(g_tables, SYNC_MODE_CLOUD_MERGE, DBStatus::OK, g_delegate);
1673 
1674     /**
1675      * @tc.steps: step6. call Sync with cloud merge strategy.
1676      * @tc.expected: OK.
1677      */
1678     DeleteCloudTableRecordByGid(4, 2);
1679     CloudDBSyncUtilsTest::callSync(g_tables, SYNC_MODE_CLOUD_MERGE, DBStatus::OK, g_delegate);
1680     sql = "select count(*) from " + DBCommon::GetLogTableName(g_tables[0]) +
1681         " where cloud_gid = '';";
1682     EXPECT_EQ(sqlite3_exec(db, sql.c_str(), CloudDBSyncUtilsTest::QueryCountCallback,
1683         reinterpret_cast<void *>(2), nullptr), SQLITE_OK);
1684     CheckCloudTotalCount(g_tables, {18, 20});
1685     CloseDb();
1686 }
1687 }
1688 #endif // RELATIONAL_STORE
1689