diff --git a/frameworks/libs/distributeddb/interfaces/include/cloud/cloud_store_types.h b/frameworks/libs/distributeddb/interfaces/include/cloud/cloud_store_types.h index 233f766b90fa2aa67bef0cd5e485681699205842..fa52df411b483a799573743494509bb40a1110c3 100644 --- a/frameworks/libs/distributeddb/interfaces/include/cloud/cloud_store_types.h +++ b/frameworks/libs/distributeddb/interfaces/include/cloud/cloud_store_types.h @@ -103,6 +103,11 @@ enum class LockAction : uint32_t { DOWNLOAD = 0x8 }; +enum class SyncFlowType : uint32_t { + NORMAL = 0, //upload and download + DOWNLOAD_ONLY = 1 +}; + struct CloudSyncOption { std::vector devices; SyncMode mode = SyncMode::SYNC_MODE_CLOUD_MERGE; @@ -117,6 +122,7 @@ struct CloudSyncOption { LockAction lockAction = LockAction::INSERT; std::string prepareTraceId; bool asyncDownloadAssets = false; + SyncFlowType syncFlowType = SyncFlowType::NORMAL; }; enum class QueryNodeType : uint32_t { diff --git a/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_relational_store.cpp b/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_relational_store.cpp index b74c0b3ebbcc998ffd1fc2e663496565ec0565ab..09b052d6bd68cdcecbf6adb435baef1f9fd05ced 100644 --- a/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_relational_store.cpp +++ b/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_relational_store.cpp @@ -1273,6 +1273,14 @@ int SQLiteRelationalStore::CheckBeforeSync(const CloudSyncOption &option) if (option.compensatedSyncOnly && option.asyncDownloadAssets) { return -E_NOT_SUPPORT; } + if (option.syncFlowType == SyncFlowType::DOWNLOAD_ONLY && option.compensatedSyncOnly) { + LOGE("[RelationalStore] DOWNLOAD_ONLY mode is not compatible with compensatedSyncOnly"); + return -E_NOT_SUPPORT; + } + if (option.syncFlowType == SyncFlowType::DOWNLOAD_ONLY && option.asyncDownloadAssets) { + LOGE("[RelationalStore] DOWNLOAD_ONLY mode is not compatible with asyncDownloadAssets"); + return -E_NOT_SUPPORT; + } int errCode = CheckQueryValid(option); if (errCode != E_OK) { return errCode; diff --git a/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_relational_utils.cpp b/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_relational_utils.cpp index 510fac325f2f88a51e7b7f86112a5523268bd955..40ca495908d339fdf9a502908c36b14966ba17ea 100644 --- a/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_relational_utils.cpp +++ b/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_relational_utils.cpp @@ -1251,6 +1251,7 @@ void SQLiteRelationalUtils::FillSyncInfo(const CloudSyncOption &option, const Sy } info.devices = option.devices; info.mode = option.mode; + info.syncFlowType = option.syncFlowType; info.callback = onProcess; info.timeout = option.waitTime; info.priorityTask = option.priorityTask; diff --git a/frameworks/libs/distributeddb/syncer/src/cloud/cloud_sync_utils.cpp b/frameworks/libs/distributeddb/syncer/src/cloud/cloud_sync_utils.cpp index 7a1a8b8bb5c3750552ef71165eda0c15fb699b6e..bd7e397c2a00520563cf83f418649c9ea0444a7b 100644 --- a/frameworks/libs/distributeddb/syncer/src/cloud/cloud_sync_utils.cpp +++ b/frameworks/libs/distributeddb/syncer/src/cloud/cloud_sync_utils.cpp @@ -1075,7 +1075,7 @@ bool CloudSyncUtils::CanStartAsyncDownload(int scheduleCount) return scheduleCount <= 0; } -bool CloudSyncUtils::NotNeedToCompensated(int errCode) +bool CloudSyncUtils::IsCloudErrorNotNeedCompensated(int errCode) { if (errCode == -E_CLOUD_NETWORK_ERROR || errCode == -E_CLOUD_ASSET_SPACE_INSUFFICIENT) { LOGW("[CloudSyncer] errCode = %d, not need to compensation.", errCode); @@ -1124,4 +1124,18 @@ bool CloudSyncUtils::IsIgnoreFailAssetErr(const VBucket &extend) { return DBCommon::IsRecordAssetsMissing(extend) || DBCommon::IsRecordAssetsSpaceInsufficient(extend); } + +bool CloudSyncUtils::NeedCompensated(const CloudSyncer::CloudTaskInfo &taskInfo) +{ + if (taskInfo.compensatedTask) { + return false; + } + if (CloudSyncUtils::IsCloudErrorNotNeedCompensated(taskInfo.errCode)) { + return false; + } + if (taskInfo.syncFlowType == SyncFlowType::DOWNLOAD_ONLY) { + return false; + } + return true; +} } \ No newline at end of file diff --git a/frameworks/libs/distributeddb/syncer/src/cloud/cloud_sync_utils.h b/frameworks/libs/distributeddb/syncer/src/cloud/cloud_sync_utils.h index 8962da570108b8a5c0b5e74954e52ff27dc93363..0aa15bcd740177d4714fbc56a4603b4b1a0e4d09 100644 --- a/frameworks/libs/distributeddb/syncer/src/cloud/cloud_sync_utils.h +++ b/frameworks/libs/distributeddb/syncer/src/cloud/cloud_sync_utils.h @@ -152,12 +152,14 @@ public: static bool CanStartAsyncDownload(int scheduleCount); - static bool NotNeedToCompensated(int errCode); + static bool IsCloudErrorNotNeedCompensated(int errCode); static bool IsCloudErrorWithoutAbort(int errCode); static bool IsAssetsSpaceInsufficient(const std::vector &extend); + static bool NeedCompensated(const CloudSyncer::CloudTaskInfo &taskInfo); + // if exist error but not abort sync task, return it errCode static int GetNoAbortErrorCode(bool isInsert, const CloudSyncData &uploadData); diff --git a/frameworks/libs/distributeddb/syncer/src/cloud/cloud_syncer.cpp b/frameworks/libs/distributeddb/syncer/src/cloud/cloud_syncer.cpp index 893aabbefd5601830a4d0906aa8bc5a033a00469..3e72d018473b473a6723705d36e3f035c8d4bae9 100644 --- a/frameworks/libs/distributeddb/syncer/src/cloud/cloud_syncer.cpp +++ b/frameworks/libs/distributeddb/syncer/src/cloud/cloud_syncer.cpp @@ -1517,8 +1517,8 @@ int CloudSyncer::PrepareSync(TaskId taskId) cloudTaskInfos_[taskId].users); currentContext_.processRecorder = std::make_shared(); } - strategyProxy_.UpdateStrategy(cloudTaskInfos_[taskId].mode, isKvScene_, policy_, - cloudDB_.GetCloudConflictHandler()); + strategyProxy_.UpdateStrategy(cloudTaskInfos_[taskId].mode, cloudTaskInfos_[taskId].syncFlowType, isKvScene_, + policy_, cloudDB_.GetCloudConflictHandler()); LOGI("[CloudSyncer] exec storeId %.3s taskId %" PRIu64 " priority[%d] compensated[%d] logicDelete[%d]", cloudTaskInfos_[taskId].storeId.c_str(), taskId, static_cast(cloudTaskInfos_[taskId].priorityTask), static_cast(cloudTaskInfos_[taskId].compensatedTask), @@ -1919,12 +1919,11 @@ void CloudSyncer::ClearContextAndNotify(TaskId taskId, int errCode) } // generate compensated sync // if already have compensated sync task in queue, no need to generate new compensated sync task - if (!info.compensatedTask && !IsAlreadyHaveCompensatedSyncTask() && - !CloudSyncUtils::NotNeedToCompensated(info.errCode)) { + if (CloudSyncUtils::NeedCompensated(info) && !IsAlreadyHaveCompensatedSyncTask()) { CloudTaskInfo taskInfo = CloudSyncUtils::InitCompensatedSyncTaskInfo(info); GenerateCompensatedSync(taskInfo); } - if (CloudSyncUtils::NotNeedToCompensated(info.errCode)) { + if (CloudSyncUtils::IsCloudErrorNotNeedCompensated(info.errCode)) { std::lock_guard autoLock(dataLock_); for (auto &cloudTaskInfoIter : cloudTaskInfos_) { if (cloudTaskInfoIter.second.compensatedTask) { diff --git a/frameworks/libs/distributeddb/syncer/src/cloud/cloud_syncer_extend.cpp b/frameworks/libs/distributeddb/syncer/src/cloud/cloud_syncer_extend.cpp index 609f3cdf727748819fc6650579cacb17033c75b3..cc7f107f3c933b38c427b5c97e4e9fd7d161466d 100644 --- a/frameworks/libs/distributeddb/syncer/src/cloud/cloud_syncer_extend.cpp +++ b/frameworks/libs/distributeddb/syncer/src/cloud/cloud_syncer_extend.cpp @@ -894,6 +894,9 @@ int CloudSyncer::DoDownloadInNeed(const CloudTaskInfo &taskInfo, bool needUpload } DoNotifyInNeed(taskInfo.taskId, needNotifyTables, isFirstDownload); TriggerAsyncDownloadAssetsInTaskIfNeed(isFirstDownload); + if (taskInfo.syncFlowType == SyncFlowType::DOWNLOAD_ONLY) { + DoBackgroundDownloadAssets(); + } return E_OK; } @@ -1023,7 +1026,8 @@ bool CloudSyncer::IsTasksCanMerge(TaskId taskId, TaskId tryMergeTaskId) const auto &tryMergeTaskInfo = cloudTaskInfos_[tryMergeTaskId]; return IsTaskCanMerge(taskInfo) && IsTaskCanMerge(tryMergeTaskInfo) && taskInfo.devices == tryMergeTaskInfo.devices && - taskInfo.asyncDownloadAssets == tryMergeTaskInfo.asyncDownloadAssets; + taskInfo.asyncDownloadAssets == tryMergeTaskInfo.asyncDownloadAssets && + taskInfo.syncFlowType == tryMergeTaskInfo.syncFlowType; } bool CloudSyncer::MergeTaskTablesIfConsistent(TaskId sourceId, TaskId targetId) diff --git a/frameworks/libs/distributeddb/syncer/src/cloud/icloud_syncer.h b/frameworks/libs/distributeddb/syncer/src/cloud/icloud_syncer.h index d95b559d4388eb0f27c6c6a26ba15165e2f84ad8..5529e1b5f10fc7e855495a4866f8b74217008cd0 100644 --- a/frameworks/libs/distributeddb/syncer/src/cloud/icloud_syncer.h +++ b/frameworks/libs/distributeddb/syncer/src/cloud/icloud_syncer.h @@ -39,6 +39,7 @@ public: int errCode = 0; int tempErrCode = 0; SyncMode mode = SyncMode::SYNC_MODE_PUSH_ONLY; + SyncFlowType syncFlowType = SyncFlowType::NORMAL; ProcessStatus status = ProcessStatus::PREPARED; LockAction lockAction = LockAction::INSERT; TaskId taskId = 0u; diff --git a/frameworks/libs/distributeddb/syncer/src/cloud/strategy/cloud_custom_pull_strategy.cpp b/frameworks/libs/distributeddb/syncer/src/cloud/strategy/cloud_custom_pull_strategy.cpp index e67e9210c1a4c689abd60fe463e673a45aed66c7..9ba3179aa88cff813087af6844960a69e70398ae 100644 --- a/frameworks/libs/distributeddb/syncer/src/cloud/strategy/cloud_custom_pull_strategy.cpp +++ b/frameworks/libs/distributeddb/syncer/src/cloud/strategy/cloud_custom_pull_strategy.cpp @@ -53,6 +53,9 @@ bool CloudCustomPullStrategy::JudgeUpdateCursor() const bool CloudCustomPullStrategy::JudgeUpload() const { + if (syncFlowType_ == SyncFlowType::DOWNLOAD_ONLY) { + LOGI("[CloudCustomPullStrategy] syncFlowType is DOWNLOAD_ONLY, skip upload"); + } return false; } diff --git a/frameworks/libs/distributeddb/syncer/src/cloud/strategy/cloud_custom_push_strategy.cpp b/frameworks/libs/distributeddb/syncer/src/cloud/strategy/cloud_custom_push_strategy.cpp index bc25aad9c66a185560178585912754122827d3da..2ffed24065ac8e6403b8918426f24b615f228afe 100644 --- a/frameworks/libs/distributeddb/syncer/src/cloud/strategy/cloud_custom_push_strategy.cpp +++ b/frameworks/libs/distributeddb/syncer/src/cloud/strategy/cloud_custom_push_strategy.cpp @@ -23,6 +23,10 @@ bool CloudCustomPushStrategy::JudgeUpdateCursor() const bool CloudCustomPushStrategy::JudgeUpload() const { + if (syncFlowType_ == SyncFlowType::DOWNLOAD_ONLY) { + LOGI("[CloudCustomPushStrategy] syncFlowType is DOWNLOAD_ONLY, skip upload"); + return false; + } return true; } diff --git a/frameworks/libs/distributeddb/syncer/src/cloud/strategy/cloud_force_pull_strategy.cpp b/frameworks/libs/distributeddb/syncer/src/cloud/strategy/cloud_force_pull_strategy.cpp index c292f53bcdf546bbda6f79d4fc5e95a37a85810a..9268c637ae011315f5d1ad9485dd73cef0739cde 100644 --- a/frameworks/libs/distributeddb/syncer/src/cloud/strategy/cloud_force_pull_strategy.cpp +++ b/frameworks/libs/distributeddb/syncer/src/cloud/strategy/cloud_force_pull_strategy.cpp @@ -53,6 +53,9 @@ bool CloudForcePullStrategy::JudgeUpdateCursor() const bool CloudForcePullStrategy::JudgeUpload() const { + if (syncFlowType_ == SyncFlowType::DOWNLOAD_ONLY) { + LOGI("[CloudForcePullStrategy] syncFlowType is DOWNLOAD_ONLY, skip upload"); + } return false; } } \ No newline at end of file diff --git a/frameworks/libs/distributeddb/syncer/src/cloud/strategy/cloud_force_push_strategy.cpp b/frameworks/libs/distributeddb/syncer/src/cloud/strategy/cloud_force_push_strategy.cpp index 9d0e2190ee81cd379b07f2d00d14dc131ed4ac78..d3c69a6fc0af20a173bf00aae8f5e5dc8af9bad5 100644 --- a/frameworks/libs/distributeddb/syncer/src/cloud/strategy/cloud_force_push_strategy.cpp +++ b/frameworks/libs/distributeddb/syncer/src/cloud/strategy/cloud_force_push_strategy.cpp @@ -57,6 +57,10 @@ bool CloudForcePushStrategy::JudgeUpdateCursor() const bool CloudForcePushStrategy::JudgeUpload() const { + if (syncFlowType_ == SyncFlowType::DOWNLOAD_ONLY) { + LOGI("[CloudForcePushStrategy] syncFlowType is DOWNLOAD_ONLY, skip upload"); + return false; + } return true; } } \ No newline at end of file diff --git a/frameworks/libs/distributeddb/syncer/src/cloud/strategy/cloud_merge_strategy.cpp b/frameworks/libs/distributeddb/syncer/src/cloud/strategy/cloud_merge_strategy.cpp index 489a0f25251b5ec646e2ee3b6c3495974765d03f..313ddcdfc2f878f59869a878e0c70944ccf78cd8 100644 --- a/frameworks/libs/distributeddb/syncer/src/cloud/strategy/cloud_merge_strategy.cpp +++ b/frameworks/libs/distributeddb/syncer/src/cloud/strategy/cloud_merge_strategy.cpp @@ -61,6 +61,10 @@ bool CloudMergeStrategy::JudgeUpdateCursor() const bool CloudMergeStrategy::JudgeUpload() const { + if (syncFlowType_ == SyncFlowType::DOWNLOAD_ONLY) { + LOGI("[CloudMergeStrategy] syncFlowType is DOWNLOAD_ONLY, skip upload"); + return false; + } return true; } diff --git a/frameworks/libs/distributeddb/syncer/src/cloud/strategy/cloud_sync_strategy.cpp b/frameworks/libs/distributeddb/syncer/src/cloud/strategy/cloud_sync_strategy.cpp index 3f016179f605e2740db83c21da2b659af1cebcc3..943f156b75d78f663b5cdcc6b68047143f1a4a05 100644 --- a/frameworks/libs/distributeddb/syncer/src/cloud/strategy/cloud_sync_strategy.cpp +++ b/frameworks/libs/distributeddb/syncer/src/cloud/strategy/cloud_sync_strategy.cpp @@ -35,6 +35,11 @@ SingleVerConflictResolvePolicy CloudSyncStrategy::GetConflictResolvePolicy() con return policy_; } +void CloudSyncStrategy::SetSyncFlowType(const SyncFlowType syncFlowType) +{ + syncFlowType_ = syncFlowType; +} + OpType CloudSyncStrategy::TagSyncDataStatus(const DataStatusInfo &statusInfo, const LogInfo &localInfo, [[gnu::unused]] const VBucket &localData, const LogInfo &cloudInfo, [[gnu::unused]] VBucket &cloudData) const diff --git a/frameworks/libs/distributeddb/syncer/src/cloud/strategy/cloud_sync_strategy.h b/frameworks/libs/distributeddb/syncer/src/cloud/strategy/cloud_sync_strategy.h index 70839d6e4ee6e025d79a114319a1602ff44bd2df..5c882dd51df9bac540aba177827f779f4a1e0f88 100644 --- a/frameworks/libs/distributeddb/syncer/src/cloud/strategy/cloud_sync_strategy.h +++ b/frameworks/libs/distributeddb/syncer/src/cloud/strategy/cloud_sync_strategy.h @@ -17,6 +17,7 @@ #define CLOUD_SYNC_STRATEGY_H #include "cloud/icloud_conflict_handler.h" +#include "cloud_store_types.h" #include "data_transformer.h" #include "db_errno.h" #include "db_types.h" @@ -39,6 +40,8 @@ public: SingleVerConflictResolvePolicy GetConflictResolvePolicy() const; + void SetSyncFlowType(const SyncFlowType syncFlowType); + virtual OpType TagSyncDataStatus(const DataStatusInfo &statusInfo, const LogInfo &localInfo, const VBucket &localData, const LogInfo &cloudInfo, VBucket &cloudData) const; @@ -71,6 +74,7 @@ protected: static bool IsSameRecord(const LogInfo &cloudInfo, const LogInfo &localInfo); SingleVerConflictResolvePolicy policy_; + SyncFlowType syncFlowType_ = SyncFlowType::NORMAL; // isKvScene_ is used to distinguish between the KV and RDB in the following scenarios: // 1. Whether upload to the cloud after delete local data that does not have a gid. diff --git a/frameworks/libs/distributeddb/syncer/src/cloud/strategy/strategy_factory.cpp b/frameworks/libs/distributeddb/syncer/src/cloud/strategy/strategy_factory.cpp index 3e5314b57bc82d7f87fc9aae94a821989ee89ed8..f2dd0c030d873d0943cf9dc35d0b0cb04e0ca4eb 100644 --- a/frameworks/libs/distributeddb/syncer/src/cloud/strategy/strategy_factory.cpp +++ b/frameworks/libs/distributeddb/syncer/src/cloud/strategy/strategy_factory.cpp @@ -21,8 +21,8 @@ #include "strategy_factory.h" namespace DistributedDB { -std::shared_ptr StrategyFactory::BuildSyncStrategy( - SyncMode mode, bool isKvScene, SingleVerConflictResolvePolicy policy) +std::shared_ptr StrategyFactory::BuildSyncStrategy(SyncMode mode, SyncFlowType syncFlowType, + bool isKvScene, SingleVerConflictResolvePolicy policy) { std::shared_ptr strategy; switch (mode) { @@ -47,6 +47,7 @@ std::shared_ptr StrategyFactory::BuildSyncStrategy( } strategy->SetConflictResolvePolicy(policy); strategy->SetIsKvScene(isKvScene); + strategy->SetSyncFlowType(syncFlowType); return strategy; } } diff --git a/frameworks/libs/distributeddb/syncer/src/cloud/strategy/strategy_factory.h b/frameworks/libs/distributeddb/syncer/src/cloud/strategy/strategy_factory.h index 82c4ae385ff9d68bcc88aceb03cf951bd9173386..431652ea145bf5b40c3c30ae76db0f33880da188 100644 --- a/frameworks/libs/distributeddb/syncer/src/cloud/strategy/strategy_factory.h +++ b/frameworks/libs/distributeddb/syncer/src/cloud/strategy/strategy_factory.h @@ -15,13 +15,15 @@ #ifndef STRATEGY_FACTORY_H #define STRATEGY_FACTORY_H +#include "cloud_store_types.h" #include "cloud_sync_strategy.h" #include "db_common.h" #include "store_types.h" namespace DistributedDB { class StrategyFactory { public: - static std::shared_ptr BuildSyncStrategy(SyncMode mode, bool isKvScene = false, + static std::shared_ptr BuildSyncStrategy(SyncMode mode, + SyncFlowType syncFlowType = SyncFlowType::NORMAL, bool isKvScene = false, SingleVerConflictResolvePolicy policy = SingleVerConflictResolvePolicy::DEFAULT_LAST_WIN); }; } diff --git a/frameworks/libs/distributeddb/syncer/src/cloud/strategy_proxy.cpp b/frameworks/libs/distributeddb/syncer/src/cloud/strategy_proxy.cpp index bd8fafa81c9f5e966160923c921700ad93f0faa6..98ab5e5d89a5a9ab701c33052bbb039d0ff76443 100644 --- a/frameworks/libs/distributeddb/syncer/src/cloud/strategy_proxy.cpp +++ b/frameworks/libs/distributeddb/syncer/src/cloud/strategy_proxy.cpp @@ -37,10 +37,10 @@ void StrategyProxy::CopyStrategy(const StrategyProxy &other) strategy_ = other.strategy_; } -void StrategyProxy::UpdateStrategy(SyncMode mode, bool isKvScene, SingleVerConflictResolvePolicy policy, - const std::weak_ptr &handler) +void StrategyProxy::UpdateStrategy(SyncMode mode, SyncFlowType syncFlowType, bool isKvScene, + SingleVerConflictResolvePolicy policy, const std::weak_ptr &handler) { - auto strategy = StrategyFactory::BuildSyncStrategy(mode, isKvScene, policy); + auto strategy = StrategyFactory::BuildSyncStrategy(mode, syncFlowType, isKvScene, policy); std::lock_guard autoLock(strategyMutex_); strategy_ = strategy; strategy_->SetCloudConflictHandler(handler); diff --git a/frameworks/libs/distributeddb/syncer/src/cloud/strategy_proxy.h b/frameworks/libs/distributeddb/syncer/src/cloud/strategy_proxy.h index db31c3dcbfdd3ab900cd91b50cf6cbba61d6e2b1..857411dd01c4a00ab3ad080dbd91857ff612e39b 100644 --- a/frameworks/libs/distributeddb/syncer/src/cloud/strategy_proxy.h +++ b/frameworks/libs/distributeddb/syncer/src/cloud/strategy_proxy.h @@ -39,7 +39,7 @@ public: ICloudSyncer::SyncParam ¶m, ICloudSyncer::DataInfo &dataInfo) const; std::pair TagStatusByStrategy(bool isExist, size_t idx, const std::shared_ptr &storage, ICloudSyncer::SyncParam ¶m, ICloudSyncer::DataInfo &dataInfo) const; - void UpdateStrategy(SyncMode mode, bool isKvScene, SingleVerConflictResolvePolicy policy, + void UpdateStrategy(SyncMode mode, SyncFlowType syncFlowType, bool isKvScene, SingleVerConflictResolvePolicy policy, const std::weak_ptr &handler); void ResetStrategy(); void SetCloudConflictHandler(const std::shared_ptr &handler); diff --git a/frameworks/libs/distributeddb/test/unittest/common/common/rdb_general_ut.cpp b/frameworks/libs/distributeddb/test/unittest/common/common/rdb_general_ut.cpp index 3f22df1c842583f7ea9e9bc59925e0b6e73fb285..a31030fdbad697aa0d69df1d097630285195bf8e 100644 --- a/frameworks/libs/distributeddb/test/unittest/common/common/rdb_general_ut.cpp +++ b/frameworks/libs/distributeddb/test/unittest/common/common/rdb_general_ut.cpp @@ -500,6 +500,12 @@ void RDBGeneralUt::CloudBlockSync(const StoreInfo &from, const Query &query, DBS void RDBGeneralUt::CloudBlockSync(const StoreInfo &from, const Query &query, SyncMode mode, DBStatus exceptStatus, DBStatus callbackExpect) +{ + CloudBlockSync(from, query, mode, SyncFlowType::NORMAL, exceptStatus, callbackExpect); +} + +void RDBGeneralUt::CloudBlockSync(const StoreInfo &from, const Query &query, SyncMode mode, SyncFlowType syncFlowType, + DBStatus exceptStatus, DBStatus callbackExpect) { LOGI("[RDBGeneralUt] Begin cloud sync, app %s store %s user %s", from.appId.c_str(), from.storeId.c_str(), from.userId.c_str()); @@ -511,6 +517,7 @@ void RDBGeneralUt::CloudBlockSync(const StoreInfo &from, const Query &query, Syn option.query = query; option.priorityTask = true; option.waitTime = DBConstant::MAX_TIMEOUT; + option.syncFlowType = syncFlowType; RelationalTestUtils::CloudBlockSync(option, delegate, exceptStatus, callbackExpect); } diff --git a/frameworks/libs/distributeddb/test/unittest/common/common/rdb_general_ut.h b/frameworks/libs/distributeddb/test/unittest/common/common/rdb_general_ut.h index 18da1f4064e2b2560328237c6018991120a4e15e..fbbe7004d59a03ea5c8440d50b0c47f124ee40d0 100644 --- a/frameworks/libs/distributeddb/test/unittest/common/common/rdb_general_ut.h +++ b/frameworks/libs/distributeddb/test/unittest/common/common/rdb_general_ut.h @@ -105,6 +105,9 @@ protected: void CloudBlockSync(const StoreInfo &from, const Query &query, SyncMode mode, DBStatus exceptStatus, DBStatus callbackExpect); + void CloudBlockSync(const StoreInfo &from, const Query &query, SyncMode mode, SyncFlowType syncFlowType, + DBStatus exceptStatus, DBStatus callbackExpect); + void SetCloudDbConfig(const StoreInfo &info) const; int GetCloudDataCount(const std::string &tableName) const; diff --git a/frameworks/libs/distributeddb/test/unittest/common/storage/cloud/distributeddb_cloud_task_merge_test.cpp b/frameworks/libs/distributeddb/test/unittest/common/storage/cloud/distributeddb_cloud_task_merge_test.cpp index 80746067b12398b20bb7af22fdeceb34bdeb0f97..2f408031119b0d9a5e3aa69b1c3cf317686848b6 100644 --- a/frameworks/libs/distributeddb/test/unittest/common/storage/cloud/distributeddb_cloud_task_merge_test.cpp +++ b/frameworks/libs/distributeddb/test/unittest/common/storage/cloud/distributeddb_cloud_task_merge_test.cpp @@ -76,7 +76,8 @@ void CreateUserDBAndTable(sqlite3 *&db) EXPECT_EQ(RelationalTestUtils::ExecSql(db, CREATE_TABLE_D_SQL), SQLITE_OK); } -void PrepareOption(CloudSyncOption &option, const Query &query, bool merge = false) +void PrepareOption(CloudSyncOption &option, const Query &query, bool merge = false, + SyncFlowType flowType = SyncFlowType::NORMAL) { option.devices = { "CLOUD" }; option.mode = SYNC_MODE_CLOUD_MERGE; @@ -500,5 +501,59 @@ HWTEST_F(DistributedDBCloudTaskMergeTest, CloudSyncMergeTaskTest004, TestSize.Le return (finishCount >= 2u); // download 2 times }); } + +/** + * @tc.name: CloudSyncMergeTaskTest005 + * @tc.desc: test merge sync task with DOWNLOAD_ONLY mode, verify tasks are merged correctly. + * @tc.type: FUNC + * @tc.require: + * @tc.author: xiefengzhu + */ +HWTEST_F(DistributedDBCloudTaskMergeTest, CloudSyncMergeTaskTest005, TestSize.Level1) +{ + /** + * @tc.steps:step1. insert user table record. + * @tc.expected: step1. ok. + */ + const int actualCount = 10; // 10 is count of records + InsertUserTableRecord(tableNameA_, actualCount); + InsertUserTableRecord(tableNameB_, actualCount); + /** + * @tc.steps:step2. start first sync task with DOWNLOAD_ONLY mode. + * @tc.expected: step2. ok. + */ + Query normalQuery1 = Query::Select().FromTable({ tableNameA_ }); + CloudSyncOption option1; + PrepareOption(option1, normalQuery1, false, SyncFlowType::DOWNLOAD_ONLY); + ASSERT_EQ(delegate_->Sync(option1, nullptr), OK); + + /** + * @tc.steps:step3. start third sync task with NORMAL mode, should not be merged. + * @tc.expected: step3. task not merged due to different syncFlowType. + */ + auto callback2 = [](const std::map &process) { + for (const auto &item: process) { + ASSERT_EQ(item.second.errCode, OK); + } + }; + Query normalQuery2 = Query::Select().FromTable({ tableNameB_ }); + CloudSyncOption option2; + PrepareOption(option2, normalQuery2, true, SyncFlowType::NORMAL); + ASSERT_EQ(delegate_->Sync(option2, callback2), OK); + + /** + * @tc.steps:step4. start second sync task with DOWNLOAD_ONLY mode, should be merged. + * @tc.expected: step4. task merged with same syncFlowType. + */ + auto callback3 = [](const std::map &process) { + for (const auto &item: process) { + ASSERT_EQ(item.second.errCode, CLOUD_SYNC_TASK_MERGED); + } + }; + Query normalQuery3 = Query::Select().FromTable({ tableNameB_ }); + CloudSyncOption option3; + PrepareOption(option3, normalQuery3, true, SyncFlowType::DOWNLOAD_ONLY); + ASSERT_EQ(delegate_->Sync(option3, callback3), OK); +} } #endif \ No newline at end of file diff --git a/frameworks/libs/distributeddb/test/unittest/common/store_test/rdb/distributeddb_rdb_complex_cloud_test.cpp b/frameworks/libs/distributeddb/test/unittest/common/store_test/rdb/distributeddb_rdb_complex_cloud_test.cpp index 5316df6351f1790baf7d640bed9486a95a4d29cd..42e01fecc9f975e3a91722c66287ebd7dc81f748 100644 --- a/frameworks/libs/distributeddb/test/unittest/common/store_test/rdb/distributeddb_rdb_complex_cloud_test.cpp +++ b/frameworks/libs/distributeddb/test/unittest/common/store_test/rdb/distributeddb_rdb_complex_cloud_test.cpp @@ -13,7 +13,12 @@ * limitations under the License. */ +#include "cloud/cloud_db_constant.h" +#include "cloud/cloud_storage_utils.h" +#include "db_common.h" #include "rdb_general_ut.h" +#include "sqlite_utils.h" +#include "time_helper.h" #ifdef USE_DISTRIBUTEDDB_CLOUD using namespace testing::ext; @@ -28,6 +33,10 @@ public: protected: static constexpr const char *CLOUD_SYNC_TABLE_A = "CLOUD_SYNC_TABLE_A"; static constexpr const char *CLOUD_SYNC_TABLE_B = "CLOUD_SYNC_TABLE_B"; + static constexpr int DATA_COUNT_PER_OP = 20; + static constexpr int ASSET_COUNT = 30; + static constexpr const int64_t BASE_MODIFY_TIME = 12345678L; + static constexpr const int64_t BASE_CREATE_TIME = 12345679L; void InitTables(const std::string &table = CLOUD_SYNC_TABLE_A); void InitCompositeTable(const StoreInfo &info1, const StoreInfo &info2, const std::string &table = CLOUD_SYNC_TABLE_B); @@ -37,6 +46,17 @@ protected: const std::vector &tables = {CLOUD_SYNC_TABLE_A}); void ExpireCursorWithEmptyGid(bool isLogicDelete, SyncMode mode = SyncMode::SYNC_MODE_CLOUD_MERGE); int GetActualTableColumnCount(const StoreInfo &info, const std::string &table); + + void InsertCloudData(int64_t begin, int64_t count, const std::string &tableName); + void UpdateCloudData(int64_t begin, int64_t count, const std::string &tableName); + void DeleteCloudData(int64_t begin, int64_t count, const std::string &tableName); + void InsertLocalData(int64_t begin, int64_t count, const StoreInfo &info, const std::string &tableName); + void UpdateLocalData(int64_t begin, int64_t count, const StoreInfo &info, const std::string &tableName); + void DeleteLocalData(int64_t begin, int64_t count, const StoreInfo &info, const std::string &tableName); + void SetAssetsDownloadingStatus(int64_t begin, int64_t count, const StoreInfo &info, const std::string &tableName); + int GetLocalDataCount(const StoreInfo &info, const std::string &tableName); + int GetCloudDataCount(const std::string &tableName); + StoreInfo info1_ = {USER_ID, APP_ID, STORE_ID_1}; StoreInfo info2_ = {USER_ID, APP_ID, STORE_ID_2}; }; @@ -62,7 +82,8 @@ void DistributedDBRDBComplexCloudTest::InitTables(const std::string &table) { std::string sql = "CREATE TABLE IF NOT EXISTS " + table + "(" "id INTEGER PRIMARY KEY AUTOINCREMENT," - "intCol INTEGER, stringCol1 TEXT, stringCol2 TEXT, uuidCol TEXT)"; + "intCol INTEGER, stringCol1 TEXT, stringCol2 TEXT, uuidCol TEXT," + "assetCol ASSET, assetsCol ASSETS)"; EXPECT_EQ(ExecuteSQL(sql, info1_), E_OK); EXPECT_EQ(ExecuteSQL(sql, info2_), E_OK); } @@ -72,6 +93,7 @@ void DistributedDBRDBComplexCloudTest::InitCompositeTable(const StoreInfo &info1 { std::string sql = "CREATE TABLE IF NOT EXISTS " + table + "(" "id INTEGER, intCol INTEGER, stringCol1 TEXT, stringCol2 TEXT," + "assetCol ASSET, assetsCol ASSETS," "PRIMARY KEY (id, intCol))"; EXPECT_EQ(ExecuteSQL(sql, info1), E_OK); EXPECT_EQ(ExecuteSQL(sql, info2), E_OK); @@ -84,6 +106,8 @@ void DistributedDBRDBComplexCloudTest::InitSchema(const StoreInfo &info, const s {{"intCol", TYPE_INDEX, false, true}, false}, {{"stringCol1", TYPE_INDEX, false, true}, false}, {{"stringCol2", TYPE_INDEX, false, true}, false}, + {{"assetCol", TYPE_INDEX, false, true}, false}, + {{"assetsCol", TYPE_INDEX, false, true}, false}, }; UtDateBaseSchemaInfo schemaInfo = { .tablesInfo = { @@ -100,6 +124,8 @@ void DistributedDBRDBComplexCloudTest::InitCompositeSchema(const StoreInfo &info {{"intCol", TYPE_INDEX, true, true}, false}, {{"stringCol1", TYPE_INDEX, false, true}, false}, {{"stringCol2", TYPE_INDEX, false, true}, false}, + {{"assetCol", TYPE_INDEX, false, true}, false}, + {{"assetsCol", TYPE_INDEX, false, true}, false}, }; UtDateBaseSchemaInfo schemaInfo = { .tablesInfo = { @@ -156,7 +182,8 @@ HWTEST_F(DistributedDBRDBComplexCloudTest, ExpireCursor001, TestSize.Level0) * @tc.steps:step1. store1 insert one data * @tc.expected: step1. insert success. */ - auto ret = ExecuteSQL("INSERT INTO CLOUD_SYNC_TABLE_A VALUES(1, 1, 'text1', 'text2', 'uuid1')", info1_); + auto ret = ExecuteSQL("INSERT INTO CLOUD_SYNC_TABLE_A VALUES(1, 1, 'text1', 'text2', 'uuid1', NULL, NULL)", + info1_); ASSERT_EQ(ret, E_OK); /** * @tc.steps:step2. store1 push and store2 pull @@ -188,7 +215,8 @@ HWTEST_F(DistributedDBRDBComplexCloudTest, ExpireCursor002, TestSize.Level2) * @tc.steps:step1. store1 insert one data * @tc.expected: step1. insert success. */ - auto ret = ExecuteSQL("INSERT INTO CLOUD_SYNC_TABLE_A VALUES(1, 1, 'text1', 'text2', 'uuid1')", info1_); + auto ret = ExecuteSQL("INSERT INTO CLOUD_SYNC_TABLE_A VALUES(1, 1, 'text1', 'text2', 'uuid1', NULL, NULL)", + info1_); ASSERT_EQ(ret, E_OK); /** * @tc.steps:step2. store1 push and store2 pull @@ -217,7 +245,8 @@ HWTEST_F(DistributedDBRDBComplexCloudTest, ExpireCursor003, TestSize.Level2) * @tc.steps:step1. store1 insert one data * @tc.expected: step1. insert success. */ - auto ret = ExecuteSQL("INSERT INTO CLOUD_SYNC_TABLE_A VALUES(1, 1, 'text1', 'text2', 'uuid1')", info1_); + auto ret = ExecuteSQL("INSERT INTO CLOUD_SYNC_TABLE_A VALUES(1, 1, 'text1', 'text2', 'uuid1', NULL, NULL)", + info1_); ASSERT_EQ(ret, E_OK); /** * @tc.steps:step2. store1 push and store2 pull @@ -250,7 +279,8 @@ HWTEST_F(DistributedDBRDBComplexCloudTest, ExpireCursor004, TestSize.Level2) * @tc.steps:step1. store1 insert one data * @tc.expected: step1. insert success. */ - auto ret = ExecuteSQL("INSERT INTO CLOUD_SYNC_TABLE_A VALUES(1, 1, 'text1', 'text2', 'uuid1')", info1_); + auto ret = ExecuteSQL("INSERT INTO CLOUD_SYNC_TABLE_A VALUES(1, 1, 'text1', 'text2', 'uuid1', NULL, NULL)", + info1_); ASSERT_EQ(ret, E_OK); /** * @tc.steps:step2. store1 push and store2 pull @@ -278,9 +308,10 @@ void DistributedDBRDBComplexCloudTest::ExpireCursorWithEmptyGid(bool isLogicDele * @tc.steps:step1. store1 insert one data * @tc.expected: step1. insert success. */ - auto ret = ExecuteSQL("INSERT INTO CLOUD_SYNC_TABLE_A VALUES(1, 1, 'text1', 'text2', 'uuid1')", info1_); + auto ret = ExecuteSQL("INSERT INTO CLOUD_SYNC_TABLE_A VALUES(1, 1, 'text1', 'text2', 'uuid1', NULL, NULL)", + info1_); ASSERT_EQ(ret, E_OK); - ret = ExecuteSQL("INSERT INTO CLOUD_SYNC_TABLE_A VALUES(2, 2, 'text3', 'text4', 'uuid2')", info2_); + ret = ExecuteSQL("INSERT INTO CLOUD_SYNC_TABLE_A VALUES(2, 2, 'text3', 'text4', 'uuid2', NULL, NULL)", info2_); ASSERT_EQ(ret, E_OK); /** * @tc.steps:step2. store1 push and store2 pull @@ -357,7 +388,7 @@ HWTEST_F(DistributedDBRDBComplexCloudTest, ExpireCursor007, TestSize.Level0) * @tc.steps:step1. store1 insert one data * @tc.expected: step1. insert success. */ - auto ret = ExecuteSQL("INSERT INTO CLOUD_SYNC_TABLE_B VALUES(1, 1, 'text1', 'text2')", info1); + auto ret = ExecuteSQL("INSERT INTO CLOUD_SYNC_TABLE_B VALUES(1, 1, 'text1', 'text2', NULL, NULL)", info1); ASSERT_EQ(ret, E_OK); /** * @tc.steps:step2. store1 push and store2 pull @@ -389,7 +420,8 @@ HWTEST_F(DistributedDBRDBComplexCloudTest, ExpireCursor008, TestSize.Level0) * @tc.steps:step1. store1 insert one data * @tc.expected: step1. insert success. */ - auto ret = ExecuteSQL("INSERT INTO CLOUD_SYNC_TABLE_A VALUES(1, 1, 'text1', 'text2', 'uuid1')", info1_); + auto ret = ExecuteSQL("INSERT INTO CLOUD_SYNC_TABLE_A VALUES(1, 1, 'text1', 'text2', 'uuid1', NULL, NULL)", + info1_); ASSERT_EQ(ret, E_OK); /** * @tc.steps:step2. store1 push and store2 pull @@ -454,7 +486,8 @@ HWTEST_F(DistributedDBRDBComplexCloudTest, ExpireCursor011, TestSize.Level2) * @tc.steps:step1. store1 insert one data * @tc.expected: step1. insert success. */ - auto ret = ExecuteSQL("INSERT INTO CLOUD_SYNC_TABLE_A VALUES(1, 1, 'text1', 'text2', 'uuid1')", info1_); + auto ret = ExecuteSQL("INSERT INTO CLOUD_SYNC_TABLE_A VALUES(1, 1, 'text1', 'text2', 'uuid1', NULL, NULL)", + info1_); ASSERT_EQ(ret, E_OK); /** * @tc.steps:step2. store1 push @@ -489,7 +522,7 @@ HWTEST_F(DistributedDBRDBComplexCloudTest, UpgradeDistributedTable001, TestSize. { /** * @tc.steps:step1. Get column count from actual database before modification - * @tc.expected: step1. Get original column count (4 columns: id, intCol, stringCol1, stringCol2). + * @tc.expected: step1. Get original column count (6 columns: id, intCol, stringCol1, stringCol2, assetCol, assetsCol). */ int originalColumnCount = GetActualTableColumnCount(info1_, CLOUD_SYNC_TABLE_A); EXPECT_GE(originalColumnCount, 0); @@ -514,7 +547,8 @@ HWTEST_F(DistributedDBRDBComplexCloudTest, UpgradeDistributedTable001, TestSize. * @tc.steps:step4. Insert data with new column * @tc.expected: step4. insert success. */ - ret = ExecuteSQL("INSERT INTO CLOUD_SYNC_TABLE_A VALUES(1, 1, 'text1', 'text2', 'uuid1', 100)", info1_); + ret = ExecuteSQL("INSERT INTO CLOUD_SYNC_TABLE_A VALUES(1, 1, 'text1', 'text2', 'uuid1', NULL, NULL, 100)", + info1_); EXPECT_EQ(ret, E_OK); /** @@ -540,5 +574,363 @@ HWTEST_F(DistributedDBRDBComplexCloudTest, UpgradeDistributedTable001, TestSize. auto count = CountTableData(info1_, CLOUD_SYNC_TABLE_A); EXPECT_GE(count, 1); } + +void DistributedDBRDBComplexCloudTest::InsertCloudData(int64_t begin, int64_t count, const std::string &tableName) +{ + auto cloudDB = GetVirtualCloudDb(); + ASSERT_NE(cloudDB, nullptr); + std::vector records; + std::vector extends; + for (int64_t i = begin; i < begin + count; ++i) { + VBucket record; + record["id"] = i; + record["intCol"] = i * 10; + record["stringCol1"] = "cloud_insert_" + std::to_string(i); + record["stringCol2"] = "cloud_insert_str2_" + std::to_string(i); + record["uuidCol"] = "uuid_" + std::to_string(i); + record["assetCol"] = Asset{}; + record["assetsCol"] = Assets{}; + records.push_back(std::move(record)); + + VBucket extend; + extend[CloudDbConstant::GID_FIELD] = std::to_string(i); + extend[CloudDbConstant::CREATE_FIELD] = BASE_CREATE_TIME; + extend[CloudDbConstant::MODIFY_FIELD] = BASE_MODIFY_TIME; + extend[CloudDbConstant::DELETE_FIELD] = false; + extends.push_back(std::move(extend)); + } + EXPECT_EQ(cloudDB->BatchInsertWithGid(tableName, std::move(records), extends), DBStatus::OK); + LOGI("[DistributedDBRDBComplexCloudTest] InsertCloudData success, begin=%" PRId64 ", count=%" PRId64, + begin, count); +} + +void DistributedDBRDBComplexCloudTest::UpdateCloudData(int64_t begin, int64_t count, const std::string &tableName) +{ + auto cloudDB = GetVirtualCloudDb(); + ASSERT_NE(cloudDB, nullptr); + std::vector records; + std::vector extends; + for (int64_t i = begin; i < begin + count; ++i) { + VBucket record; + record["id"] = i; + record["intCol"] = i * 100; + record["stringCol1"] = "cloud_update_" + std::to_string(i); + record["stringCol2"] = "cloud_update_str2_" + std::to_string(i); + record["uuidCol"] = "uuid_update_" + std::to_string(i); + record["assetCol"] = Asset{}; + record["assetsCol"] = Assets{}; + records.push_back(std::move(record)); + + VBucket extend; + extend[CloudDbConstant::GID_FIELD] = std::to_string(i); + extend[CloudDbConstant::CREATE_FIELD] = BASE_CREATE_TIME; + extend[CloudDbConstant::MODIFY_FIELD] = BASE_MODIFY_TIME + i; + extends.push_back(std::move(extend)); + } + EXPECT_EQ(cloudDB->BatchUpdate(tableName, std::move(records), extends), DBStatus::OK); + + LOGI("[DistributedDBRDBComplexCloudTest] UpdateCloudData success, begin=%" PRId64 ", count=%" PRId64, + begin, count); +} + +void DistributedDBRDBComplexCloudTest::DeleteCloudData(int64_t begin, int64_t count, const std::string &tableName) +{ + auto cloudDB = GetVirtualCloudDb(); + ASSERT_NE(cloudDB, nullptr); + std::vector extends; + for (int64_t i = begin; i < begin + count; ++i) { + VBucket extend; + extend[CloudDbConstant::GID_FIELD] = std::to_string(i); + extend[CloudDbConstant::CREATE_FIELD] = BASE_CREATE_TIME; + extend[CloudDbConstant::MODIFY_FIELD] = BASE_MODIFY_TIME + i; + extends.push_back(std::move(extend)); + } + EXPECT_EQ(cloudDB->BatchDelete(tableName, extends), DBStatus::OK); + LOGI("[DistributedDBRDBComplexCloudTest] DeleteCloudData success, begin=%" PRId64 ", count=%" PRId64, + begin, count); +} + +void DistributedDBRDBComplexCloudTest::InsertLocalData(int64_t begin, int64_t count, const StoreInfo &info, + const std::string &tableName) +{ + for (int64_t i = begin; i < begin + count; ++i) { + std::string sql = "INSERT INTO " + tableName + " VALUES(" + std::to_string(i) + ", " + + std::to_string(i * 10) + ", 'local_insert_" + std::to_string(i) + "', 'local_str2_" + + std::to_string(i) + "', 'local_uuid_" + std::to_string(i) + "', NULL, NULL)"; + EXPECT_EQ(ExecuteSQL(sql, info), E_OK); + } + LOGI("[DistributedDBRDBComplexCloudTest] InsertLocalData success, begin=%" PRId64 ", count=%" PRId64, + begin, count); +} + +void DistributedDBRDBComplexCloudTest::UpdateLocalData(int64_t begin, int64_t count, const StoreInfo &info, + const std::string &tableName) +{ + for (int64_t i = begin; i < begin + count; ++i) { + std::string sql = "UPDATE " + tableName + " SET intCol=" + std::to_string(i * 100) + + ", stringCol1='local_update_" + std::to_string(i) + "' WHERE id=" + std::to_string(i); + EXPECT_EQ(ExecuteSQL(sql, info), E_OK); + } + LOGI("[DistributedDBRDBComplexCloudTest] UpdateLocalData success, begin=%" PRId64 ", count=%" PRId64, + begin, count); +} + +void DistributedDBRDBComplexCloudTest::DeleteLocalData(int64_t begin, int64_t count, const StoreInfo &info, + const std::string &tableName) +{ + for (int64_t i = begin; i < begin + count; ++i) { + std::string sql = "DELETE FROM " + tableName + " WHERE id=" + std::to_string(i); + EXPECT_EQ(ExecuteSQL(sql, info), E_OK); + } + LOGI("[DistributedDBRDBComplexCloudTest] DeleteLocalData success, begin=%" PRId64 ", count=%" PRId64, + begin, count); +} + +void DistributedDBRDBComplexCloudTest::SetAssetsDownloadingStatus(int64_t begin, int64_t count, const StoreInfo &info, + const std::string &tableName) +{ + auto db = GetSqliteHandle(info); + ASSERT_NE(db, nullptr); + std::string logTable = DBCommon::GetLogTableName(tableName); + std::string sql = "UPDATE " + logTable + " SET status=" + + std::to_string(static_cast(AssetStatus::DOWNLOADING)) + + " WHERE data_key >= " + std::to_string(begin) + + " AND data_key < " + std::to_string(begin + count); + EXPECT_EQ(SQLiteUtils::ExecuteRawSQL(db, sql), E_OK); + LOGI("[DistributedDBRDBComplexCloudTest] SetAssetsDownloadingStatus success, begin=%" PRId64 ", count=%" PRId64, + begin, count); +} + +int DistributedDBRDBComplexCloudTest::GetLocalDataCount(const StoreInfo &info, const std::string &tableName) +{ + return CountTableData(info, tableName); +} + +int DistributedDBRDBComplexCloudTest::GetCloudDataCount(const std::string &tableName) +{ + return RDBGeneralUt::GetCloudDataCount(tableName); +} + +/** + * @tc.name: DownloadOnlySync001 + * @tc.desc: Test downloadOnly sync with MERGE mode, local has no data, cloud has insert/update/delete data. + * @tc.type: FUNC + * @tc.author: xiefengzhu + */ +HWTEST_F(DistributedDBRDBComplexCloudTest, DownloadOnlySync001, TestSize.Level0) +{ + /** + * @tc.steps:step1. Prepare cloud data: insert/update/delete 20 records each + * @tc.expected: step1. cloud data prepared successfully. + */ + InsertCloudData(1, DATA_COUNT_PER_OP * 3, CLOUD_SYNC_TABLE_A); + UpdateCloudData(DATA_COUNT_PER_OP + 1, DATA_COUNT_PER_OP, CLOUD_SYNC_TABLE_A); + DeleteCloudData(DATA_COUNT_PER_OP * 2 + 1, DATA_COUNT_PER_OP, CLOUD_SYNC_TABLE_A); + + int cloudCountBefore = GetCloudDataCount(CLOUD_SYNC_TABLE_A); + LOGI("[DownloadOnlySync001] Cloud data count before sync: %d", cloudCountBefore); + + /** + * @tc.steps:step2. Execute downloadOnly sync with MERGE mode + * @tc.expected: step2. sync success. + */ + Query query = Query::Select().FromTable({CLOUD_SYNC_TABLE_A}); + EXPECT_NO_FATAL_FAILURE(CloudBlockSync(info1_, query, SyncMode::SYNC_MODE_CLOUD_MERGE, + SyncFlowType::DOWNLOAD_ONLY, OK, OK)); + + /** + * @tc.steps:step3. Verify local data is consistent with cloud + * @tc.expected: step3. local data count matches cloud. + */ + int localCountAfter = GetLocalDataCount(info1_, CLOUD_SYNC_TABLE_A); + int cloudCountAfter = GetCloudDataCount(CLOUD_SYNC_TABLE_A); + LOGI("[DownloadOnlySync001] Local count after sync: %d, Cloud count: %d", localCountAfter, cloudCountAfter); + EXPECT_EQ(localCountAfter, cloudCountAfter); +} + +/** + * @tc.name: DownloadOnlySync002 + * @tc.desc: Test downloadOnly sync with MERGE mode, both local and cloud have insert/update/delete data. + * @tc.expected: Local data not uploaded, local data correctly updated. + * @tc.type: FUNC + * @tc.author: xiefengzhu + */ +HWTEST_F(DistributedDBRDBComplexCloudTest, DownloadOnlySync002, TestSize.Level0) +{ + /** + * @tc.steps:step1. Prepare cloud data: insert/update/delete 20 records each (different range) + * @tc.expected: step1. cloud data prepared successfully. + */ + Query query = Query::Select().FromTable({CLOUD_SYNC_TABLE_A}); + InsertCloudData(1, DATA_COUNT_PER_OP * 3, CLOUD_SYNC_TABLE_A); + EXPECT_NO_FATAL_FAILURE(CloudBlockSync(info1_, query, SyncMode::SYNC_MODE_CLOUD_MERGE, + SyncFlowType::NORMAL, OK, OK)); + UpdateCloudData(DATA_COUNT_PER_OP + 1, DATA_COUNT_PER_OP, CLOUD_SYNC_TABLE_A); + DeleteCloudData(DATA_COUNT_PER_OP * 2 + 1, DATA_COUNT_PER_OP, CLOUD_SYNC_TABLE_A); + + int cloudCountBefore = GetCloudDataCount(CLOUD_SYNC_TABLE_A); + LOGI("[DownloadOnlySync002] Cloud data count before sync: %d", cloudCountBefore); + + /** + * @tc.steps:step2. Prepare local data: insert/update/delete 20 records each + * @tc.expected: step2. local data prepared successfully. + */ + InsertLocalData(DATA_COUNT_PER_OP * 3 + 1, DATA_COUNT_PER_OP * 3, info1_, CLOUD_SYNC_TABLE_A); + UpdateLocalData(DATA_COUNT_PER_OP * 4 + 1, DATA_COUNT_PER_OP, info1_, CLOUD_SYNC_TABLE_A); + DeleteLocalData(DATA_COUNT_PER_OP * 5 + 1, DATA_COUNT_PER_OP, info1_, CLOUD_SYNC_TABLE_A); + + int localCountBefore = GetLocalDataCount(info1_, CLOUD_SYNC_TABLE_A); + LOGI("[DownloadOnlySync002] Local data count before sync: %d", localCountBefore); + + /** + * @tc.steps:step3. Execute downloadOnly sync with MERGE mode + * @tc.expected: step3. sync success. + */ + EXPECT_NO_FATAL_FAILURE(CloudBlockSync(info1_, query, SyncMode::SYNC_MODE_CLOUD_MERGE, + SyncFlowType::DOWNLOAD_ONLY, OK, OK)); + + /** + * @tc.steps:step4. Verify local data not uploaded and correctly updated + * @tc.expected: step4. cloud data count unchanged, local data merged correctly. + */ + int cloudCountAfter = GetCloudDataCount(CLOUD_SYNC_TABLE_A); + EXPECT_EQ(cloudCountAfter, cloudCountBefore); + + int localCountAfter = GetLocalDataCount(info1_, CLOUD_SYNC_TABLE_A); + LOGI("[DownloadOnlySync002] Local count after sync: %d", localCountAfter); + EXPECT_GE(localCountAfter, localCountBefore - DATA_COUNT_PER_OP); +} + +/** + * @tc.name: DownloadOnlySync003 + * @tc.desc: Test downloadOnly sync with MERGE mode, local has DOWNLOADING status assets. + * @tc.expected: Local data not uploaded, local data correctly updated, assets downloaded. + * @tc.type: FUNC + * @tc.author: xiefengzhu + */ +HWTEST_F(DistributedDBRDBComplexCloudTest, DownloadOnlySync003, TestSize.Level0) +{ + /** + * @tc.steps:step1. Prepare local data with DOWNLOADING status assets + * @tc.expected: step1. local data prepared successfully. + */ + InsertLocalData(1, DATA_COUNT_PER_OP, info1_, CLOUD_SYNC_TABLE_A); + UpdateLocalData(1, DATA_COUNT_PER_OP / 2, info1_, CLOUD_SYNC_TABLE_A); + DeleteLocalData(DATA_COUNT_PER_OP / 2 + 1, DATA_COUNT_PER_OP / 2, info1_, CLOUD_SYNC_TABLE_A); + SetAssetsDownloadingStatus(1, ASSET_COUNT, info1_, CLOUD_SYNC_TABLE_A); + + /** + * @tc.steps:step2. Prepare cloud data + * @tc.expected: step2. cloud data prepared successfully. + */ + InsertCloudData(DATA_COUNT_PER_OP + 1, DATA_COUNT_PER_OP, CLOUD_SYNC_TABLE_A); + UpdateCloudData(DATA_COUNT_PER_OP + 1, DATA_COUNT_PER_OP / 2, CLOUD_SYNC_TABLE_A); + DeleteCloudData(DATA_COUNT_PER_OP + DATA_COUNT_PER_OP / 2 + 1, DATA_COUNT_PER_OP / 2, CLOUD_SYNC_TABLE_A); + + int cloudCountBefore = GetCloudDataCount(CLOUD_SYNC_TABLE_A); + + /** + * @tc.steps:step3. Execute downloadOnly sync with MERGE mode + * @tc.expected: step3. sync success. + */ + Query query = Query::Select().FromTable({CLOUD_SYNC_TABLE_A}); + EXPECT_NO_FATAL_FAILURE(CloudBlockSync(info1_, query, SyncMode::SYNC_MODE_CLOUD_MERGE, + SyncFlowType::DOWNLOAD_ONLY, OK, OK)); + + /** + * @tc.steps:step4. Verify local data not uploaded and correctly updated + * @tc.expected: step4. cloud data count unchanged, local data merged correctly. + */ + int cloudCountAfter = GetCloudDataCount(CLOUD_SYNC_TABLE_A); + EXPECT_EQ(cloudCountAfter, cloudCountBefore); +} + +/** + * @tc.name: DownloadOnlySync004 + * @tc.desc: Test downloadOnly sync with FORCE_PULL mode, local has DOWNLOADING status assets. + * @tc.expected: Local data not uploaded, local data correctly updated. + * @tc.type: FUNC + * @tc.author: xiefengzhu + */ +HWTEST_F(DistributedDBRDBComplexCloudTest, DownloadOnlySync004, TestSize.Level0) +{ + /** + * @tc.steps:step1. Prepare local data with DOWNLOADING status assets + * @tc.expected: step1. local data prepared successfully. + */ + InsertLocalData(1, DATA_COUNT_PER_OP, info1_, CLOUD_SYNC_TABLE_A); + UpdateLocalData(1, DATA_COUNT_PER_OP / 2, info1_, CLOUD_SYNC_TABLE_A); + DeleteLocalData(DATA_COUNT_PER_OP / 2 + 1, DATA_COUNT_PER_OP / 2, info1_, CLOUD_SYNC_TABLE_A); + SetAssetsDownloadingStatus(1, ASSET_COUNT, info1_, CLOUD_SYNC_TABLE_A); + + /** + * @tc.steps:step2. Prepare cloud data + * @tc.expected: step2. cloud data prepared successfully. + */ + InsertCloudData(DATA_COUNT_PER_OP + 1, DATA_COUNT_PER_OP, CLOUD_SYNC_TABLE_A); + UpdateCloudData(DATA_COUNT_PER_OP + 1, DATA_COUNT_PER_OP / 2, CLOUD_SYNC_TABLE_A); + DeleteCloudData(DATA_COUNT_PER_OP + DATA_COUNT_PER_OP / 2 + 1, DATA_COUNT_PER_OP / 2, CLOUD_SYNC_TABLE_A); + + int cloudCountBefore = GetCloudDataCount(CLOUD_SYNC_TABLE_A); + + /** + * @tc.steps:step3. Execute downloadOnly sync with FORCE_PULL mode + * @tc.expected: step3. sync success. + */ + Query query = Query::Select().FromTable({CLOUD_SYNC_TABLE_A}); + EXPECT_NO_FATAL_FAILURE(CloudBlockSync(info1_, query, SyncMode::SYNC_MODE_CLOUD_FORCE_PULL, + SyncFlowType::DOWNLOAD_ONLY, OK, OK)); + + /** + * @tc.steps:step4. Verify local data not uploaded and correctly updated + * @tc.expected: step4. cloud data count unchanged, local data updated with cloud priority. + */ + int cloudCountAfter = GetCloudDataCount(CLOUD_SYNC_TABLE_A); + EXPECT_EQ(cloudCountAfter, cloudCountBefore); +} + +/** + * @tc.name: DownloadOnlySync005 + * @tc.desc: Test downloadOnly sync with FORCE_PUSH mode, local has DOWNLOADING status assets. + * @tc.expected: Local data not uploaded, local data correctly updated. + * @tc.type: FUNC + * @tc.author: xiefengzhu + */ +HWTEST_F(DistributedDBRDBComplexCloudTest, DownloadOnlySync005, TestSize.Level0) +{ + /** + * @tc.steps:step1. Prepare local data with DOWNLOADING status assets + * @tc.expected: step1. local data prepared successfully. + */ + InsertLocalData(1, DATA_COUNT_PER_OP, info1_, CLOUD_SYNC_TABLE_A); + UpdateLocalData(1, DATA_COUNT_PER_OP / 2, info1_, CLOUD_SYNC_TABLE_A); + DeleteLocalData(DATA_COUNT_PER_OP / 2 + 1, DATA_COUNT_PER_OP / 2, info1_, CLOUD_SYNC_TABLE_A); + SetAssetsDownloadingStatus(1, ASSET_COUNT, info1_, CLOUD_SYNC_TABLE_A); + + /** + * @tc.steps:step2. Prepare cloud data + * @tc.expected: step2. cloud data prepared successfully. + */ + InsertCloudData(DATA_COUNT_PER_OP + 1, DATA_COUNT_PER_OP, CLOUD_SYNC_TABLE_A); + UpdateCloudData(DATA_COUNT_PER_OP + 1, DATA_COUNT_PER_OP / 2, CLOUD_SYNC_TABLE_A); + DeleteCloudData(DATA_COUNT_PER_OP + DATA_COUNT_PER_OP / 2 + 1, DATA_COUNT_PER_OP / 2, CLOUD_SYNC_TABLE_A); + + int cloudCountBefore = GetCloudDataCount(CLOUD_SYNC_TABLE_A); + + /** + * @tc.steps:step3. Execute downloadOnly sync with FORCE_PUSH mode + * @tc.expected: step3. sync success. + */ + Query query = Query::Select().FromTable({CLOUD_SYNC_TABLE_A}); + EXPECT_NO_FATAL_FAILURE(CloudBlockSync(info1_, query, SyncMode::SYNC_MODE_CLOUD_FORCE_PUSH, + SyncFlowType::DOWNLOAD_ONLY, OK, OK)); + + /** + * @tc.steps:step4. Verify local data not uploaded (downloadOnly skips upload) + * @tc.expected: step4. cloud data count unchanged, local data updated. + */ + int cloudCountAfter = GetCloudDataCount(CLOUD_SYNC_TABLE_A); + EXPECT_EQ(cloudCountAfter, cloudCountBefore); +} } #endif diff --git a/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/cloud_syncer_test.h b/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/cloud_syncer_test.h index f647c0dab22e69fadac21b800bbb2bf338d64cdb..ac789c852b7487880875084e1e66774a3af46bc8 100644 --- a/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/cloud_syncer_test.h +++ b/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/cloud_syncer_test.h @@ -60,7 +60,7 @@ public: currentContext_.notifier = std::make_shared(this); currentContext_.processRecorder = std::make_shared(); currentContext_.notifier->Init({currentContext_.tableName}, { "cloud" }, cloudTaskInfos_[taskId].users); - strategyProxy_.UpdateStrategy(SyncMode::SYNC_MODE_CLOUD_MERGE, isKvScene_, + strategyProxy_.UpdateStrategy(SyncMode::SYNC_MODE_CLOUD_MERGE, SyncFlowType::NORMAL, isKvScene_, SingleVerConflictResolvePolicy::DEFAULT_LAST_WIN, std::weak_ptr()); closed_ = false; cloudTaskInfos_[taskId].callback = [this, taskId](const std::map &process) {