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, 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, 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.Level0) 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, dataInfoWithLog, assetInfo), expectCode); 550 EXPECT_EQ(storageProxy->Commit(), E_OK); 551 } 552 553 /** 554 * @tc.name: GetInfoByPrimaryKeyOrGidTest014 555 * @tc.desc: Test collate nocase for primary key(NOCASE followed by ','), case mismatch 556 * @tc.type: FUNC 557 * @tc.require: 558 * @tc.author: zhangshijie 559 */ 560 HWTEST_F(DistributedDBCloudSaveCloudDataTest, GetInfoByPrimaryKeyOrGidTest014, TestSize.Level0) 561 { 562 std::string createSql = "create table " + g_tableName + "(name text primary key COLLATE NOCASE, age text);"; 563 std::string insertSql = "insert into " + g_tableName + " values('abcd', '10');"; 564 std::vector<std::string> pkStr = { "aBcD" }; 565 PrimaryKeyCollateTest(createSql, insertSql, pkStr, false); 566 } 567 568 /** 569 * @tc.name: GetInfoByPrimaryKeyOrGidTest015 570 * @tc.desc: Test collate nocase for primary key, case match 571 * @tc.type: FUNC 572 * @tc.require: 573 * @tc.author: zhangshijie 574 */ 575 HWTEST_F(DistributedDBCloudSaveCloudDataTest, GetInfoByPrimaryKeyOrGidTest015, TestSize.Level0) 576 { 577 std::string createSql = "create table " + g_tableName + "(name text primary key COLLATE NOCASE, age text);"; 578 std::string insertSql = "insert into " + g_tableName + " values('abcd', '10');"; 579 std::vector<std::string> pkStr = { "abcd" }; 580 PrimaryKeyCollateTest(createSql, insertSql, pkStr, false); 581 } 582 583 /** 584 * @tc.name: GetInfoByPrimaryKeyOrGidTest016 585 * @tc.desc: Test collate nocase for primary key(NOCASE followed by ')'), case mismatch 586 * @tc.type: FUNC 587 * @tc.require: 588 * @tc.author: zhangshijie 589 */ 590 HWTEST_F(DistributedDBCloudSaveCloudDataTest, GetInfoByPrimaryKeyOrGidTest016, TestSize.Level0) 591 { 592 std::string createSql = "create table " + g_tableName + "(name text primary key COLLATE NOCASE);"; 593 std::string insertSql = "insert into " + g_tableName + " values('abcd');"; 594 std::vector<std::string> pkStr = { "aBcD" }; 595 PrimaryKeyCollateTest(createSql, insertSql, pkStr, false); 596 } 597 598 /** 599 * @tc.name: GetInfoByPrimaryKeyOrGidTest017 600 * @tc.desc: Test collate nocase for primary key(NOCASE followed by ' '), case mismatch 601 * @tc.type: FUNC 602 * @tc.require: 603 * @tc.author: zhangshijie 604 */ 605 HWTEST_F(DistributedDBCloudSaveCloudDataTest, GetInfoByPrimaryKeyOrGidTest017, TestSize.Level0) 606 { 607 std::string createSql = "create table " + g_tableName + "(name text primary key COLLATE NOCASE , age int);"; 608 std::string insertSql = "insert into " + g_tableName + " values('abcd', 10);"; 609 std::vector<std::string> pkStr = { "aBcD" }; 610 PrimaryKeyCollateTest(createSql, insertSql, pkStr, false); 611 } 612 613 /** 614 * @tc.name: GetInfoByPrimaryKeyOrGidTest018 615 * @tc.desc: Test collate nocase NOT for primary key, case mismatch 616 * @tc.type: FUNC 617 * @tc.require: 618 * @tc.author: zhangshijie 619 */ 620 HWTEST_F(DistributedDBCloudSaveCloudDataTest, GetInfoByPrimaryKeyOrGidTest018, TestSize.Level0) 621 { 622 std::string createSql = "create table " + g_tableName + "(name text primary key, age TEXT COLLATE NOCASE);"; 623 std::string insertSql = "insert into " + g_tableName + " values('abcd', '10');"; 624 std::vector<std::string> pkStr = { "aBcD" }; 625 PrimaryKeyCollateTest(createSql, insertSql, pkStr, false, -E_NOT_FOUND); 626 } 627 628 /** 629 * @tc.name: GetInfoByPrimaryKeyOrGidTest019 630 * @tc.desc: Test collate nocase for one primary key, one pk case mismatch 631 * @tc.type: FUNC 632 * @tc.require: 633 * @tc.author: zhangshijie 634 */ 635 HWTEST_F(DistributedDBCloudSaveCloudDataTest, GetInfoByPrimaryKeyOrGidTest019, TestSize.Level0) 636 { 637 std::string createSql = "create table " + g_tableName + "(NAME text collate NOCASE, age text," + 638 "primary key(name, age));"; 639 std::string insertSql = "insert into " + g_tableName + " values('abcd', 'ab');"; 640 std::vector<std::string> pkStr = { "aBcD", "ab" }; 641 PrimaryKeyCollateTest(createSql, insertSql, pkStr, true); 642 } 643 644 /** 645 * @tc.name: GetInfoByPrimaryKeyOrGidTest020 646 * @tc.desc: Test collate nocase for one primary key, two pk case mismatch 647 * @tc.type: FUNC 648 * @tc.require: 649 * @tc.author: zhangshijie 650 */ 651 HWTEST_F(DistributedDBCloudSaveCloudDataTest, GetInfoByPrimaryKeyOrGidTest020, TestSize.Level0) 652 { 653 std::string createSql = "create table " + g_tableName + "(NAME text collate NOCASE, age text," + 654 "primary key(name, age));"; 655 std::string insertSql = "insert into " + g_tableName + " values('abcd', 'aB');"; 656 std::vector<std::string> pkStr = { "aBcD", "AB" }; 657 PrimaryKeyCollateTest(createSql, insertSql, pkStr, true, -E_NOT_FOUND); 658 } 659 660 /** 661 * @tc.name: GetInfoByPrimaryKeyOrGidTest021 662 * @tc.desc: Test collate nocase for two primary key, two pk case mismatch 663 * @tc.type: FUNC 664 * @tc.require: 665 * @tc.author: zhangshijie 666 */ 667 HWTEST_F(DistributedDBCloudSaveCloudDataTest, GetInfoByPrimaryKeyOrGidTest021, TestSize.Level0) 668 { 669 std::string createSql = "create table " + g_tableName + "(NAME text collate NOCASE, age text collate nocase," + 670 "primary key(name, age));"; 671 std::string insertSql = "insert into " + g_tableName + " values('abcd', 'aB');"; 672 std::vector<std::string> pkStr = { "aBcD", "ab" }; 673 PrimaryKeyCollateTest(createSql, insertSql, pkStr, true); 674 } 675 676 /** 677 * @tc.name: GetInfoByPrimaryKeyOrGidTest022 678 * @tc.desc: Test collate rtrim for primary key(NOCASE followed by ','), trim mismatch 679 * @tc.type: FUNC 680 * @tc.require: 681 * @tc.author: zhangshijie 682 */ 683 HWTEST_F(DistributedDBCloudSaveCloudDataTest, GetInfoByPrimaryKeyOrGidTest022, TestSize.Level0) 684 { 685 std::string createSql = "create table " + g_tableName + "(name text primary key COLLATE RTRIM, age text);"; 686 std::string insertSql = "insert into " + g_tableName + " values('abcd ', '10');"; 687 std::vector<std::string> pkStr = { "abcd" }; 688 PrimaryKeyCollateTest(createSql, insertSql, pkStr, false); 689 } 690 691 /** 692 * @tc.name: GetInfoByPrimaryKeyOrGidTest023 693 * @tc.desc: Test collate nocase for primary key, trim match 694 * @tc.type: FUNC 695 * @tc.require: 696 * @tc.author: zhangshijie 697 */ 698 HWTEST_F(DistributedDBCloudSaveCloudDataTest, GetInfoByPrimaryKeyOrGidTest023, TestSize.Level0) 699 { 700 std::string createSql = "create table " + g_tableName + "(name text primary key COLLATE RTRIM, age text);"; 701 std::string insertSql = "insert into " + g_tableName + " values('abcd_', '10');"; 702 std::vector<std::string> pkStr = { "abcd_" }; 703 PrimaryKeyCollateTest(createSql, insertSql, pkStr, false); 704 } 705 706 /** 707 * @tc.name: GetInfoByPrimaryKeyOrGidTest024 708 * @tc.desc: Test collate rtrim for primary key(NOCASE followed by ')'), rtrim mismatch 709 * @tc.type: FUNC 710 * @tc.require: 711 * @tc.author: zhangshijie 712 */ 713 HWTEST_F(DistributedDBCloudSaveCloudDataTest, GetInfoByPrimaryKeyOrGidTest024, TestSize.Level0) 714 { 715 std::string createSql = "create table " + g_tableName + "(name text primary key COLLATE rtrim);"; 716 std::string insertSql = "insert into " + g_tableName + " values('abcd ');"; 717 std::vector<std::string> pkStr = { "abcd" }; 718 PrimaryKeyCollateTest(createSql, insertSql, pkStr, false); 719 } 720 721 /** 722 * @tc.name: GetInfoByPrimaryKeyOrGidTest025 723 * @tc.desc: Test collate rtrim NOT for primary key, rtrim mismatch 724 * @tc.type: FUNC 725 * @tc.require: 726 * @tc.author: zhangshijie 727 */ 728 HWTEST_F(DistributedDBCloudSaveCloudDataTest, GetInfoByPrimaryKeyOrGidTest025, TestSize.Level0) 729 { 730 std::string createSql = "create table " + g_tableName + "(name text primary key, age TEXT COLLATE rtrim);"; 731 std::string insertSql = "insert into " + g_tableName + " values('abcd ', '10');"; 732 std::vector<std::string> pkStr = { "abcd" }; 733 PrimaryKeyCollateTest(createSql, insertSql, pkStr, false, -E_NOT_FOUND); 734 } 735 736 /** 737 * @tc.name: GetInfoByPrimaryKeyOrGidTest026 738 * @tc.desc: Test collate rtrim for one primary key, one pk rtrim mismatch 739 * @tc.type: FUNC 740 * @tc.require: 741 * @tc.author: zhangshijie 742 */ 743 HWTEST_F(DistributedDBCloudSaveCloudDataTest, GetInfoByPrimaryKeyOrGidTest026, TestSize.Level0) 744 { 745 std::string createSql = "create table " + g_tableName + "(NAME text collate RTRIM, age text," + 746 "primary key(name, age));"; 747 std::string insertSql = "insert into " + g_tableName + " values('abcd ', 'ab');"; 748 std::vector<std::string> pkStr = { "abcd", "ab" }; 749 PrimaryKeyCollateTest(createSql, insertSql, pkStr, true); 750 } 751 752 /** 753 * @tc.name: GetInfoByPrimaryKeyOrGidTest026 754 * @tc.desc: Test collate rtrim for one primary key, two pk rttim mismatch 755 * @tc.type: FUNC 756 * @tc.require: 757 * @tc.author: zhangshijie 758 */ 759 HWTEST_F(DistributedDBCloudSaveCloudDataTest, GetInfoByPrimaryKeyOrGidTest027, TestSize.Level0) 760 { 761 std::string createSql = "create table " + g_tableName + "(NAME text collate rtrim, age text," + 762 "primary key(name, age));"; 763 std::string insertSql = "insert into " + g_tableName + " values('abcd ', 'aB ');"; 764 std::vector<std::string> pkStr = { "abcd", "aB" }; 765 PrimaryKeyCollateTest(createSql, insertSql, pkStr, true, -E_NOT_FOUND); 766 } 767 768 /** 769 * @tc.name: GetInfoByPrimaryKeyOrGidTest027 770 * @tc.desc: Test collate rtrim for two primary key, two pk rtrim mismatch 771 * @tc.type: FUNC 772 * @tc.require: 773 * @tc.author: zhangshijie 774 */ 775 HWTEST_F(DistributedDBCloudSaveCloudDataTest, GetInfoByPrimaryKeyOrGidTest028, TestSize.Level0) 776 { 777 std::string createSql = "create table " + g_tableName + "(NAME text collate rtrim, age text collate rtrim," + 778 "primary key(name, age));"; 779 std::string insertSql = "insert into " + g_tableName + " values('abcd ', 'ab');"; 780 std::vector<std::string> pkStr = { "abcd ", "ab " }; 781 PrimaryKeyCollateTest(createSql, insertSql, pkStr, true); 782 } 783 ConstructDownloadData(DownloadData & downloadData,GidType gidType,bool nullable,bool vBucketContains)784 void ConstructDownloadData(DownloadData &downloadData, GidType gidType, bool nullable, bool vBucketContains) 785 { 786 for (int i = 0; i < 7; i++) { // 7 is record counts 787 VBucket vBucket; 788 if (i == 3) { // 3 is record index 789 vBucket["id"] = 4L + i; // id = 5, 6 already pre_insert 790 } else { 791 vBucket["id"] = 1L + i; 792 } 793 794 std::string name = "lisi" + std::to_string(i); 795 vBucket["name"] = name; 796 vBucket["age"] = 100.0 + i; // 100.0 is offset for cloud data 797 if (vBucketContains) { 798 vBucket["sex"] = i % 2 ? true : false; // 2 is mod 799 } 800 801 vBucket["image"] = std::vector<uint8_t>(1, i); 802 std::string gid; 803 if (gidType == GidType::GID_MATCH) { 804 gid = g_gid + std::to_string(i); 805 } else if (gidType == GidType::GID_EMPTY) { 806 std::string emptyGid = ""; 807 gid = emptyGid; 808 } else if (gidType == GidType::GID_INVALID) { 809 std::string invalidGid = "abc'd"; 810 gid = invalidGid; 811 } else { 812 gid = std::to_string(i) + g_gid; 813 } 814 815 vBucket[CloudDbConstant::GID_FIELD] = gid; 816 int64_t cTime = 12345678L + i; 817 vBucket[CloudDbConstant::CREATE_FIELD] = cTime; 818 int64_t mTime = 12345679L + i; 819 vBucket[CloudDbConstant::MODIFY_FIELD] = mTime; 820 downloadData.data.push_back(vBucket); 821 } 822 823 downloadData.opType = { OpType::UPDATE, OpType::DELETE, OpType::ONLY_UPDATE_GID, OpType::INSERT, 824 OpType::SET_CLOUD_FORCE_PUSH_FLAG_ZERO, OpType::SET_CLOUD_FORCE_PUSH_FLAG_ONE, OpType::NOT_HANDLE }; 825 } 826 SaveCloudDataTest(PrimaryKeyType pkType,GidType gidType=GidType::GID_MATCH,bool nullable=true,bool vBucketContains=true,int expectCode=E_OK)827 void SaveCloudDataTest(PrimaryKeyType pkType, GidType gidType = GidType::GID_MATCH, bool nullable = true, 828 bool vBucketContains = true, int expectCode = E_OK) 829 { 830 /** 831 * @tc.steps:step1. create db, create table. 832 * @tc.expected: step1. return ok. 833 */ 834 PrepareDataBase(g_tableName, pkType, nullable); 835 836 /** 837 * @tc.steps:step2. call PutCloudSyncData 838 * @tc.expected: step2. return ok. 839 */ 840 std::shared_ptr<StorageProxy> storageProxy = GetStorageProxy(g_cloudStore); 841 ASSERT_NE(storageProxy, nullptr); 842 EXPECT_EQ(storageProxy->StartTransaction(TransactType::IMMEDIATE), E_OK); 843 844 DownloadData downloadData; 845 ConstructDownloadData(downloadData, gidType, nullable, vBucketContains); 846 EXPECT_EQ(storageProxy->PutCloudSyncData(g_tableName, downloadData), expectCode); 847 if (expectCode == E_OK) { 848 for (size_t i = 0; i < downloadData.opType.size(); i++) { 849 if (downloadData.opType[i] == OpType::INSERT) { 850 EXPECT_TRUE(downloadData.data[i].find(CloudDbConstant::ROW_ID_FIELD_NAME) != 851 downloadData.data[i].end()); 852 } 853 } 854 } 855 EXPECT_EQ(storageProxy->Commit(), E_OK); 856 } 857 858 /** 859 * @tc.name: PutCloudSyncDataTest001 860 * @tc.desc: Test save cloud data into table with no primary key, gid match 861 * @tc.type: FUNC 862 * @tc.require: 863 * @tc.author: zhangshijie 864 */ 865 HWTEST_F(DistributedDBCloudSaveCloudDataTest, PutCloudSyncDataTest001, TestSize.Level0) 866 { 867 SaveCloudDataTest(PrimaryKeyType::NO_PRIMARY_KEY); 868 // there is one log record with cloud_gid = abcd3(id = 7 will delete first, then insert again) 869 std::string sql = "select count(data_key) from " + DBCommon::GetLogTableName(g_tableName) + 870 " where cloud_gid = '" + g_gid + std::to_string(3) + "'"; // 3 is gid index 871 sqlite3 *db = RelationalTestUtils::CreateDataBase(g_dbDir + STORE_ID + DB_SUFFIX); 872 EXPECT_NE(db, nullptr); __anon2ff534420202(sqlite3_stmt *stmt) 873 int errCode = RelationalTestUtils::ExecSql(db, sql, nullptr, [] (sqlite3_stmt *stmt) { 874 EXPECT_EQ(sqlite3_column_int64(stmt, 0), 1); // will get only 1 log record 875 return E_OK; 876 }); 877 EXPECT_EQ(errCode, SQLITE_OK); 878 EXPECT_EQ(sqlite3_close_v2(db), E_OK); 879 } 880 881 /** 882 * @tc.name: PutCloudSyncDataTest002 883 * @tc.desc: Test save cloud data into table with no primary key, gid mismatch 884 * @tc.type: FUNC 885 * @tc.require: 886 * @tc.author: zhangshijie 887 */ 888 HWTEST_F(DistributedDBCloudSaveCloudDataTest, PutCloudSyncDataTest002, TestSize.Level0) 889 { 890 SaveCloudDataTest(PrimaryKeyType::NO_PRIMARY_KEY, GidType::GID_MISMATCH); 891 } 892 893 /** 894 * @tc.name: PutCloudSyncDataTest003 895 * @tc.desc: Test save cloud data into table with no primary key, gid is empty 896 * @tc.type: FUNC 897 * @tc.require: 898 * @tc.author: zhangshijie 899 */ 900 HWTEST_F(DistributedDBCloudSaveCloudDataTest, PutCloudSyncDataTest003, TestSize.Level0) 901 { 902 SaveCloudDataTest(PrimaryKeyType::NO_PRIMARY_KEY, GidType::GID_EMPTY, true, true, -E_CLOUD_ERROR); 903 } 904 905 /** 906 * @tc.name: PutCloudSyncDataTest004 907 * @tc.desc: Test save cloud data into table with single primary key, gid match 908 * @tc.type: FUNC 909 * @tc.require: 910 * @tc.author: zhangshijie 911 */ 912 HWTEST_F(DistributedDBCloudSaveCloudDataTest, PutCloudSyncDataTest004, TestSize.Level0) 913 { 914 SaveCloudDataTest(PrimaryKeyType::SINGLE_PRIMARY_KEY); 915 } 916 917 /** 918 * @tc.name: PutCloudSyncDataTest005 919 * @tc.desc: Test save cloud data into table with single primary key, gid mismatch 920 * @tc.type: FUNC 921 * @tc.require: 922 * @tc.author: zhangshijie 923 */ 924 HWTEST_F(DistributedDBCloudSaveCloudDataTest, PutCloudSyncDataTest005, TestSize.Level0) 925 { 926 SaveCloudDataTest(PrimaryKeyType::SINGLE_PRIMARY_KEY, GidType::GID_MISMATCH); 927 } 928 929 /** 930 * @tc.name: PutCloudSyncDataTest006 931 * @tc.desc: Test save cloud data into table with single primary key, gid is empty 932 * @tc.type: FUNC 933 * @tc.require: 934 * @tc.author: zhangshijie 935 */ 936 HWTEST_F(DistributedDBCloudSaveCloudDataTest, PutCloudSyncDataTest006, TestSize.Level0) 937 { 938 SaveCloudDataTest(PrimaryKeyType::SINGLE_PRIMARY_KEY, GidType::GID_EMPTY, true, true, -E_CLOUD_ERROR); 939 } 940 941 /** 942 * @tc.name: PutCloudSyncDataTest007 943 * @tc.desc: Test save cloud data into table with single primary key, gid is empty, cloud field less than schema, 944 * field can be null 945 * @tc.type: FUNC 946 * @tc.require: 947 * @tc.author: zhangshijie 948 */ 949 HWTEST_F(DistributedDBCloudSaveCloudDataTest, PutCloudSyncDataTest007, TestSize.Level0) 950 { 951 SaveCloudDataTest(PrimaryKeyType::SINGLE_PRIMARY_KEY, GidType::GID_MATCH, true, false); 952 } 953 954 /** 955 * @tc.name: PutCloudSyncDataTest008 956 * @tc.desc: Test save cloud data into table with single primary key, gid is empty, cloud field less than schema, 957 * field can not be null 958 * @tc.type: FUNC 959 * @tc.require: 960 * @tc.author: zhangshijie 961 */ 962 HWTEST_F(DistributedDBCloudSaveCloudDataTest, PutCloudSyncDataTest008, TestSize.Level0) 963 { 964 SaveCloudDataTest(PrimaryKeyType::SINGLE_PRIMARY_KEY, GidType::GID_EMPTY, false, false, -E_CLOUD_ERROR); 965 } 966 967 /** 968 * @tc.name: PutCloudSyncDataTest009 969 * @tc.desc: Test save cloud data into table with composite primary key, gid match, primary key mismatch 970 * @tc.type: FUNC 971 * @tc.require: 972 * @tc.author: zhangshijie 973 */ 974 HWTEST_F(DistributedDBCloudSaveCloudDataTest, PutCloudSyncDataTest009, TestSize.Level0) 975 { 976 SaveCloudDataTest(PrimaryKeyType::COMPOSITE_PRIMARY_KEY); 977 } 978 979 /** 980 * @tc.name: PutCloudSyncDataTest010 981 * @tc.desc: Test save cloud data into table with composite primary key, gid mismatch, primary key mismatch 982 * @tc.type: FUNC 983 * @tc.require: 984 * @tc.author: zhangshijie 985 */ 986 HWTEST_F(DistributedDBCloudSaveCloudDataTest, PutCloudSyncDataTest010, TestSize.Level0) 987 { 988 SaveCloudDataTest(PrimaryKeyType::COMPOSITE_PRIMARY_KEY, GidType::GID_MISMATCH); 989 } 990 991 /** 992 * @tc.name: PutCloudSyncDataTest011 993 * @tc.desc: Test save cloud data into table with composite primary key, invalid gid 994 * @tc.type: FUNC 995 * @tc.require: 996 * @tc.author: zhangshijie 997 */ 998 HWTEST_F(DistributedDBCloudSaveCloudDataTest, PutCloudSyncDataTest011, TestSize.Level0) 999 { 1000 SaveCloudDataTest(PrimaryKeyType::COMPOSITE_PRIMARY_KEY, GidType::GID_INVALID, true, true, -E_CLOUD_ERROR); 1001 } 1002 ConstructMultiDownloadData(DownloadData & downloadData,GidType gidType)1003 void ConstructMultiDownloadData(DownloadData &downloadData, GidType gidType) 1004 { 1005 for (int i = 0; i < 6; i++) { // 6 is record counts 1006 VBucket vBucket; 1007 if (i < 1) { // UPDATE_TIMESTAMP doesn't contain pk 1008 vBucket["id"] = 1L + i; 1009 } else if (i > 1) { 1010 vBucket["id"] = 10L + i; // 10 is id offset for cloud data 1011 } 1012 1013 std::string name = "lisi" + std::to_string(i); 1014 vBucket["name"] = name; 1015 vBucket["age"] = 100.0 + i; // 100.0 is offset for cloud data 1016 vBucket["sex"] = i % 2 ? true : false; // 2 is mod 1017 1018 vBucket["image"] = std::vector<uint8_t>(1, i); 1019 std::string gid; 1020 if (gidType == GidType::GID_MATCH) { 1021 if (i <= 1) { // first 2 exists in local 1022 gid = g_gid + std::to_string(i); 1023 } else { 1024 gid = g_gid + std::to_string(10 + i); // 10 is id offset for cloud data 1025 } 1026 } else if (gidType == GidType::GID_EMPTY) { 1027 std::string emptyGid = ""; 1028 gid = emptyGid; 1029 } else { 1030 gid = std::to_string(i) + g_gid; 1031 } 1032 1033 vBucket[CloudDbConstant::GID_FIELD] = gid; 1034 int64_t cTime = BASE_CREATE_TIME + i; 1035 vBucket[CloudDbConstant::CREATE_FIELD] = cTime; 1036 int64_t mTime = BASE_MODIFY_TIME + i; 1037 vBucket[CloudDbConstant::MODIFY_FIELD] = mTime; 1038 downloadData.data.push_back(vBucket); 1039 } 1040 1041 downloadData.opType = { OpType::UPDATE, OpType::UPDATE_TIMESTAMP, OpType::INSERT, OpType::INSERT, 1042 OpType::INSERT, OpType::NOT_HANDLE }; 1043 } 1044 1045 /** 1046 * @tc.name: PutCloudSyncDataTest012 1047 * @tc.desc: Test save cloud data into table with no primary key, multi cloud data 1048 * @tc.type: FUNC 1049 * @tc.require: 1050 * @tc.author: zhangshijie 1051 */ 1052 HWTEST_F(DistributedDBCloudSaveCloudDataTest, PutCloudSyncDataTest012, TestSize.Level0) 1053 { 1054 /** 1055 * @tc.steps:step1. create db, create table. 1056 * @tc.expected: step1. return ok. 1057 */ 1058 PrepareDataBase(g_tableName, PrimaryKeyType::NO_PRIMARY_KEY, true); 1059 1060 /** 1061 * @tc.steps:step2. call PutCloudSyncData 1062 * @tc.expected: step2. return ok. 1063 */ 1064 std::shared_ptr<StorageProxy> storageProxy = GetStorageProxy(g_cloudStore); 1065 ASSERT_NE(storageProxy, nullptr); 1066 EXPECT_EQ(storageProxy->StartTransaction(TransactType::IMMEDIATE), E_OK); 1067 1068 DownloadData downloadData; 1069 ConstructMultiDownloadData(downloadData, GidType::GID_MATCH); 1070 EXPECT_EQ(storageProxy->PutCloudSyncData(g_tableName, downloadData), E_OK); 1071 EXPECT_EQ(storageProxy->Commit(), E_OK); 1072 } 1073 1074 /** 1075 * @tc.name: PutCloudSyncDataTest013 1076 * @tc.desc: Test save cloud data with type = update_timestamp 1077 * @tc.type: FUNC 1078 * @tc.require: 1079 * @tc.author: zhangshijie 1080 */ 1081 HWTEST_F(DistributedDBCloudSaveCloudDataTest, PutCloudSyncDataTest013, TestSize.Level0) 1082 { 1083 /** 1084 * @tc.steps:step1. create db, create table. 1085 * @tc.expected: step1. return ok. 1086 */ 1087 PrepareDataBase(g_tableName, PrimaryKeyType::SINGLE_PRIMARY_KEY, true); 1088 1089 std::string sql = "delete from " + g_tableName + " where id = 2"; 1090 sqlite3 *db = RelationalTestUtils::CreateDataBase(g_dbDir + STORE_ID + DB_SUFFIX); 1091 EXPECT_NE(db, nullptr); 1092 EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), E_OK); 1093 /** 1094 * @tc.steps:step2. call PutCloudSyncData 1095 * @tc.expected: step2. return ok. 1096 */ 1097 std::shared_ptr<StorageProxy> storageProxy = GetStorageProxy(g_cloudStore); 1098 ASSERT_NE(storageProxy, nullptr); 1099 EXPECT_EQ(storageProxy->StartTransaction(TransactType::IMMEDIATE), E_OK); 1100 1101 DownloadData downloadData; 1102 ConstructMultiDownloadData(downloadData, GidType::GID_MATCH); 1103 EXPECT_EQ(storageProxy->PutCloudSyncData(g_tableName, downloadData), E_OK); 1104 EXPECT_EQ(storageProxy->Commit(), E_OK); 1105 1106 /** 1107 * @tc.steps:step3. verify data 1108 * @tc.expected: step3. verify data ok. 1109 */ 1110 sql = "select device, timestamp, flag from " + DBCommon::GetLogTableName(g_tableName) + 1111 " where data_key = -1 and cloud_gid = ''"; 1112 int count = 0; __anon2ff534420302(sqlite3_stmt *stmt) 1113 int errCode = RelationalTestUtils::ExecSql(db, sql, nullptr, [&count] (sqlite3_stmt *stmt) { 1114 std::string device = "cloud"; 1115 std::vector<uint8_t> deviceVec; 1116 (void)SQLiteUtils::GetColumnBlobValue(stmt, 0, deviceVec); // 0 is device 1117 std::string getDevice; 1118 DBCommon::VectorToString(deviceVec, getDevice); 1119 EXPECT_EQ(device, getDevice); 1120 EXPECT_EQ(sqlite3_column_int64(stmt, 1), BASE_MODIFY_TIME + 1); 1121 EXPECT_EQ(sqlite3_column_int(stmt, 2), 0x20|0x01); // 2 is flag 1122 count++; 1123 return E_OK; 1124 }); 1125 EXPECT_EQ(errCode, E_OK); 1126 EXPECT_EQ(count, 1); 1127 EXPECT_EQ(sqlite3_close_v2(db), E_OK); 1128 } 1129 1130 /** 1131 * @tc.name: PutCloudSyncDataTest014 1132 * @tc.desc: Test PutCloudSyncData when vbucket doesn't contain pk data and gid match, 1133 * @tc.type: FUNC 1134 * @tc.require: 1135 * @tc.author: zhangshijie 1136 */ 1137 HWTEST_F(DistributedDBCloudSaveCloudDataTest, PutCloudSyncDataTest014, TestSize.Level0) 1138 { 1139 /** 1140 * @tc.steps:step1. create db, create table. 1141 * @tc.expected: step1. return ok. 1142 */ 1143 PrepareDataBase(g_tableName, PrimaryKeyType::SINGLE_PRIMARY_KEY); 1144 1145 /** 1146 * @tc.steps:step2. construct data without primary key value, call PutCloudSyncData. 1147 * @tc.expected: step2. return E_OK. 1148 */ 1149 std::shared_ptr<StorageProxy> storageProxy = GetStorageProxy(g_cloudStore); 1150 ASSERT_NE(storageProxy, nullptr); 1151 EXPECT_EQ(storageProxy->StartTransaction(TransactType::IMMEDIATE), E_OK); 1152 1153 DownloadData downloadData; 1154 VBucket vBucket; 1155 std::string gid = g_gid + std::to_string(0); 1156 vBucket[CloudDbConstant::GID_FIELD] = gid; 1157 vBucket[CloudDbConstant::MODIFY_FIELD] = BASE_MODIFY_TIME; 1158 downloadData.data.push_back(vBucket); 1159 downloadData.opType = { OpType::DELETE }; 1160 EXPECT_EQ(storageProxy->PutCloudSyncData(g_tableName, downloadData), E_OK); 1161 EXPECT_EQ(storageProxy->Commit(), E_OK); 1162 } 1163 1164 /** 1165 * @tc.name: PutCloudSyncDataTest015 1166 * @tc.desc: Test clear gid and ONLY_UPDATE_GID 1167 * @tc.type: FUNC 1168 * @tc.require: 1169 * @tc.author: zhangshijie 1170 */ 1171 HWTEST_F(DistributedDBCloudSaveCloudDataTest, PutCloudSyncDataTest015, TestSize.Level0) 1172 { 1173 /** 1174 * @tc.steps:step1. create db, create table. 1175 * @tc.expected: step1. return ok. 1176 */ 1177 PrepareDataBase(g_tableName, PrimaryKeyType::SINGLE_PRIMARY_KEY); 1178 1179 /** 1180 * @tc.steps:step2. construct data type = clear_gid, call PutCloudSyncData. 1181 * @tc.expected: step2. return E_OK. 1182 */ 1183 std::shared_ptr<StorageProxy> storageProxy = GetStorageProxy(g_cloudStore); 1184 ASSERT_NE(storageProxy, nullptr); 1185 EXPECT_EQ(storageProxy->StartTransaction(TransactType::IMMEDIATE), E_OK); 1186 1187 DownloadData downloadData; 1188 for (int i = 0; i < 2; i++) { // 2 is record count 1189 VBucket vBucket; 1190 std::string gid = g_gid + std::to_string(i * 4); // 4 is data index 1191 vBucket[CloudDbConstant::GID_FIELD] = gid; 1192 vBucket[CloudDbConstant::MODIFY_FIELD] = BASE_MODIFY_TIME; 1193 downloadData.data.push_back(vBucket); 1194 } 1195 downloadData.opType = { OpType::ONLY_UPDATE_GID, OpType::CLEAR_GID }; 1196 EXPECT_EQ(storageProxy->PutCloudSyncData(g_tableName, downloadData), E_OK); 1197 EXPECT_EQ(storageProxy->Commit(), E_OK); 1198 1199 /** 1200 * @tc.steps:step3. verify data 1201 * @tc.expected: step3. verify data ok. 1202 */ 1203 std::string sql = "select cloud_gid, flag from " + DBCommon::GetLogTableName(g_tableName) + 1204 " where data_key = 1 or data_key = 5"; 1205 int count = 0; 1206 sqlite3 *db = RelationalTestUtils::CreateDataBase(g_dbDir + STORE_ID + DB_SUFFIX); 1207 EXPECT_NE(db, nullptr); __anon2ff534420402(sqlite3_stmt *stmt) 1208 int errCode = RelationalTestUtils::ExecSql(db, sql, nullptr, [&count] (sqlite3_stmt *stmt) { 1209 std::string gid = ""; 1210 if (count == 0) { 1211 gid = g_gid + "0"; 1212 } 1213 const unsigned char *val = sqlite3_column_text(stmt, 0); 1214 EXPECT_TRUE(val != nullptr); 1215 std::string getGid = reinterpret_cast<const char *>(val); 1216 LOGD("GET GID = %s", getGid.c_str()); 1217 EXPECT_EQ(getGid, gid); 1218 if (count == 1) { 1219 int flag = sqlite3_column_int(stmt, 1); 1220 // 0x04 is binay num of b100, clear gid will clear 2th bit of flag 1221 EXPECT_EQ(static_cast<uint16_t>(flag) & 0x04, 0); 1222 } 1223 count++; 1224 return E_OK; 1225 }); 1226 EXPECT_EQ(errCode, E_OK); 1227 EXPECT_EQ(count, 2); // 2 is result count 1228 EXPECT_EQ(sqlite3_close_v2(db), E_OK); 1229 } 1230 DeleteWithPkTest(PrimaryKeyType pkType)1231 void DeleteWithPkTest(PrimaryKeyType pkType) 1232 { 1233 /** 1234 * @tc.steps:step1. create db, create table. 1235 * @tc.expected: step1. return ok. 1236 */ 1237 PrepareDataBase(g_tableName, pkType, false); 1238 1239 /** 1240 * @tc.steps:step2. call PutCloudSyncData 1241 * @tc.expected: step2. return ok. 1242 */ 1243 std::shared_ptr<StorageProxy> storageProxy = GetStorageProxy(g_cloudStore); 1244 ASSERT_NE(storageProxy, nullptr); 1245 EXPECT_EQ(storageProxy->StartTransaction(TransactType::IMMEDIATE), E_OK); 1246 1247 DownloadData downloadData; 1248 VBucket vBucket; 1249 vBucket["id"] = 1L; 1250 if (pkType == PrimaryKeyType::COMPOSITE_PRIMARY_KEY) { 1251 std::string name = "zhangsan1"; 1252 vBucket["name"] = name; 1253 } 1254 1255 std::string gid = g_gid + "_not_exist"; // gid mismatch 1256 vBucket[CloudDbConstant::GID_FIELD] = gid; 1257 vBucket[CloudDbConstant::MODIFY_FIELD] = BASE_MODIFY_TIME; 1258 downloadData.data.push_back(vBucket); 1259 downloadData.opType = { OpType::DELETE }; 1260 EXPECT_EQ(storageProxy->PutCloudSyncData(g_tableName, downloadData), E_OK); 1261 EXPECT_EQ(storageProxy->Commit(), E_OK); 1262 1263 /** 1264 * @tc.steps:step3. verify data 1265 * @tc.expected: step3. verify data ok. 1266 */ 1267 std::string sql; 1268 if (pkType == PrimaryKeyType::SINGLE_PRIMARY_KEY) { 1269 sql = "select count(1) from " + g_tableName + " where id = 1"; 1270 } else { 1271 sql = "select count(1) from " + g_tableName + " where id = 1 and name = 'zhangsan'"; 1272 } 1273 int count = 0; 1274 sqlite3 *db = RelationalTestUtils::CreateDataBase(g_dbDir + STORE_ID + DB_SUFFIX); 1275 EXPECT_NE(db, nullptr); 1276 int errCode = RelationalTestUtils::ExecSql(db, sql, nullptr, [&count] (sqlite3_stmt *stmt) { 1277 EXPECT_EQ(sqlite3_column_int(stmt, 0), 0); 1278 count++; 1279 return E_OK; 1280 }); 1281 EXPECT_EQ(errCode, E_OK); 1282 EXPECT_EQ(count, 1); 1283 EXPECT_EQ(sqlite3_close_v2(db), E_OK); 1284 } 1285 1286 /** 1287 * @tc.name: PutCloudSyncDataTest016 1288 * @tc.desc: Test delete data with pk in cloud data(normally there is no pk in cloud data when it is delete) 1289 * @tc.type: FUNC 1290 * @tc.require: 1291 * @tc.author: zhangshijie 1292 */ 1293 HWTEST_F(DistributedDBCloudSaveCloudDataTest, PutCloudSyncDataTest016, TestSize.Level1) 1294 { 1295 DeleteWithPkTest(PrimaryKeyType::SINGLE_PRIMARY_KEY); 1296 } 1297 1298 /** 1299 * @tc.name: PutCloudSyncDataTest017 1300 * @tc.desc: Test delete data with pk in cloud data(normally there is no pk in cloud data when it is delete) 1301 * primary key is COMPOSITE_PRIMARY_KEY 1302 * @tc.type: FUNC 1303 * @tc.require: 1304 * @tc.author: zhangshijie 1305 */ 1306 HWTEST_F(DistributedDBCloudSaveCloudDataTest, PutCloudSyncDataTest017, TestSize.Level1) 1307 { 1308 DeleteWithPkTest(PrimaryKeyType::COMPOSITE_PRIMARY_KEY); 1309 } 1310 1311 /** 1312 * @tc.name: DropTableTest001 1313 * @tc.desc: Test drop table 1314 * @tc.type: FUNC 1315 * @tc.require: 1316 * @tc.author: zhangshijie 1317 */ 1318 HWTEST_F(DistributedDBCloudSaveCloudDataTest, DropTableTest001, TestSize.Level1) 1319 { 1320 /** 1321 * @tc.steps:step1. create db, create table, prepare data. 1322 * @tc.expected: step1. ok. 1323 */ 1324 sqlite3 *db = RelationalTestUtils::CreateDataBase(g_dbDir + STORE_ID + DB_SUFFIX); 1325 EXPECT_NE(db, nullptr); 1326 EXPECT_EQ(RelationalTestUtils::ExecSql(db, "PRAGMA journal_mode=WAL;"), SQLITE_OK); 1327 1328 std::string sql = "create table t_device(key int, value text);create table t_cloud(key int, value text);"; 1329 EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), SQLITE_OK); 1330 EXPECT_EQ(g_delegate->CreateDistributedTable("t_device", DistributedDB::DEVICE_COOPERATION), OK); 1331 EXPECT_EQ(g_delegate->CreateDistributedTable("t_cloud", DistributedDB::CLOUD_COOPERATION), OK); 1332 1333 sql = "insert into t_device values(1, 'zhangsan');insert into t_cloud values(1, 'zhangsan');"; 1334 EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), SQLITE_OK); 1335 sql = "update " + DBCommon::GetLogTableName("t_cloud") + " set flag = 0"; 1336 EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), SQLITE_OK); 1337 1338 /** 1339 * @tc.steps:step2. drop table t_cloud, check log data 1340 * @tc.expected: step2. success. 1341 */ 1342 sql = "drop table t_cloud;"; 1343 EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), SQLITE_OK); 1344 sql = "select flag from " + DBCommon::GetLogTableName("t_cloud") + " where data_key = -1;"; 1345 int count = 0; __anon2ff534420602(sqlite3_stmt *stmt) 1346 int errCode = RelationalTestUtils::ExecSql(db, sql, nullptr, [&count] (sqlite3_stmt *stmt) { 1347 EXPECT_EQ(sqlite3_column_int(stmt, 0), 3); // 3 mean local delete 1348 count++; 1349 return E_OK; 1350 }); 1351 EXPECT_EQ(errCode, E_OK); 1352 EXPECT_EQ(count, 1); 1353 1354 /** 1355 * @tc.steps:step3. drop table t_device, check log data 1356 * @tc.expected: step3. success. 1357 */ 1358 sql = "drop table t_device;"; 1359 EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), SQLITE_OK); 1360 sql = "select flag from " + DBCommon::GetLogTableName("t_device") + " where flag = 0x03;"; 1361 count = 0; __anon2ff534420702(sqlite3_stmt *stmt) 1362 errCode = RelationalTestUtils::ExecSql(db, sql, nullptr, [&count] (sqlite3_stmt *stmt) { 1363 count++; 1364 return E_OK; 1365 }); 1366 EXPECT_EQ(errCode, E_OK); 1367 EXPECT_EQ(count, 1); 1368 EXPECT_EQ(sqlite3_close_v2(db), E_OK); 1369 } 1370 1371 /** 1372 * @tc.name: GetDataWithAsset001 1373 * @tc.desc: Test get data with abnormal asset 1374 * @tc.type: FUNC 1375 * @tc.require: 1376 * @tc.author: zhangqiquan 1377 */ 1378 HWTEST_F(DistributedDBCloudSaveCloudDataTest, GetDataWithAsset001, TestSize.Level0) 1379 { 1380 /** 1381 * @tc.steps:step1. create db, create table, prepare data. 1382 * @tc.expected: step1. success. 1383 */ 1384 PrepareDataBaseForAsset(g_assetTableName, true); 1385 RuntimeConfig::SetCloudTranslate(std::make_shared<VirtualCloudDataTranslate>()); 1386 std::shared_ptr<StorageProxy> storageProxy = GetStorageProxy(g_cloudStore); 1387 ASSERT_NE(storageProxy, nullptr); 1388 int errCode = storageProxy->StartTransaction(); 1389 EXPECT_EQ(errCode, E_OK); 1390 /** 1391 * @tc.steps:step2. create db, create table, prepare data. 1392 * @tc.expected: step2. success. 1393 */ 1394 ContinueToken token = nullptr; 1395 CloudSyncData data(g_assetTableName); 1396 errCode = storageProxy->GetCloudData(g_assetTableName, 0u, token, data); 1397 EXPECT_EQ(errCode, E_OK); 1398 EXPECT_EQ(data.ignoredCount, 1); 1399 1400 EXPECT_EQ(storageProxy->Commit(), E_OK); 1401 EXPECT_EQ(token, nullptr); 1402 RuntimeConfig::SetCloudTranslate(nullptr); 1403 } 1404 CheckCloudBatchData(CloudSyncBatch & batchData,bool existRef)1405 void CheckCloudBatchData(CloudSyncBatch &batchData, bool existRef) 1406 { 1407 for (size_t i = 0u; i < batchData.rowid.size(); ++i) { 1408 int64_t rowid = batchData.rowid[i]; 1409 auto &extend = batchData.extend[i]; 1410 ASSERT_EQ(extend.find(CloudDbConstant::REFERENCE_FIELD) != extend.end(), existRef); 1411 if (!existRef) { 1412 continue; 1413 } 1414 Entries entries = std::get<Entries>(extend[CloudDbConstant::REFERENCE_FIELD]); 1415 EXPECT_EQ(std::to_string(rowid), entries["targetTable"]); 1416 } 1417 } 1418 1419 /** 1420 * @tc.name: FillReferenceGid001 1421 * @tc.desc: Test fill gid data with normal 1422 * @tc.type: FUNC 1423 * @tc.require: 1424 * @tc.author: zhangqiquan 1425 */ 1426 HWTEST_F(DistributedDBCloudSaveCloudDataTest, FillReferenceGid001, TestSize.Level0) 1427 { 1428 auto storage = new(std::nothrow) MockRelationalSyncAbleStorage(); 1429 CloudSyncData syncData("FillReferenceGid001"); 1430 EXPECT_CALL(*storage, GetReferenceGid).WillRepeatedly([&syncData](const std::string &tableName, __anon2ff534420802(const std::string &tableName, const CloudSyncBatch &syncBatch, std::map<int64_t, Entries> &referenceGid) 1431 const CloudSyncBatch &syncBatch, std::map<int64_t, Entries> &referenceGid) { 1432 EXPECT_EQ(syncData.tableName, tableName); 1433 EXPECT_EQ(syncBatch.rowid.size(), 1u); // has 1 record 1434 for (auto rowid : syncBatch.rowid) { 1435 Entries entries; 1436 entries["targetTable"] = std::to_string(rowid); 1437 referenceGid[rowid] = entries; 1438 } 1439 return E_OK; 1440 }); 1441 syncData.insData.rowid.push_back(1); // rowid is 1 1442 syncData.insData.extend.resize(1); // has 1 record 1443 syncData.updData.rowid.push_back(2); // rowid is 2 1444 syncData.updData.extend.resize(1); // has 1 record 1445 syncData.delData.rowid.push_back(3); // rowid is 3 1446 syncData.delData.extend.resize(1); // has 1 record 1447 EXPECT_EQ(storage->CallFillReferenceData(syncData), E_OK); 1448 CheckCloudBatchData(syncData.insData, true); 1449 CheckCloudBatchData(syncData.updData, true); 1450 CheckCloudBatchData(syncData.delData, false); 1451 RefObject::KillAndDecObjRef(storage); 1452 } 1453 1454 /** 1455 * @tc.name: FillReferenceGid002 1456 * @tc.desc: Test fill gid data with abnormal 1457 * @tc.type: FUNC 1458 * @tc.require: 1459 * @tc.author: zhangqiquan 1460 */ 1461 HWTEST_F(DistributedDBCloudSaveCloudDataTest, FillReferenceGid002, TestSize.Level0) 1462 { 1463 auto storage = new(std::nothrow) MockRelationalSyncAbleStorage(); 1464 CloudSyncData syncData("FillReferenceGid002"); 1465 syncData.insData.rowid.push_back(1); // rowid is 1 1466 EXPECT_CALL(*storage, GetReferenceGid).WillRepeatedly([](const std::string &, __anon2ff534420902(const std::string &, const CloudSyncBatch &, std::map<int64_t, Entries> &referenceGid) 1467 const CloudSyncBatch &, std::map<int64_t, Entries> &referenceGid) { 1468 referenceGid[0] = {}; // create default 1469 return E_OK; 1470 }); 1471 EXPECT_EQ(storage->CallFillReferenceData(syncData), -E_UNEXPECTED_DATA); 1472 syncData.insData.extend.resize(1); // rowid is 1 1473 EXPECT_EQ(storage->CallFillReferenceData(syncData), E_OK); 1474 RefObject::KillAndDecObjRef(storage); 1475 } 1476 1477 /** 1478 * @tc.name: ConsistentFlagTest001 1479 * @tc.desc: Check the 0x20 bit of flag changed from the trigger 1480 * @tc.type: FUNC 1481 * @tc.require: 1482 * @tc.author: bty 1483 */ 1484 HWTEST_F(DistributedDBCloudSaveCloudDataTest, ConsistentFlagTest001, TestSize.Level1) 1485 { 1486 /** 1487 * @tc.steps:step1. create db, create table, prepare data. 1488 * @tc.expected: step1. success. 1489 */ 1490 PrepareDataBase(g_tableName, PrimaryKeyType::SINGLE_PRIMARY_KEY, true); 1491 sqlite3 *db = RelationalTestUtils::CreateDataBase(g_dbDir + STORE_ID + DB_SUFFIX); 1492 ASSERT_NE(db, nullptr); 1493 std::string sql = "insert into " + g_tableName + "(id, name) values(10, 'xx1'), (11, 'xx2')"; 1494 EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), E_OK); 1495 sql = "delete from " + g_tableName + " where id=11;"; 1496 EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), E_OK); 1497 1498 /** 1499 * @tc.steps:step2 query inserted and updated data, check flag 1500 * @tc.expected: step2. success. 1501 */ 1502 sql = "select flag from " + DBCommon::GetLogTableName(g_tableName) + 1503 " where data_key in('10', '1')"; __anon2ff534420a02(sqlite3_stmt *stmt) 1504 int errCode = RelationalTestUtils::ExecSql(db, sql, nullptr, [] (sqlite3_stmt *stmt) { 1505 EXPECT_EQ(sqlite3_column_int(stmt, 0), 0x20|0x02); 1506 return E_OK; 1507 }); 1508 EXPECT_EQ(errCode, E_OK); 1509 1510 /** 1511 * @tc.steps:step3 query deleted data which gid is not empty, check flag 1512 * @tc.expected: step3. success. 1513 */ 1514 sql = "select flag from " + DBCommon::GetLogTableName(g_tableName) + 1515 " where data_key=-1 and cloud_gid !='';"; __anon2ff534420b02(sqlite3_stmt *stmt) 1516 errCode = RelationalTestUtils::ExecSql(db, sql, nullptr, [] (sqlite3_stmt *stmt) { 1517 EXPECT_EQ(sqlite3_column_int(stmt, 0), 0x20|0x03); 1518 return E_OK; 1519 }); 1520 EXPECT_EQ(errCode, E_OK); 1521 1522 /** 1523 * @tc.steps:step4 query deleted data which gid is empty, check flag 1524 * @tc.expected: step4. success. 1525 */ 1526 sql = "select flag from " + DBCommon::GetLogTableName(g_tableName) + 1527 " where data_key=-1 and cloud_gid ='';"; __anon2ff534420c02(sqlite3_stmt *stmt) 1528 errCode = RelationalTestUtils::ExecSql(db, sql, nullptr, [] (sqlite3_stmt *stmt) { 1529 EXPECT_EQ(sqlite3_column_int(stmt, 0), 0x03); 1530 return E_OK; 1531 }); 1532 EXPECT_EQ(errCode, E_OK); 1533 EXPECT_EQ(sqlite3_close_v2(db), SQLITE_OK); 1534 } 1535 } 1536