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