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