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