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