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 "relational_store_instance.h" 25 #include "relational_store_manager.h" 26 #include "relational_sync_able_storage.h" 27 #include "sqlite_relational_store.h" 28 #include "storage_proxy.h" 29 #include "virtual_cloud_data_translate.h" 30 #include "runtime_config.h" 31 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)82 void SetCloudSchema(PrimaryKeyType pkType, bool nullable) 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 = { "image", TYPE_INDEX<Bytes>, false, true }; 91 tableSchema = { g_tableName, { field1, field2, field3, field4, field5} }; 92 93 DataBaseSchema dbSchema; 94 dbSchema.tables = { tableSchema }; 95 g_cloudStore->SetCloudDbSchema(dbSchema); 96 } 97 PrepareDataBase(const std::string & tableName,PrimaryKeyType pkType,bool nullable=true)98 void PrepareDataBase(const std::string &tableName, PrimaryKeyType pkType, bool nullable = true) 99 { 100 /** 101 * @tc.steps:step1. create table. 102 * @tc.expected: step1. return ok. 103 */ 104 sqlite3 *db = RelationalTestUtils::CreateDataBase(g_dbDir + STORE_ID + DB_SUFFIX); 105 EXPECT_NE(db, nullptr); 106 std::string sql; 107 if (pkType == PrimaryKeyType::SINGLE_PRIMARY_KEY) { 108 sql = "create table " + tableName + "(id int primary key, name TEXT, age REAL, sex INTEGER, image BLOB);"; 109 } else if (pkType == PrimaryKeyType::NO_PRIMARY_KEY) { 110 sql = "create table " + tableName + "(id int, name TEXT, age REAL, sex INTEGER, image BLOB);"; 111 } else { 112 sql = "create table " + tableName + "(id int, name TEXT, age REAL, sex INTEGER, image BLOB," \ 113 " PRIMARY KEY(id, name))"; 114 } 115 EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), E_OK); 116 117 /** 118 * @tc.steps:step2. create distributed table with CLOUD_COOPERATION mode. 119 * @tc.expected: step2. return ok. 120 */ 121 EXPECT_EQ(g_delegate->CreateDistributedTable(tableName, DistributedDB::CLOUD_COOPERATION), OK); 122 123 /** 124 * @tc.steps:step3. insert some row. 125 * @tc.expected: step3. return ok. 126 */ 127 if (pkType == PrimaryKeyType::COMPOSITE_PRIMARY_KEY) { 128 sql = "insert into " + tableName + "(id, name, age)" \ 129 " values(1, 'zhangsan1', 10.1), (1, 'zhangsan2', 10.1), (2, 'zhangsan1', 10.0), (3, 'zhangsan3', 30)," 130 " (4, 'zhangsan4', 40.123), (5, 'zhangsan5', 50.123);"; 131 } else { 132 sql = "insert into " + tableName + "(id, name)" \ 133 " values(1, 'zhangsan1'), (2, 'zhangsan2'), (3, 'zhangsan3'), (4, 'zhangsan4')," 134 " (5, 'zhangsan5'), (6, 'zhangsan6'), (7, 'zhangsan7');"; 135 } 136 EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), E_OK); 137 138 /** 139 * @tc.steps:step4. preset cloud gid. 140 * @tc.expected: step4. return ok. 141 */ 142 for (int i = 0; i < 7; i++) { // update first 7 records 143 if (i == 4) { // 4 is id 144 sql = "update " + DBCommon::GetLogTableName(tableName) + " set cloud_gid = '" + 145 g_gid + std::to_string(i) + "', flag = 6 where data_key = " + std::to_string(i + 1); 146 } else { 147 sql = "update " + DBCommon::GetLogTableName(tableName) + " set cloud_gid = '" + 148 g_gid + std::to_string(i) + "' where data_key = " + std::to_string(i + 1); 149 } 150 EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), E_OK); 151 if (pkType != PrimaryKeyType::COMPOSITE_PRIMARY_KEY && i == 6) { // 6 is index 152 sql = "delete from " + tableName + " where id = 7;"; 153 EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), E_OK); 154 } 155 } 156 157 EXPECT_EQ(sqlite3_close_v2(db), E_OK); 158 159 SetCloudSchema(pkType, nullable); 160 } 161 InitStoreProp(const std::string & storePath,const std::string & appId,const std::string & userId,RelationalDBProperties & properties)162 void InitStoreProp(const std::string &storePath, const std::string &appId, const std::string &userId, 163 RelationalDBProperties &properties) 164 { 165 properties.SetStringProp(RelationalDBProperties::DATA_DIR, storePath); 166 properties.SetStringProp(RelationalDBProperties::APP_ID, appId); 167 properties.SetStringProp(RelationalDBProperties::USER_ID, userId); 168 properties.SetStringProp(RelationalDBProperties::STORE_ID, STORE_ID); 169 std::string identifier = userId + "-" + appId + "-" + STORE_ID; 170 std::string hashIdentifier = DBCommon::TransferHashString(identifier); 171 properties.SetStringProp(RelationalDBProperties::IDENTIFIER_DATA, hashIdentifier); 172 } 173 GetRelationalStore()174 const RelationalSyncAbleStorage *GetRelationalStore() 175 { 176 RelationalDBProperties properties; 177 InitStoreProp(g_storePath, APP_ID, USER_ID, properties); 178 int errCode = E_OK; 179 g_store = RelationalStoreInstance::GetDataBase(properties, errCode); 180 if (g_store == nullptr) { 181 LOGE("Get db failed:%d", errCode); 182 return nullptr; 183 } 184 return static_cast<SQLiteRelationalStore *>(g_store)->GetStorageEngine(); 185 } 186 SetUpTestCase(void)187 void DistributedDBCloudSaveCloudDataTest::SetUpTestCase(void) 188 { 189 DistributedDBToolsUnitTest::TestDirInit(g_testDir); 190 LOGD("Test dir is %s", g_testDir.c_str()); 191 g_dbDir = g_testDir + "/"; 192 g_storePath = g_dbDir + STORE_ID + DB_SUFFIX; 193 DistributedDBToolsUnitTest::RemoveTestDbFiles(g_testDir); 194 } 195 TearDownTestCase(void)196 void DistributedDBCloudSaveCloudDataTest::TearDownTestCase(void) 197 { 198 } 199 SetUp()200 void DistributedDBCloudSaveCloudDataTest::SetUp() 201 { 202 CreatDB(); 203 DBStatus status = g_mgr.OpenStore(g_dbDir + STORE_ID + DB_SUFFIX, STORE_ID, {}, g_delegate); 204 EXPECT_EQ(status, OK); 205 ASSERT_NE(g_delegate, nullptr); 206 g_cloudStore = (ICloudSyncStorageInterface *) GetRelationalStore(); 207 ASSERT_NE(g_cloudStore, nullptr); 208 } 209 TearDown()210 void DistributedDBCloudSaveCloudDataTest::TearDown() 211 { 212 RefObject::DecObjRef(g_store); 213 EXPECT_EQ(g_mgr.CloseStore(g_delegate), OK); 214 g_delegate = nullptr; 215 DistributedDBToolsUnitTest::RemoveTestDbFiles(g_testDir); 216 } 217 GetStorageProxy(ICloudSyncStorageInterface * store)218 std::shared_ptr<StorageProxy> GetStorageProxy(ICloudSyncStorageInterface *store) 219 { 220 return StorageProxy::GetCloudDb(store); 221 } 222 GetInfoByPrimaryKeyOrGidTest(PrimaryKeyType pkType,const std::string & gidStr,int64_t id,int expectCode,bool compositePkMatch=false)223 void GetInfoByPrimaryKeyOrGidTest(PrimaryKeyType pkType, const std::string &gidStr, int64_t id, 224 int expectCode, bool compositePkMatch = false) 225 { 226 /** 227 * @tc.steps:step1. create db, create table. 228 * @tc.expected: step1. return ok. 229 */ 230 PrepareDataBase(g_tableName, pkType); 231 232 /** 233 * @tc.steps:step2. call GetInfoByPrimaryKeyOrGid. 234 * @tc.expected: step2. return expectCode. 235 */ 236 std::shared_ptr<StorageProxy> storageProxy = GetStorageProxy(g_cloudStore); 237 ASSERT_NE(storageProxy, nullptr); 238 EXPECT_EQ(storageProxy->StartTransaction(), E_OK); 239 VBucket vBucket; 240 vBucket["id"] = id ; 241 if (compositePkMatch) { 242 std::string name = "zhangsan1"; 243 vBucket["name"] = name; 244 vBucket["age"] = 10.1; // 10.1 is test age 245 } else { 246 std::string name = "zhangsan100"; 247 vBucket["name"] = name; 248 vBucket["age"] = 10.11; // 10.11 is test age 249 } 250 vBucket[CloudDbConstant::GID_FIELD] = gidStr; 251 DataInfoWithLog dataInfoWithLog; 252 VBucket assetInfo; 253 EXPECT_EQ(storageProxy->GetInfoByPrimaryKeyOrGid(g_tableName, vBucket, dataInfoWithLog, assetInfo), expectCode); 254 if (expectCode == E_OK) { 255 if (pkType == PrimaryKeyType::SINGLE_PRIMARY_KEY) { 256 int64_t val = -1; 257 // id is pk 258 EXPECT_EQ(CloudStorageUtils::GetValueFromVBucket("id", dataInfoWithLog.primaryKeys, val), E_OK); 259 } else if (pkType == PrimaryKeyType::COMPOSITE_PRIMARY_KEY) { 260 EXPECT_TRUE(dataInfoWithLog.primaryKeys.find("id") != dataInfoWithLog.primaryKeys.end()); 261 std::string name; 262 EXPECT_EQ(CloudStorageUtils::GetValueFromVBucket("name", dataInfoWithLog.primaryKeys, name), E_OK); 263 LOGD("name = %s", name.c_str()); 264 } else { 265 EXPECT_EQ(dataInfoWithLog.primaryKeys.size(), 0u); 266 } 267 Timestamp eraseTime = dataInfoWithLog.logInfo.timestamp / CloudDbConstant::TEN_THOUSAND * 268 CloudDbConstant::TEN_THOUSAND; 269 Timestamp eraseWTime = dataInfoWithLog.logInfo.wTimestamp / CloudDbConstant::TEN_THOUSAND * 270 CloudDbConstant::TEN_THOUSAND; 271 EXPECT_EQ(dataInfoWithLog.logInfo.timestamp, eraseTime); 272 EXPECT_EQ(dataInfoWithLog.logInfo.wTimestamp, eraseWTime); 273 } 274 } 275 276 /** 277 * @tc.name: GetInfoByPrimaryKeyOrGidTest001 278 * @tc.desc: Test GetInfoByPrimaryKeyOrGid when table has single primary key and gid = "", id = 100; 279 * @tc.type: FUNC 280 * @tc.require: 281 * @tc.author: zhangshijie 282 */ 283 HWTEST_F(DistributedDBCloudSaveCloudDataTest, GetInfoByPrimaryKeyOrGidTest001, TestSize.Level0) 284 { 285 GetInfoByPrimaryKeyOrGidTest(PrimaryKeyType::SINGLE_PRIMARY_KEY, "", 100L, -E_NOT_FOUND); 286 } 287 288 /** 289 * @tc.name: GetInfoByPrimaryKeyOrGidTest002 290 * @tc.desc: Test GetInfoByPrimaryKeyOrGid when table has single primary key and gid = "", id = 1; 291 * @tc.type: FUNC 292 * @tc.require: 293 * @tc.author: zhangshijie 294 */ 295 HWTEST_F(DistributedDBCloudSaveCloudDataTest, GetInfoByPrimaryKeyOrGidTest002, TestSize.Level0) 296 { 297 GetInfoByPrimaryKeyOrGidTest(PrimaryKeyType::SINGLE_PRIMARY_KEY, "", 1, E_OK); 298 } 299 300 /** 301 * @tc.name: GetInfoByPrimaryKeyOrGidTest003 302 * @tc.desc: Test GetInfoByPrimaryKeyOrGid when table has single primary key and gid = abcd0, id = 100; 303 * @tc.type: FUNC 304 * @tc.require: 305 * @tc.author: zhangshijie 306 */ 307 HWTEST_F(DistributedDBCloudSaveCloudDataTest, GetInfoByPrimaryKeyOrGidTest003, TestSize.Level0) 308 { 309 GetInfoByPrimaryKeyOrGidTest(PrimaryKeyType::SINGLE_PRIMARY_KEY, g_gid + std::to_string(0), 100L, E_OK); 310 } 311 312 /** 313 * @tc.name: GetInfoByPrimaryKeyOrGidTest004 314 * @tc.desc: Test GetInfoByPrimaryKeyOrGid when table has single primary key and gid = abcd0, id = 2, which will 315 * match two records; 316 * @tc.type: FUNC 317 * @tc.require: 318 * @tc.author: zhangshijie 319 */ 320 HWTEST_F(DistributedDBCloudSaveCloudDataTest, GetInfoByPrimaryKeyOrGidTest004, TestSize.Level0) 321 { 322 GetInfoByPrimaryKeyOrGidTest(PrimaryKeyType::SINGLE_PRIMARY_KEY, g_gid + std::to_string(0), 2L, 323 -E_CLOUD_ERROR); 324 } 325 326 /** 327 * @tc.name: GetInfoByPrimaryKeyOrGidTest005 328 * @tc.desc: Test GetInfoByPrimaryKeyOrGid when table has single primary key and gid = abcd100, id = 100; 329 * @tc.type: FUNC 330 * @tc.require: 331 * @tc.author: zhangshijie 332 */ 333 HWTEST_F(DistributedDBCloudSaveCloudDataTest, GetInfoByPrimaryKeyOrGidTest005, TestSize.Level0) 334 { 335 GetInfoByPrimaryKeyOrGidTest(PrimaryKeyType::SINGLE_PRIMARY_KEY, g_gid + std::to_string(100), 100L, 336 -E_NOT_FOUND); 337 } 338 339 /** 340 * @tc.name: GetInfoByPrimaryKeyOrGidTest006 341 * @tc.desc: Test GetInfoByPrimaryKeyOrGid when table has no primary key and gid = abcd0, id = 100; 342 * @tc.type: FUNC 343 * @tc.require: 344 * @tc.author: zhangshijie 345 */ 346 HWTEST_F(DistributedDBCloudSaveCloudDataTest, GetInfoByPrimaryKeyOrGidTest006, TestSize.Level0) 347 { 348 GetInfoByPrimaryKeyOrGidTest(PrimaryKeyType::NO_PRIMARY_KEY, g_gid + std::to_string(0), 100L, E_OK); 349 } 350 351 /** 352 * @tc.name: GetInfoByPrimaryKeyOrGidTest007 353 * @tc.desc: Test GetInfoByPrimaryKeyOrGid when table has no primary key and gid = "", id = 1; 354 * @tc.type: FUNC 355 * @tc.require: 356 * @tc.author: zhangshijie 357 */ 358 HWTEST_F(DistributedDBCloudSaveCloudDataTest, GetInfoByPrimaryKeyOrGidTest007, TestSize.Level0) 359 { 360 GetInfoByPrimaryKeyOrGidTest(PrimaryKeyType::NO_PRIMARY_KEY, "", 1L, -E_CLOUD_ERROR); 361 } 362 363 /** 364 * @tc.name: GetInfoByPrimaryKeyOrGidTest008 365 * @tc.desc: Test GetInfoByPrimaryKeyOrGid when table has no primary key and gid = abcd100, id = 1; 366 * @tc.type: FUNC 367 * @tc.require: 368 * @tc.author: zhangshijie 369 */ 370 HWTEST_F(DistributedDBCloudSaveCloudDataTest, GetInfoByPrimaryKeyOrGidTest008, TestSize.Level0) 371 { 372 GetInfoByPrimaryKeyOrGidTest(PrimaryKeyType::NO_PRIMARY_KEY, g_gid + std::to_string(100), 1L, 373 -E_NOT_FOUND); 374 } 375 376 /** 377 * @tc.name: GetInfoByPrimaryKeyOrGidTest009 378 * @tc.desc: Test GetInfoByPrimaryKeyOrGid when table has composite primary key and gid = "", primary key match; 379 * @tc.type: FUNC 380 * @tc.require: 381 * @tc.author: zhangshijie 382 */ 383 HWTEST_F(DistributedDBCloudSaveCloudDataTest, GetInfoByPrimaryKeyOrGidTest009, TestSize.Level0) 384 { 385 GetInfoByPrimaryKeyOrGidTest(PrimaryKeyType::COMPOSITE_PRIMARY_KEY, "", 1L, E_OK, true); 386 } 387 388 /** 389 * @tc.name: GetInfoByPrimaryKeyOrGidTest010 390 * @tc.desc: Test GetInfoByPrimaryKeyOrGid when table has composite primary key and gid = "", 391 * primary key mismatch; 392 * @tc.type: FUNC 393 * @tc.require: 394 * @tc.author: zhangshijie 395 */ 396 HWTEST_F(DistributedDBCloudSaveCloudDataTest, GetInfoByPrimaryKeyOrGidTest010, TestSize.Level0) 397 { 398 GetInfoByPrimaryKeyOrGidTest(PrimaryKeyType::COMPOSITE_PRIMARY_KEY, "", 1L, -E_NOT_FOUND, false); 399 } 400 401 /** 402 * @tc.name: GetInfoByPrimaryKeyOrGidTest011 403 * @tc.desc: Test GetInfoByPrimaryKeyOrGid when table has composite primary key and gid match, 404 * primary key mismatch 405 * @tc.type: FUNC 406 * @tc.require: 407 * @tc.author: zhangshijie 408 */ 409 HWTEST_F(DistributedDBCloudSaveCloudDataTest, GetInfoByPrimaryKeyOrGidTest011, TestSize.Level0) 410 { 411 GetInfoByPrimaryKeyOrGidTest(PrimaryKeyType::COMPOSITE_PRIMARY_KEY, "abcd0", 11L, E_OK, false); 412 } 413 VbucketWithoutPrimaryDataTest(PrimaryKeyType pkType)414 void VbucketWithoutPrimaryDataTest(PrimaryKeyType pkType) 415 { 416 /** 417 * @tc.steps:step1. create db, create table. 418 * @tc.expected: step1. return ok. 419 */ 420 PrepareDataBase(g_tableName, pkType); 421 422 /** 423 * @tc.steps:step2. call GetInfoByPrimaryKeyOrGid. 424 * @tc.expected: step2. return E_OK. 425 */ 426 std::shared_ptr<StorageProxy> storageProxy = GetStorageProxy(g_cloudStore); 427 ASSERT_NE(storageProxy, nullptr); 428 EXPECT_EQ(storageProxy->StartTransaction(), E_OK); 429 VBucket vBucket; 430 std::string gid = g_gid + std::to_string(0); 431 vBucket[CloudDbConstant::GID_FIELD] = gid; 432 DataInfoWithLog dataInfoWithLog; 433 VBucket assetInfo; 434 EXPECT_EQ(storageProxy->GetInfoByPrimaryKeyOrGid(g_tableName, vBucket, dataInfoWithLog, assetInfo), E_OK); 435 } 436 437 /** 438 * @tc.name: GetInfoByPrimaryKeyOrGidTest012 439 * @tc.desc: Test GetInfoByPrimaryKeyOrGid when vbucket doesn't contain pk data and gid match, 440 * @tc.type: FUNC 441 * @tc.require: 442 * @tc.author: zhangshijie 443 */ 444 HWTEST_F(DistributedDBCloudSaveCloudDataTest, GetInfoByPrimaryKeyOrGidTest012, TestSize.Level0) 445 { 446 VbucketWithoutPrimaryDataTest(PrimaryKeyType::SINGLE_PRIMARY_KEY); 447 } 448 449 /** 450 * @tc.name: GetInfoByPrimaryKeyOrGidTest013 451 * @tc.desc: Test GetInfoByPrimaryKeyOrGid when vbucket doesn't contain pk(composite pk) data and gid match, 452 * @tc.type: FUNC 453 * @tc.require: 454 * @tc.author: zhangshijie 455 */ 456 HWTEST_F(DistributedDBCloudSaveCloudDataTest, GetInfoByPrimaryKeyOrGidTest013, TestSize.Level0) 457 { 458 VbucketWithoutPrimaryDataTest(PrimaryKeyType::COMPOSITE_PRIMARY_KEY); 459 } 460 ConstructDownloadData(DownloadData & downloadData,GidType gidType,bool nullable,bool vBucketContains)461 void ConstructDownloadData(DownloadData &downloadData, GidType gidType, bool nullable, bool vBucketContains) 462 { 463 for (int i = 0; i < 7; i++) { // 7 is record counts 464 VBucket vBucket; 465 if (i == 3) { // 3 is record index 466 vBucket["id"] = 4L + i; // id = 5, 6 already pre_insert 467 } else { 468 vBucket["id"] = 1L + i; 469 } 470 471 std::string name = "lisi" + std::to_string(i); 472 vBucket["name"] = name; 473 vBucket["age"] = 100.0 + i; // 100.0 is offset for cloud data 474 if (vBucketContains) { 475 vBucket["sex"] = i % 2 ? true : false; // 2 is mod 476 } 477 478 vBucket["image"] = std::vector<uint8_t>(1, i); 479 std::string gid; 480 if (gidType == GidType::GID_MATCH) { 481 gid = g_gid + std::to_string(i); 482 } else if (gidType == GidType::GID_EMPTY) { 483 std::string emptyGid = ""; 484 gid = emptyGid; 485 } else if (gidType == GidType::GID_INVALID) { 486 std::string invalidGid = "abc'd"; 487 gid = invalidGid; 488 } else { 489 gid = std::to_string(i) + g_gid; 490 } 491 492 vBucket[CloudDbConstant::GID_FIELD] = gid; 493 int64_t cTime = 12345678L + i; 494 vBucket[CloudDbConstant::CREATE_FIELD] = cTime; 495 int64_t mTime = 12345679L + i; 496 vBucket[CloudDbConstant::MODIFY_FIELD] = mTime; 497 downloadData.data.push_back(vBucket); 498 } 499 500 downloadData.opType = { OpType::UPDATE, OpType::DELETE, OpType::ONLY_UPDATE_GID, OpType::INSERT, 501 OpType::SET_CLOUD_FORCE_PUSH_FLAG_ZERO, OpType::SET_CLOUD_FORCE_PUSH_FLAG_ONE, OpType::NOT_HANDLE }; 502 } 503 SaveCloudDataTest(PrimaryKeyType pkType,GidType gidType=GidType::GID_MATCH,bool nullable=true,bool vBucketContains=true,int expectCode=E_OK)504 void SaveCloudDataTest(PrimaryKeyType pkType, GidType gidType = GidType::GID_MATCH, bool nullable = true, 505 bool vBucketContains = true, int expectCode = E_OK) 506 { 507 /** 508 * @tc.steps:step1. create db, create table. 509 * @tc.expected: step1. return ok. 510 */ 511 PrepareDataBase(g_tableName, pkType, nullable); 512 513 /** 514 * @tc.steps:step2. call PutCloudSyncData 515 * @tc.expected: step2. return ok. 516 */ 517 std::shared_ptr<StorageProxy> storageProxy = GetStorageProxy(g_cloudStore); 518 ASSERT_NE(storageProxy, nullptr); 519 EXPECT_EQ(storageProxy->StartTransaction(TransactType::IMMEDIATE), E_OK); 520 521 DownloadData downloadData; 522 ConstructDownloadData(downloadData, gidType, nullable, vBucketContains); 523 EXPECT_EQ(storageProxy->PutCloudSyncData(g_tableName, downloadData), expectCode); 524 if (expectCode == E_OK) { 525 for (size_t i = 0; i < downloadData.opType.size(); i++) { 526 if (downloadData.opType[i] == OpType::INSERT) { 527 EXPECT_TRUE(downloadData.data[i].find(CloudDbConstant::ROW_ID_FIELD_NAME) != 528 downloadData.data[i].end()); 529 } 530 } 531 } 532 EXPECT_EQ(storageProxy->Commit(), E_OK); 533 } 534 535 /** 536 * @tc.name: PutCloudSyncDataTest001 537 * @tc.desc: Test save cloud data into table with no primary key, gid match 538 * @tc.type: FUNC 539 * @tc.require: 540 * @tc.author: zhangshijie 541 */ 542 HWTEST_F(DistributedDBCloudSaveCloudDataTest, PutCloudSyncDataTest001, TestSize.Level0) 543 { 544 SaveCloudDataTest(PrimaryKeyType::NO_PRIMARY_KEY); 545 // there is one log record with cloud_gid = abcd3(id = 7 will delete first, then insert again) 546 std::string sql = "select count(data_key) from " + DBCommon::GetLogTableName(g_tableName) + 547 " where cloud_gid = '" + g_gid + std::to_string(3) + "'"; // 3 is gid index 548 sqlite3 *db = RelationalTestUtils::CreateDataBase(g_dbDir + STORE_ID + DB_SUFFIX); 549 EXPECT_NE(db, nullptr); __anon417013e90202(sqlite3_stmt *stmt) 550 int errCode = RelationalTestUtils::ExecSql(db, sql, nullptr, [] (sqlite3_stmt *stmt) { 551 EXPECT_EQ(sqlite3_column_int64(stmt, 0), 1); // will get only 1 log record 552 return OK; 553 }); 554 EXPECT_EQ(errCode, SQLITE_OK); 555 EXPECT_EQ(sqlite3_close_v2(db), E_OK); 556 } 557 558 /** 559 * @tc.name: PutCloudSyncDataTest002 560 * @tc.desc: Test save cloud data into table with no primary key, gid mismatch 561 * @tc.type: FUNC 562 * @tc.require: 563 * @tc.author: zhangshijie 564 */ 565 HWTEST_F(DistributedDBCloudSaveCloudDataTest, PutCloudSyncDataTest002, TestSize.Level0) 566 { 567 SaveCloudDataTest(PrimaryKeyType::NO_PRIMARY_KEY, GidType::GID_MISMATCH); 568 } 569 570 /** 571 * @tc.name: PutCloudSyncDataTest003 572 * @tc.desc: Test save cloud data into table with no primary key, gid is empty 573 * @tc.type: FUNC 574 * @tc.require: 575 * @tc.author: zhangshijie 576 */ 577 HWTEST_F(DistributedDBCloudSaveCloudDataTest, PutCloudSyncDataTest003, TestSize.Level0) 578 { 579 SaveCloudDataTest(PrimaryKeyType::NO_PRIMARY_KEY, GidType::GID_EMPTY, true, true, -E_CLOUD_ERROR); 580 } 581 582 /** 583 * @tc.name: PutCloudSyncDataTest004 584 * @tc.desc: Test save cloud data into table with single primary key, gid match 585 * @tc.type: FUNC 586 * @tc.require: 587 * @tc.author: zhangshijie 588 */ 589 HWTEST_F(DistributedDBCloudSaveCloudDataTest, PutCloudSyncDataTest004, TestSize.Level0) 590 { 591 SaveCloudDataTest(PrimaryKeyType::SINGLE_PRIMARY_KEY); 592 } 593 594 /** 595 * @tc.name: PutCloudSyncDataTest005 596 * @tc.desc: Test save cloud data into table with single primary key, gid mismatch 597 * @tc.type: FUNC 598 * @tc.require: 599 * @tc.author: zhangshijie 600 */ 601 HWTEST_F(DistributedDBCloudSaveCloudDataTest, PutCloudSyncDataTest005, TestSize.Level0) 602 { 603 SaveCloudDataTest(PrimaryKeyType::SINGLE_PRIMARY_KEY, GidType::GID_MISMATCH); 604 } 605 606 /** 607 * @tc.name: PutCloudSyncDataTest006 608 * @tc.desc: Test save cloud data into table with single primary key, gid is empty 609 * @tc.type: FUNC 610 * @tc.require: 611 * @tc.author: zhangshijie 612 */ 613 HWTEST_F(DistributedDBCloudSaveCloudDataTest, PutCloudSyncDataTest006, TestSize.Level0) 614 { 615 SaveCloudDataTest(PrimaryKeyType::SINGLE_PRIMARY_KEY, GidType::GID_EMPTY, true, true, -E_CLOUD_ERROR); 616 } 617 618 /** 619 * @tc.name: PutCloudSyncDataTest007 620 * @tc.desc: Test save cloud data into table with single primary key, gid is empty, cloud field less than schema, 621 * field can be null 622 * @tc.type: FUNC 623 * @tc.require: 624 * @tc.author: zhangshijie 625 */ 626 HWTEST_F(DistributedDBCloudSaveCloudDataTest, PutCloudSyncDataTest007, TestSize.Level0) 627 { 628 SaveCloudDataTest(PrimaryKeyType::SINGLE_PRIMARY_KEY, GidType::GID_MATCH, true, false); 629 } 630 631 /** 632 * @tc.name: PutCloudSyncDataTest008 633 * @tc.desc: Test save cloud data into table with single primary key, gid is empty, cloud field less than schema, 634 * field can not be null 635 * @tc.type: FUNC 636 * @tc.require: 637 * @tc.author: zhangshijie 638 */ 639 HWTEST_F(DistributedDBCloudSaveCloudDataTest, PutCloudSyncDataTest008, TestSize.Level0) 640 { 641 SaveCloudDataTest(PrimaryKeyType::SINGLE_PRIMARY_KEY, GidType::GID_EMPTY, false, false, -E_CLOUD_ERROR); 642 } 643 644 /** 645 * @tc.name: PutCloudSyncDataTest009 646 * @tc.desc: Test save cloud data into table with composite primary key, gid match, primary key mismatch 647 * @tc.type: FUNC 648 * @tc.require: 649 * @tc.author: zhangshijie 650 */ 651 HWTEST_F(DistributedDBCloudSaveCloudDataTest, PutCloudSyncDataTest009, TestSize.Level0) 652 { 653 SaveCloudDataTest(PrimaryKeyType::COMPOSITE_PRIMARY_KEY); 654 } 655 656 /** 657 * @tc.name: PutCloudSyncDataTest010 658 * @tc.desc: Test save cloud data into table with composite primary key, gid mismatch, primary key mismatch 659 * @tc.type: FUNC 660 * @tc.require: 661 * @tc.author: zhangshijie 662 */ 663 HWTEST_F(DistributedDBCloudSaveCloudDataTest, PutCloudSyncDataTest010, TestSize.Level0) 664 { 665 SaveCloudDataTest(PrimaryKeyType::COMPOSITE_PRIMARY_KEY, GidType::GID_MISMATCH); 666 } 667 668 /** 669 * @tc.name: PutCloudSyncDataTest011 670 * @tc.desc: Test save cloud data into table with composite primary key, invalid gid 671 * @tc.type: FUNC 672 * @tc.require: 673 * @tc.author: zhangshijie 674 */ 675 HWTEST_F(DistributedDBCloudSaveCloudDataTest, PutCloudSyncDataTest011, TestSize.Level0) 676 { 677 SaveCloudDataTest(PrimaryKeyType::COMPOSITE_PRIMARY_KEY, GidType::GID_INVALID, true, true, -E_CLOUD_ERROR); 678 } 679 ConstructMultiDownloadData(DownloadData & downloadData,GidType gidType)680 void ConstructMultiDownloadData(DownloadData &downloadData, GidType gidType) 681 { 682 for (int i = 0; i < 6; i++) { // 6 is record counts 683 VBucket vBucket; 684 if (i < 1) { // UPDATE_TIMESTAMP doesn't contain pk 685 vBucket["id"] = 1L + i; 686 } else if (i > 1) { 687 vBucket["id"] = 10L + i; // 10 is id offset for cloud data 688 } 689 690 std::string name = "lisi" + std::to_string(i); 691 vBucket["name"] = name; 692 vBucket["age"] = 100.0 + i; // 100.0 is offset for cloud data 693 vBucket["sex"] = i % 2 ? true : false; // 2 is mod 694 695 vBucket["image"] = std::vector<uint8_t>(1, i); 696 std::string gid; 697 if (gidType == GidType::GID_MATCH) { 698 if (i <= 1) { // first 2 exists in local 699 gid = g_gid + std::to_string(i); 700 } else { 701 gid = g_gid + std::to_string(10 + i); // 10 is id offset for cloud data 702 } 703 } else if (gidType == GidType::GID_EMPTY) { 704 std::string emptyGid = ""; 705 gid = emptyGid; 706 } else { 707 gid = std::to_string(i) + g_gid; 708 } 709 710 vBucket[CloudDbConstant::GID_FIELD] = gid; 711 int64_t cTime = BASE_CREATE_TIME + i; 712 vBucket[CloudDbConstant::CREATE_FIELD] = cTime; 713 int64_t mTime = BASE_MODIFY_TIME + i; 714 vBucket[CloudDbConstant::MODIFY_FIELD] = mTime; 715 downloadData.data.push_back(vBucket); 716 } 717 718 downloadData.opType = { OpType::UPDATE, OpType::UPDATE_TIMESTAMP, OpType::INSERT, OpType::INSERT, 719 OpType::INSERT, OpType::NOT_HANDLE }; 720 } 721 722 /** 723 * @tc.name: PutCloudSyncDataTest012 724 * @tc.desc: Test save cloud data into table with no primary key, multi cloud data 725 * @tc.type: FUNC 726 * @tc.require: 727 * @tc.author: zhangshijie 728 */ 729 HWTEST_F(DistributedDBCloudSaveCloudDataTest, PutCloudSyncDataTest012, TestSize.Level0) 730 { 731 /** 732 * @tc.steps:step1. create db, create table. 733 * @tc.expected: step1. return ok. 734 */ 735 PrepareDataBase(g_tableName, PrimaryKeyType::NO_PRIMARY_KEY, true); 736 737 /** 738 * @tc.steps:step2. call PutCloudSyncData 739 * @tc.expected: step2. return ok. 740 */ 741 std::shared_ptr<StorageProxy> storageProxy = GetStorageProxy(g_cloudStore); 742 ASSERT_NE(storageProxy, nullptr); 743 EXPECT_EQ(storageProxy->StartTransaction(TransactType::IMMEDIATE), E_OK); 744 745 DownloadData downloadData; 746 ConstructMultiDownloadData(downloadData, GidType::GID_MATCH); 747 EXPECT_EQ(storageProxy->PutCloudSyncData(g_tableName, downloadData), E_OK); 748 EXPECT_EQ(storageProxy->Commit(), E_OK); 749 } 750 751 /** 752 * @tc.name: PutCloudSyncDataTest013 753 * @tc.desc: Test save cloud data with type = update_timestamp 754 * @tc.type: FUNC 755 * @tc.require: 756 * @tc.author: zhangshijie 757 */ 758 HWTEST_F(DistributedDBCloudSaveCloudDataTest, PutCloudSyncDataTest013, TestSize.Level0) 759 { 760 /** 761 * @tc.steps:step1. create db, create table. 762 * @tc.expected: step1. return ok. 763 */ 764 PrepareDataBase(g_tableName, PrimaryKeyType::SINGLE_PRIMARY_KEY, true); 765 766 std::string sql = "delete from " + g_tableName + " where id = 2"; 767 sqlite3 *db = RelationalTestUtils::CreateDataBase(g_dbDir + STORE_ID + DB_SUFFIX); 768 EXPECT_NE(db, nullptr); 769 EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), E_OK); 770 /** 771 * @tc.steps:step2. call PutCloudSyncData 772 * @tc.expected: step2. return ok. 773 */ 774 std::shared_ptr<StorageProxy> storageProxy = GetStorageProxy(g_cloudStore); 775 ASSERT_NE(storageProxy, nullptr); 776 EXPECT_EQ(storageProxy->StartTransaction(TransactType::IMMEDIATE), E_OK); 777 778 DownloadData downloadData; 779 ConstructMultiDownloadData(downloadData, GidType::GID_MATCH); 780 EXPECT_EQ(storageProxy->PutCloudSyncData(g_tableName, downloadData), E_OK); 781 EXPECT_EQ(storageProxy->Commit(), E_OK); 782 783 /** 784 * @tc.steps:step3. verify data 785 * @tc.expected: step3. verify data ok. 786 */ 787 sql = "select device, timestamp, flag from " + DBCommon::GetLogTableName(g_tableName) + 788 " where data_key = -1 and cloud_gid = ''"; 789 int count = 0; __anon417013e90302(sqlite3_stmt *stmt) 790 int errCode = RelationalTestUtils::ExecSql(db, sql, nullptr, [&count] (sqlite3_stmt *stmt) { 791 std::string device = "cloud"; 792 std::vector<uint8_t> deviceVec; 793 (void)SQLiteUtils::GetColumnBlobValue(stmt, 0, deviceVec); // 0 is device 794 std::string getDevice; 795 DBCommon::VectorToString(deviceVec, getDevice); 796 EXPECT_EQ(device, getDevice); 797 EXPECT_EQ(sqlite3_column_int64(stmt, 1), BASE_MODIFY_TIME + 1); 798 EXPECT_EQ(sqlite3_column_int(stmt, 2), 1); // 2 is flag 799 count++; 800 return OK; 801 }); 802 EXPECT_EQ(errCode, E_OK); 803 EXPECT_EQ(count, 1); 804 EXPECT_EQ(sqlite3_close_v2(db), E_OK); 805 } 806 807 /** 808 * @tc.name: PutCloudSyncDataTest014 809 * @tc.desc: Test PutCloudSyncData when vbucket doesn't contain pk data and gid match, 810 * @tc.type: FUNC 811 * @tc.require: 812 * @tc.author: zhangshijie 813 */ 814 HWTEST_F(DistributedDBCloudSaveCloudDataTest, PutCloudSyncDataTest014, TestSize.Level0) 815 { 816 /** 817 * @tc.steps:step1. create db, create table. 818 * @tc.expected: step1. return ok. 819 */ 820 PrepareDataBase(g_tableName, PrimaryKeyType::SINGLE_PRIMARY_KEY); 821 822 /** 823 * @tc.steps:step2. construct data without primary key value, call PutCloudSyncData. 824 * @tc.expected: step2. return E_OK. 825 */ 826 std::shared_ptr<StorageProxy> storageProxy = GetStorageProxy(g_cloudStore); 827 ASSERT_NE(storageProxy, nullptr); 828 EXPECT_EQ(storageProxy->StartTransaction(TransactType::IMMEDIATE), E_OK); 829 830 DownloadData downloadData; 831 VBucket vBucket; 832 std::string gid = g_gid + std::to_string(0); 833 vBucket[CloudDbConstant::GID_FIELD] = gid; 834 vBucket[CloudDbConstant::MODIFY_FIELD] = BASE_MODIFY_TIME; 835 downloadData.data.push_back(vBucket); 836 downloadData.opType = { OpType::DELETE }; 837 EXPECT_EQ(storageProxy->PutCloudSyncData(g_tableName, downloadData), E_OK); 838 EXPECT_EQ(storageProxy->Commit(), E_OK); 839 } 840 841 /** 842 * @tc.name: PutCloudSyncDataTest015 843 * @tc.desc: Test clear gid and ONLY_UPDATE_GID 844 * @tc.type: FUNC 845 * @tc.require: 846 * @tc.author: zhangshijie 847 */ 848 HWTEST_F(DistributedDBCloudSaveCloudDataTest, PutCloudSyncDataTest015, TestSize.Level0) 849 { 850 /** 851 * @tc.steps:step1. create db, create table. 852 * @tc.expected: step1. return ok. 853 */ 854 PrepareDataBase(g_tableName, PrimaryKeyType::SINGLE_PRIMARY_KEY); 855 856 /** 857 * @tc.steps:step2. construct data type = clear_gid, call PutCloudSyncData. 858 * @tc.expected: step2. return E_OK. 859 */ 860 std::shared_ptr<StorageProxy> storageProxy = GetStorageProxy(g_cloudStore); 861 ASSERT_NE(storageProxy, nullptr); 862 EXPECT_EQ(storageProxy->StartTransaction(TransactType::IMMEDIATE), E_OK); 863 864 DownloadData downloadData; 865 for (int i = 0; i < 2; i++) { // 2 is record count 866 VBucket vBucket; 867 std::string gid = g_gid + std::to_string(i * 4); // 4 is data index 868 vBucket[CloudDbConstant::GID_FIELD] = gid; 869 vBucket[CloudDbConstant::MODIFY_FIELD] = BASE_MODIFY_TIME; 870 downloadData.data.push_back(vBucket); 871 } 872 downloadData.opType = { OpType::ONLY_UPDATE_GID, OpType::CLEAR_GID }; 873 EXPECT_EQ(storageProxy->PutCloudSyncData(g_tableName, downloadData), E_OK); 874 EXPECT_EQ(storageProxy->Commit(), E_OK); 875 876 /** 877 * @tc.steps:step3. verify data 878 * @tc.expected: step3. verify data ok. 879 */ 880 std::string sql = "select cloud_gid, flag from " + DBCommon::GetLogTableName(g_tableName) + 881 " where data_key = 1 or data_key = 5"; 882 int count = 0; 883 sqlite3 *db = RelationalTestUtils::CreateDataBase(g_dbDir + STORE_ID + DB_SUFFIX); 884 EXPECT_NE(db, nullptr); __anon417013e90402(sqlite3_stmt *stmt) 885 int errCode = RelationalTestUtils::ExecSql(db, sql, nullptr, [&count] (sqlite3_stmt *stmt) { 886 std::string gid = ""; 887 if (count == 0) { 888 gid = g_gid + "0"; 889 } 890 const unsigned char *val = sqlite3_column_text(stmt, 0); 891 EXPECT_TRUE(val != nullptr); 892 std::string getGid = reinterpret_cast<const char *>(val); 893 LOGD("GET GID = %s", getGid.c_str()); 894 EXPECT_EQ(getGid, gid); 895 if (count == 1) { 896 int flag = sqlite3_column_int(stmt, 1); 897 EXPECT_EQ(flag & 0x04, 0); // 0x04 is binay num of b100, clear gid will clear 2th bit of flag 898 } 899 count++; 900 return OK; 901 }); 902 EXPECT_EQ(errCode, E_OK); 903 EXPECT_EQ(count, 2); // 2 is result count 904 EXPECT_EQ(sqlite3_close_v2(db), E_OK); 905 } 906 DeleteWithPkTest(PrimaryKeyType pkType)907 void DeleteWithPkTest(PrimaryKeyType pkType) 908 { 909 /** 910 * @tc.steps:step1. create db, create table. 911 * @tc.expected: step1. return ok. 912 */ 913 PrepareDataBase(g_tableName, pkType, false); 914 915 /** 916 * @tc.steps:step2. call PutCloudSyncData 917 * @tc.expected: step2. return ok. 918 */ 919 std::shared_ptr<StorageProxy> storageProxy = GetStorageProxy(g_cloudStore); 920 ASSERT_NE(storageProxy, nullptr); 921 EXPECT_EQ(storageProxy->StartTransaction(TransactType::IMMEDIATE), E_OK); 922 923 DownloadData downloadData; 924 VBucket vBucket; 925 vBucket["id"] = 1L; 926 if (pkType == PrimaryKeyType::COMPOSITE_PRIMARY_KEY) { 927 std::string name = "zhangsan1"; 928 vBucket["name"] = name; 929 } 930 931 std::string gid = g_gid + "_not_exist"; // gid mismatch 932 vBucket[CloudDbConstant::GID_FIELD] = gid; 933 vBucket[CloudDbConstant::MODIFY_FIELD] = BASE_MODIFY_TIME; 934 downloadData.data.push_back(vBucket); 935 downloadData.opType = { OpType::DELETE }; 936 EXPECT_EQ(storageProxy->PutCloudSyncData(g_tableName, downloadData), E_OK); 937 EXPECT_EQ(storageProxy->Commit(), E_OK); 938 939 /** 940 * @tc.steps:step3. verify data 941 * @tc.expected: step3. verify data ok. 942 */ 943 std::string sql; 944 if (pkType == PrimaryKeyType::SINGLE_PRIMARY_KEY) { 945 sql = "select count(1) from " + g_tableName + " where id = 1"; 946 } else { 947 sql = "select count(1) from " + g_tableName + " where id = 1 and name = 'zhangsan'"; 948 } 949 int count = 0; 950 sqlite3 *db = RelationalTestUtils::CreateDataBase(g_dbDir + STORE_ID + DB_SUFFIX); 951 EXPECT_NE(db, nullptr); 952 int errCode = RelationalTestUtils::ExecSql(db, sql, nullptr, [&count] (sqlite3_stmt *stmt) { 953 EXPECT_EQ(sqlite3_column_int(stmt, 0), 0); 954 count++; 955 return OK; 956 }); 957 EXPECT_EQ(errCode, E_OK); 958 EXPECT_EQ(count, 1); 959 EXPECT_EQ(sqlite3_close_v2(db), E_OK); 960 } 961 962 /** 963 * @tc.name: PutCloudSyncDataTest016 964 * @tc.desc: Test delete data with pk in cloud data(normally there is no pk in cloud data when it is delete) 965 * @tc.type: FUNC 966 * @tc.require: 967 * @tc.author: zhangshijie 968 */ 969 HWTEST_F(DistributedDBCloudSaveCloudDataTest, PutCloudSyncDataTest016, TestSize.Level1) 970 { 971 DeleteWithPkTest(PrimaryKeyType::SINGLE_PRIMARY_KEY); 972 } 973 974 /** 975 * @tc.name: PutCloudSyncDataTest017 976 * @tc.desc: Test delete data with pk in cloud data(normally there is no pk in cloud data when it is delete) 977 * primary key is COMPOSITE_PRIMARY_KEY 978 * @tc.type: FUNC 979 * @tc.require: 980 * @tc.author: zhangshijie 981 */ 982 HWTEST_F(DistributedDBCloudSaveCloudDataTest, PutCloudSyncDataTest017, TestSize.Level1) 983 { 984 DeleteWithPkTest(PrimaryKeyType::COMPOSITE_PRIMARY_KEY); 985 } 986 987 /** 988 * @tc.name: DropTableTest001 989 * @tc.desc: Test drop table 990 * @tc.type: FUNC 991 * @tc.require: 992 * @tc.author: zhangshijie 993 */ 994 HWTEST_F(DistributedDBCloudSaveCloudDataTest, DropTableTest001, TestSize.Level1) 995 { 996 /** 997 * @tc.steps:step1. create db, create table, prepare data. 998 * @tc.expected: step1. ok. 999 */ 1000 sqlite3 *db = RelationalTestUtils::CreateDataBase(g_dbDir + STORE_ID + DB_SUFFIX); 1001 EXPECT_NE(db, nullptr); 1002 EXPECT_EQ(RelationalTestUtils::ExecSql(db, "PRAGMA journal_mode=WAL;"), SQLITE_OK); 1003 1004 std::string sql = "create table t_device(key int, value text);create table t_cloud(key int, value text);"; 1005 EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), SQLITE_OK); 1006 EXPECT_EQ(g_delegate->CreateDistributedTable("t_device", DistributedDB::DEVICE_COOPERATION), OK); 1007 EXPECT_EQ(g_delegate->CreateDistributedTable("t_cloud", DistributedDB::CLOUD_COOPERATION), OK); 1008 1009 sql = "insert into t_device values(1, 'zhangsan');insert into t_cloud values(1, 'zhangsan');"; 1010 EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), SQLITE_OK); 1011 sql = "update " + DBCommon::GetLogTableName("t_cloud") + " set flag = 0"; 1012 EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), SQLITE_OK); 1013 return; 1014 1015 /** 1016 * @tc.steps:step2. drop table t_cloud, check log data 1017 * @tc.expected: step2. success. 1018 */ 1019 sql = "drop table t_cloud;"; 1020 EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), SQLITE_OK); 1021 sql = "select flag from " + DBCommon::GetLogTableName("t_cloud") + " where data_key = -1;"; 1022 int count = 0; __anon417013e90602(sqlite3_stmt *stmt) 1023 int errCode = RelationalTestUtils::ExecSql(db, sql, nullptr, [&count] (sqlite3_stmt *stmt) { 1024 EXPECT_EQ(sqlite3_column_int(stmt, 0), 3); // 3 mean local delete 1025 count++; 1026 return OK; 1027 }); 1028 EXPECT_EQ(errCode, E_OK); 1029 EXPECT_EQ(count, 1); 1030 1031 /** 1032 * @tc.steps:step3. drop table t_device, check log data 1033 * @tc.expected: step3. success. 1034 */ 1035 sql = "drop table t_device;"; 1036 EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), SQLITE_OK); 1037 sql = "select flag from " + DBCommon::GetLogTableName("t_device") + " where flag = 0x03;"; 1038 count = 0; __anon417013e90702(sqlite3_stmt *stmt) 1039 errCode = RelationalTestUtils::ExecSql(db, sql, nullptr, [&count] (sqlite3_stmt *stmt) { 1040 count++; 1041 return OK; 1042 }); 1043 EXPECT_EQ(errCode, E_OK); 1044 EXPECT_EQ(count, 1); 1045 EXPECT_EQ(sqlite3_close_v2(db), E_OK); 1046 } 1047 } 1048