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