diff --git a/data_object/CMakeLists.txt b/data_object/CMakeLists.txt index 318c5f41f10a7072076ac8d88a6ca110ac73b9c7..117034f620a220414c4fd9269668dc16d0ad9b8a 100644 --- a/data_object/CMakeLists.txt +++ b/data_object/CMakeLists.txt @@ -35,6 +35,7 @@ include(${KV_STORE_DIR}/interfaces/CMakeLists.txt OPTIONAL) set(links secure mock adapter distributeddb kvdb) add_library(data_object SHARED ${data_object_src}) target_link_libraries(data_object ${links}) +target_include_directories(data_object PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/frameworks/innerkitsimpl/include) target_include_directories(data_object PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/frameworks/innerkitsimpl/include/common) target_include_directories(data_object PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/interfaces/innerkits) target_include_directories(data_object PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/../relational_store/interfaces/inner_api/common_type/include) \ No newline at end of file diff --git a/data_object/bundle.json b/data_object/bundle.json index 146b70fc55c04f18355e1b7abc52d6735852bd12..26237616c8df80245469345c178c585fcf0c5c0f 100644 --- a/data_object/bundle.json +++ b/data_object/bundle.json @@ -61,10 +61,7 @@ "dmsfwk", "hisysevent" ], - "third_party": [ - "libuv", - "bounds_checking_function" - ] + "third_party": [] }, "build": { "sub_component": [ diff --git a/data_object/frameworks/innerkitsimpl/include/adaptor/flat_object_storage_engine.h b/data_object/frameworks/innerkitsimpl/include/adaptor/flat_object_storage_engine.h index e549a1c32220265420f64ebbcdef62c804134ee2..d94ee1f1f9c986c02f6b6cc0c65193943fdf634b 100644 --- a/data_object/frameworks/innerkitsimpl/include/adaptor/flat_object_storage_engine.h +++ b/data_object/frameworks/innerkitsimpl/include/adaptor/flat_object_storage_engine.h @@ -49,6 +49,7 @@ public: void NotifyStatus(const std::string &sessionId, const std::string &deviceId, const std::string &status); void NotifyChange(const std::string &sessionId, const std::map> &changedData); private: + constexpr static const char *DISTRIBUTED_DATASYNC = "ohos.permission.DISTRIBUTED_DATASYNC"; std::mutex operationMutex_{}; std::shared_ptr storeManager_; std::map delegates_; diff --git a/data_object/frameworks/innerkitsimpl/include/common/common_types.h b/data_object/frameworks/innerkitsimpl/include/common/common_types.h new file mode 100644 index 0000000000000000000000000000000000000000..67d4e2e7081f375eba0310428bbb7448ed7b69a7 --- /dev/null +++ b/data_object/frameworks/innerkitsimpl/include/common/common_types.h @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_DATA_OBJECT_COMMON_TYPES_H +#define OHOS_DATA_OBJECT_COMMON_TYPES_H +#include +#include +#include +#include +namespace OHOS::CommonType { +struct AssetValue { + enum Status : int32_t { + STATUS_UNKNOWN, + STATUS_NORMAL, + STATUS_INSERT, + STATUS_UPDATE, + STATUS_DELETE, + STATUS_ABNORMAL, + STATUS_DOWNLOADING, + STATUS_BUTT + }; + static constexpr uint64_t NO_EXPIRES_TIME = 0; + uint32_t version = 0; + mutable uint32_t status = STATUS_UNKNOWN; + uint64_t expiresTime = NO_EXPIRES_TIME; + std::string id; + std::string name; + std::string uri; + std::string createTime; + std::string modifyTime; + std::string size; + std::string hash; + std::string path; +}; +using Bytes = std::vector; +using Asset = AssetValue; +using Assets = std::vector; +using Value = std::variant; +using ValuesBucket = std::map; +} +#endif // OHOS_DATA_OBJECT_COMMON_TYPES_H \ No newline at end of file diff --git a/data_object/frameworks/innerkitsimpl/include/common/logger.h b/data_object/frameworks/innerkitsimpl/include/common/logger.h index 2d591b0f0c6af53740f088876c6dc3017f8c2ddb..63f2a1e771e19ff6b13790c674bbc1f33a116701 100644 --- a/data_object/frameworks/innerkitsimpl/include/common/logger.h +++ b/data_object/frameworks/innerkitsimpl/include/common/logger.h @@ -60,7 +60,7 @@ static inline OHOS::HiviewDFX::HiLogLabel LogLabel() } \ } while (0) -#define LOG_FATAL(fmt, ...) \ +#define LOG_FATAL(fmt, ...) \ do { \ auto lable = LogLabel(); \ if (HiLogIsLoggable(lable.domain, lable.tag, LogLevel::LOG_FATAL)) { \ @@ -73,14 +73,15 @@ static inline OHOS::HiviewDFX::HiLogLabel LogLabel() #else #include #include +#define __FILE_NAME__ __FILE__ #define LOG_DEBUG(fmt, ...) \ - printf("[D][ObjectStore]%s:%d %s: " fmt "\n", __FILE__, __LINE__, __FUNCTION__, ##__VA_ARGS__) + printf("[D][ObjectStore]%s:%d %s: " fmt "\n", __FILE_NAME__, __LINE__, __FUNCTION__, ##__VA_ARGS__) #define LOG_ERROR(fmt, ...) \ - printf("[E][ObjectStore]%s:%d %s: " fmt "\n", __FILE__, __LINE__, __FUNCTION__, ##__VA_ARGS__) + printf("[E][ObjectStore]%s:%d %s: " fmt "\n", __FILE_NAME__, __LINE__, __FUNCTION__, ##__VA_ARGS__) #define LOG_INFO(fmt, ...) \ - printf("[I][ObjectStore]%s:%d %s: " fmt "\n", __FILE__, __LINE__, __FUNCTION__, ##__VA_ARGS__) + printf("[I][ObjectStore]%s:%d %s: " fmt "\n", __FILE_NAME__, __LINE__, __FUNCTION__, ##__VA_ARGS__) #define LOG_WARN(fmt, ...) \ - printf("[W][ObjectStore]%s:%d %s: " fmt "\n", __FILE__, __LINE__, __FUNCTION__, ##__VA_ARGS__) + printf("[W][ObjectStore]%s:%d %s: " fmt "\n", __FILE_NAME__, __LINE__, __FUNCTION__, ##__VA_ARGS__) #endif // #ifdef HILOG_ENABLE #endif // OBJECT_STORE_LOGGER_H diff --git a/data_object/frameworks/innerkitsimpl/include/common/object_radar_reporter.h b/data_object/frameworks/innerkitsimpl/include/common/object_radar_reporter.h index 95181502b7bc52420d111e9de342175e76d1c733..8c87673de6a8bc6853f3ce3ac5644fb04403ba4a 100644 --- a/data_object/frameworks/innerkitsimpl/include/common/object_radar_reporter.h +++ b/data_object/frameworks/innerkitsimpl/include/common/object_radar_reporter.h @@ -16,12 +16,15 @@ #ifndef OBJECT_RADAR_REPORTER_H #define OBJECT_RADAR_REPORTER_H -#include "hisysevent.h" +#include "hisysevent_c.h" +#include +#include "visibility.h" namespace OHOS::ObjectStore { enum BizScene { CREATE = 1, SAVE = 2, + DATA_RESTORE = 3, }; enum CreateStage { INIT_STORE = 1, @@ -33,6 +36,12 @@ enum SaveStage { SAVE_TO_SERVICE = 1, SAVE_TO_STORE = 2, PUSH_ASSETS = 3, + SYNC_DATA = 4, +}; +enum DataRestoreStage { + DATA_RECV = 1, + ASSETS_RECV = 2, + NOTIFY = 3, }; enum StageRes { IDLE = 0, @@ -55,18 +64,21 @@ enum ErrorCode { GETKV_FAILED = OFFSET + 6, DB_NOT_INIT = OFFSET + 7, }; -static constexpr char DOMAIN[] = "DISTDATAMGR"; -const std::string EVENT_NAME = "DISTRIBUTED_DATA_OBJECT_BEHAVIOR"; -static constexpr HiviewDFX::HiSysEvent::EventType TYPE = HiviewDFX::HiSysEvent::EventType::BEHAVIOR; -const std::string ORG_PKG = "distributeddata"; -const std::string ERROR_CODE = "ERROR_CODE"; -const std::string BIZ_STATE = "BIZ_STATE"; +constexpr char DOMAIN[] = "DISTDATAMGR"; +constexpr char EVENT_NAME[] = "DISTRIBUTED_DATA_OBJECT_BEHAVIOR"; +constexpr char ORG_PKG[] = "distributeddata"; -#define RADAR_REPORT(bizScene, bizStage, stageRes, ...) \ -({ \ - HiSysEventWrite(ObjectStore::DOMAIN, ObjectStore::EVENT_NAME, ObjectStore::TYPE, \ - "ORG_PKG", ObjectStore::ORG_PKG, "FUNC", __FUNCTION__, \ - "BIZ_SCENE", bizScene, "BIZ_STAGE", bizStage, "STAGE_RES", stageRes, ##__VA_ARGS__); \ -}) +class API_EXPORT RadarReporter { +public: + static void ReportStateStart(std::string func, int32_t scene, int32_t stage, int32_t stageRes, + int32_t state, std::string appCaller); + static void ReportStateFinished(std::string func, int32_t scene, int32_t stage, + int32_t stageRes, int32_t state); + static void ReportStateError(std::string func, int32_t scene, int32_t stage, int32_t stageRes, + int32_t errCode, int32_t state); + static void ReportStage(std::string func, int32_t scene, int32_t stage, int32_t stageRes); + static void ReportStageError(std::string func, int32_t scene, int32_t stage, + int32_t stageRes, int32_t errCode); +}; } // namespace OHOS::ObjectStore #endif // OBJECT_RADAR_REPORTER_H diff --git a/data_object/frameworks/innerkitsimpl/include/communicator/softbus_adapter.h b/data_object/frameworks/innerkitsimpl/include/communicator/softbus_adapter.h index 748697069f67a6c88820045a8f8aaa3876e1fe0f..bb3961e5e5b5abae9bde64b2ce9f79560b582603 100644 --- a/data_object/frameworks/innerkitsimpl/include/communicator/softbus_adapter.h +++ b/data_object/frameworks/innerkitsimpl/include/communicator/softbus_adapter.h @@ -67,7 +67,7 @@ public: int RemoveSessionServerAdapter(const std::string &sessionName) const; - void UpdateRelationship(const std::string &networkid, const DeviceChangeType &type); + void UpdateRelationship(const std::string &networkId, const DeviceChangeType &type); void NotifyDataListeners(const uint8_t *ptr, const int size, const std::string &deviceId, const PipeInfo &pipeInfo); diff --git a/data_object/frameworks/innerkitsimpl/src/adaptor/distributed_object_impl.cpp b/data_object/frameworks/innerkitsimpl/src/adaptor/distributed_object_impl.cpp index 17b7c15be97d405a39e3eed9f69f218b3c79d220..9bc4246e50965b644f168bbb35c31af78147c014 100644 --- a/data_object/frameworks/innerkitsimpl/src/adaptor/distributed_object_impl.cpp +++ b/data_object/frameworks/innerkitsimpl/src/adaptor/distributed_object_impl.cpp @@ -91,7 +91,6 @@ uint32_t DistributedObjectImpl::GetComplex(const std::string &key, std::vectorSave(sessionId_, deviceId); if (status != SUCCESS) { LOG_ERROR("DistributedObjectImpl:Save failed. status = %{public}d", status); diff --git a/data_object/frameworks/innerkitsimpl/src/adaptor/distributed_object_store_impl.cpp b/data_object/frameworks/innerkitsimpl/src/adaptor/distributed_object_store_impl.cpp index 8abff6e4abd586b8a439b631621931a1b5bcabf4..5904e83124874f7c3592537e8a89bded4c034a40 100644 --- a/data_object/frameworks/innerkitsimpl/src/adaptor/distributed_object_store_impl.cpp +++ b/data_object/frameworks/innerkitsimpl/src/adaptor/distributed_object_store_impl.cpp @@ -257,17 +257,18 @@ void WatcherProxy::SetAssetChangeCallBack(const AssetChangeCallback &assetChange DistributedObjectStore *DistributedObjectStore::GetInstance(const std::string &bundleName) { - RADAR_REPORT(CREATE, INIT_STORE, IDLE, BIZ_STATE, START); static std::mutex instLock_; static DistributedObjectStore *instPtr = nullptr; if (instPtr == nullptr) { std::lock_guard lock(instLock_); if (instPtr == nullptr && !bundleName.empty()) { + RadarReporter::ReportStateStart(std::string(__FUNCTION__), CREATE, INIT_STORE, IDLE, START, bundleName); LOG_INFO("new objectstore %{public}s", bundleName.c_str()); FlatObjectStore *flatObjectStore = new (std::nothrow) FlatObjectStore(bundleName); if (flatObjectStore == nullptr) { LOG_ERROR("no memory for FlatObjectStore malloc!"); - RADAR_REPORT(CREATE, INIT_STORE, RADAR_FAILED, ERROR_CODE, NO_MEMORY, BIZ_STATE, FINISHED); + RadarReporter::ReportStateError(std::string(__FUNCTION__), CREATE, INIT_STORE, + RADAR_FAILED, NO_MEMORY, FINISHED); return nullptr; } // Use instMemory to make sure this singleton not free before other object. @@ -276,12 +277,13 @@ DistributedObjectStore *DistributedObjectStore::GetInstance(const std::string &b if (instPtr == nullptr) { delete flatObjectStore; LOG_ERROR("no memory for DistributedObjectStoreImpl malloc!"); - RADAR_REPORT(CREATE, INIT_STORE, RADAR_FAILED, ERROR_CODE, NO_MEMORY, BIZ_STATE, FINISHED); + RadarReporter::ReportStateError(std::string(__FUNCTION__), CREATE, INIT_STORE, + RADAR_FAILED, NO_MEMORY, FINISHED); return nullptr; } + RadarReporter::ReportStage(std::string(__FUNCTION__), CREATE, INIT_STORE, RADAR_SUCCESS); } } - RADAR_REPORT(CREATE, INIT_STORE, RADAR_SUCCESS); return instPtr; } diff --git a/data_object/frameworks/innerkitsimpl/src/adaptor/flat_object_storage_engine.cpp b/data_object/frameworks/innerkitsimpl/src/adaptor/flat_object_storage_engine.cpp index 77fdee13fa7912085bff869bdd6b5742a22b9fe8..8f51a161bc26e905b643375a165de85a9480e2f6 100644 --- a/data_object/frameworks/innerkitsimpl/src/adaptor/flat_object_storage_engine.cpp +++ b/data_object/frameworks/innerkitsimpl/src/adaptor/flat_object_storage_engine.cpp @@ -14,6 +14,8 @@ */ #include "flat_object_storage_engine.h" +#include "accesstoken_kit.h" +#include "ipc_skeleton.h" #include "logger.h" #include "objectstore_errors.h" #include "process_communicator_impl.h" @@ -39,18 +41,21 @@ uint32_t FlatObjectStorageEngine::Open(const std::string &bundleName) LOG_INFO("FlatObjectDatabase: No need to reopen it"); return SUCCESS; } - auto status = DistributedDB::KvStoreDelegateManager::SetProcessLabel("objectstoreDB", bundleName); - if (status != DistributedDB::DBStatus::OK) { - LOG_ERROR("delegate SetProcessLabel failed: %{public}d.", static_cast(status)); - } - - auto communicator = std::make_shared(); - auto commStatus = DistributedDB::KvStoreDelegateManager::SetProcessCommunicator(communicator); - if (commStatus != DistributedDB::DBStatus::OK) { - LOG_ERROR("set distributed db communicator failed."); + auto tokenId = IPCSkeleton::GetSelfTokenID(); + int32_t ret = Security::AccessToken::AccessTokenKit::VerifyAccessToken(tokenId, DISTRIBUTED_DATASYNC); + LOG_INFO("bundleName:%{public}s, permission :%{public}d", bundleName.c_str(), ret); + if (ret == Security::AccessToken::PermissionState::PERMISSION_GRANTED) { + auto status = DistributedDB::KvStoreDelegateManager::SetProcessLabel("objectstoreDB", bundleName); + if (status != DistributedDB::DBStatus::OK) { + LOG_ERROR("delegate SetProcessLabel failed: %{public}d.", static_cast(status)); + } + status = DistributedDB::KvStoreDelegateManager::SetProcessCommunicator( + std::make_shared()); + if (status != DistributedDB::DBStatus::OK) { + LOG_ERROR("set distributed db communicator failed: %{public}d.", static_cast(status)); + } } storeManager_ = std::make_shared(bundleName, "default"); - DistributedDB::KvStoreConfig config; config.dataDir = "/data/log"; storeManager_->SetKvStoreConfig(config); @@ -85,16 +90,18 @@ void FlatObjectStorageEngine::OnComplete(const std::string &key, uint32_t FlatObjectStorageEngine::CreateTable(const std::string &key) { - RADAR_REPORT(CREATE, CREATE_TABLE, IDLE); + RadarReporter::ReportStage(std::string(__FUNCTION__), CREATE, CREATE_TABLE, IDLE); if (!isOpened_) { - RADAR_REPORT(CREATE, CREATE_TABLE, RADAR_FAILED, ERROR_CODE, DB_NOT_INIT, BIZ_STATE, FINISHED); + RadarReporter::ReportStateError(std::string(__FUNCTION__), CREATE, CREATE_TABLE, + RADAR_FAILED, DB_NOT_INIT, FINISHED); return ERR_DB_NOT_INIT; } { std::lock_guard lock(operationMutex_); if (delegates_.count(key) != 0) { LOG_ERROR("FlatObjectStorageEngine::CreateTable %{public}s already created", key.c_str()); - RADAR_REPORT(CREATE, CREATE_TABLE, RADAR_FAILED, ERROR_CODE, DUPLICATE_CREATE, BIZ_STATE, FINISHED); + RadarReporter::ReportStateError(std::string(__FUNCTION__), CREATE, CREATE_TABLE, RADAR_FAILED, + DUPLICATE_CREATE, FINISHED); return ERR_EXIST; } } @@ -110,7 +117,8 @@ uint32_t FlatObjectStorageEngine::CreateTable(const std::string &key) }); if (status != DistributedDB::DBStatus::OK || kvStore == nullptr) { LOG_ERROR("FlatObjectStorageEngine::CreateTable %{public}s getkvstore fail[%{public}d]", key.c_str(), status); - RADAR_REPORT(CREATE, CREATE_TABLE, RADAR_FAILED, ERROR_CODE, status, BIZ_STATE, FINISHED); + RadarReporter::ReportStateError(std::string(__FUNCTION__), CREATE, CREATE_TABLE, + RADAR_FAILED, status, FINISHED); return ERR_DB_GETKV_FAIL; } bool autoSync = true; @@ -119,7 +127,8 @@ uint32_t FlatObjectStorageEngine::CreateTable(const std::string &key) status = kvStore->Pragma(DistributedDB::AUTO_SYNC, data); if (status != DistributedDB::DBStatus::OK) { LOG_ERROR("FlatObjectStorageEngine::CreateTable %{public}s Pragma fail[%{public}d]", key.c_str(), status); - RADAR_REPORT(CREATE, CREATE_TABLE, RADAR_FAILED, ERROR_CODE, status, BIZ_STATE, FINISHED); + RadarReporter::ReportStateError(std::string(__FUNCTION__), CREATE, CREATE_TABLE, + RADAR_FAILED, status, FINISHED); return ERR_DB_GETKV_FAIL; } LOG_INFO("create table %{public}s success", key.c_str()); @@ -136,7 +145,7 @@ uint32_t FlatObjectStorageEngine::CreateTable(const std::string &key) deviceIds.push_back(item.deviceId); } SyncAllData(key, deviceIds, onComplete); - RADAR_REPORT(CREATE, CREATE_TABLE, RADAR_SUCCESS); + RadarReporter::ReportStateFinished(std::string(__FUNCTION__), CREATE, CREATE_TABLE, RADAR_SUCCESS, FINISHED); return SUCCESS; } diff --git a/data_object/frameworks/innerkitsimpl/src/adaptor/flat_object_store.cpp b/data_object/frameworks/innerkitsimpl/src/adaptor/flat_object_store.cpp index 7ac84b788d4ecf2c62b1cbb850867429b1bfcbd4..c7b109a391a8f53acc10c29f2fc2e42cdd95d373 100644 --- a/data_object/frameworks/innerkitsimpl/src/adaptor/flat_object_store.cpp +++ b/data_object/frameworks/innerkitsimpl/src/adaptor/flat_object_store.cpp @@ -60,8 +60,8 @@ uint32_t FlatObjectStore::CreateObject(const std::string &sessionId) LOG_ERROR("FlatObjectStore::CreateObject createTable err %{public}d", status); return status; } - ResumeObject(sessionId); SubscribeDataChange(sessionId); + ResumeObject(sessionId); return SUCCESS; } @@ -83,8 +83,8 @@ void FlatObjectStore::ResumeObject(const std::string &sessionId) std::lock_guard lck(mutex_); if (find(retrievedCache_.begin(), retrievedCache_.end(), sessionId) == retrievedCache_.end()) { retrievedCache_.push_back(sessionId); + storageEngine_->NotifyStatus(sessionId, "local", "restored"); } - storageEngine_->NotifyStatus(sessionId, "local", "restored"); } }; cacheManager_->ResumeObject(bundleName_, sessionId, callback); @@ -105,7 +105,11 @@ void FlatObjectStore::SubscribeDataChange(const std::string &sessionId) storageEngine_->NotifyChange(sessionId, filteredData); } if (allReady) { - storageEngine_->NotifyStatus(sessionId, "local", "restored"); + std::lock_guard lck(mutex_); + if (find(retrievedCache_.begin(), retrievedCache_.end(), sessionId) == retrievedCache_.end()) { + retrievedCache_.push_back(sessionId); + storageEngine_->NotifyStatus(sessionId, "local", "restored"); + } } }; cacheManager_->SubscribeDataChange(bundleName_, sessionId, remoteResumeCallback); @@ -182,6 +186,7 @@ uint32_t FlatObjectStore::SetStatusNotifier(std::shared_ptr notif uint32_t FlatObjectStore::Save(const std::string &sessionId, const std::string &deviceId) { + RadarReporter::ReportStateStart(std::string(__FUNCTION__), SAVE, SAVE_TO_SERVICE, IDLE, START, bundleName_); if (cacheManager_ == nullptr) { LOG_ERROR("FlatObjectStore::cacheManager_ is null"); return ERR_NULL_PTR; @@ -190,7 +195,8 @@ uint32_t FlatObjectStore::Save(const std::string &sessionId, const std::string & uint32_t status = storageEngine_->GetItems(sessionId, objectData); if (status != SUCCESS) { LOG_ERROR("FlatObjectStore::GetItems fail"); - RADAR_REPORT(SAVE, SAVE_TO_SERVICE, RADAR_FAILED, ERROR_CODE, status, BIZ_STATE, FINISHED); + RadarReporter::ReportStateError(std::string(__FUNCTION__), SAVE, SAVE_TO_SERVICE, + RADAR_FAILED, status, FINISHED); return status; } return cacheManager_->Save(bundleName_, sessionId, deviceId, objectData); @@ -390,9 +396,6 @@ uint32_t CacheManager::Save(const std::string &bundleName, const std::string &se LOG_INFO("CacheManager::start wait"); auto [timeout, res] = block->GetValue(); LOG_INFO("CacheManager::end wait, timeout: %{public}d, result: %{public}d", timeout, res); - if (timeout) { - RADAR_REPORT(SAVE, SAVE_TO_SERVICE, RADAR_FAILED, ERROR_CODE, TIMEOUT, BIZ_STATE, FINISHED); - } return res; } @@ -421,25 +424,26 @@ int32_t CacheManager::SaveObject(const std::string &bundleName, const std::strin sptr proxy = ClientAdaptor::GetObjectService(); if (proxy == nullptr) { LOG_ERROR("proxy is nullptr."); - RADAR_REPORT(SAVE, SAVE_TO_SERVICE, RADAR_FAILED, ERROR_CODE, SA_DIED, BIZ_STATE, FINISHED); + RadarReporter::ReportStateError(std::string(__FUNCTION__), SAVE, SAVE_TO_SERVICE, + RADAR_FAILED, SA_DIED, FINISHED); return ERR_PROCESSING; } sptr objectSaveCallback = new (std::nothrow) ObjectSaveCallback(callback); if (objectSaveCallback == nullptr) { LOG_ERROR("CacheManager::SaveObject no memory for ObjectSaveCallback malloc!"); - RADAR_REPORT(SAVE, SAVE_TO_SERVICE, RADAR_FAILED, ERROR_CODE, NO_MEMORY, BIZ_STATE, FINISHED); + RadarReporter::ReportStateError(std::string(__FUNCTION__), SAVE, SAVE_TO_SERVICE, + RADAR_FAILED, NO_MEMORY, FINISHED); return ERR_NULL_PTR; } int32_t status = proxy->ObjectStoreSave( bundleName, sessionId, deviceId, objectData, objectSaveCallback->AsObject().GetRefPtr()); if (status != SUCCESS) { LOG_ERROR("object save failed code=%d.", static_cast(status)); - if (status == ERR_IPC) { - RADAR_REPORT(SAVE, SAVE_TO_SERVICE, RADAR_FAILED, ERROR_CODE, IPC_ERROR, BIZ_STATE, FINISHED); - } + RadarReporter::ReportStateError(std::string(__FUNCTION__), SAVE, SAVE_TO_SERVICE, + RADAR_FAILED, IPC_ERROR, FINISHED); + } else { + RadarReporter::ReportStage(std::string(__FUNCTION__), SAVE, SAVE_TO_SERVICE, RADAR_SUCCESS); } - LOG_INFO("object save successful"); - RADAR_REPORT(SAVE, SAVE_TO_SERVICE, RADAR_SUCCESS); return status; } @@ -469,24 +473,20 @@ int32_t CacheManager::RevokeSaveObject( int32_t CacheManager::ResumeObject(const std::string &bundleName, const std::string &sessionId, std::function> &data, bool allReady)> &callback) { - RADAR_REPORT(CREATE, RESTORE, IDLE); sptr proxy = ClientAdaptor::GetObjectService(); if (proxy == nullptr) { LOG_ERROR("proxy is nullptr."); - RADAR_REPORT(CREATE, RESTORE, RADAR_FAILED, ERROR_CODE, SA_DIED, BIZ_STATE, FINISHED); return ERR_NULL_PTR; } sptr objectRetrieveCallback = new (std::nothrow) ObjectRetrieveCallback(callback); if (objectRetrieveCallback == nullptr) { LOG_ERROR("CacheManager::ResumeObject no memory for ObjectRetrieveCallback malloc!"); - RADAR_REPORT(CREATE, RESTORE, RADAR_FAILED, ERROR_CODE, NO_MEMORY, BIZ_STATE, FINISHED); return ERR_NULL_PTR; } int32_t status = proxy->ObjectStoreRetrieve( bundleName, sessionId, objectRetrieveCallback->AsObject().GetRefPtr()); if (status != SUCCESS) { LOG_ERROR("object resume failed code=%d.", static_cast(status)); - RADAR_REPORT(CREATE, RESTORE, RADAR_FAILED, ERROR_CODE, IPC_ERROR, BIZ_STATE, FINISHED); } LOG_INFO("object resume successful"); return status; diff --git a/data_object/frameworks/innerkitsimpl/src/communicator/softbus_adapter_standard.cpp b/data_object/frameworks/innerkitsimpl/src/communicator/softbus_adapter_standard.cpp index 1b2f7aef0216cc57cec6fa4e604c10a08b7aefc1..92f8339696196f3bbcadf6c19d4173d88c7c1ed3 100644 --- a/data_object/frameworks/innerkitsimpl/src/communicator/softbus_adapter_standard.cpp +++ b/data_object/frameworks/innerkitsimpl/src/communicator/softbus_adapter_standard.cpp @@ -245,20 +245,20 @@ std::vector SoftBusAdapter::GetRemoteNodesBasicInfo() const return dis; } -void SoftBusAdapter::UpdateRelationship(const std::string &networkid, const DeviceChangeType &type) +void SoftBusAdapter::UpdateRelationship(const std::string &networkId, const DeviceChangeType &type) { - auto uuid = DevManager::GetInstance()->GetUuidByNodeId(networkid); + auto uuid = DevManager::GetInstance()->GetUuidByNodeId(networkId); lock_guard lock(networkMutex_); switch (type) { case DeviceChangeType::DEVICE_OFFLINE: { - auto size = this->networkId2Uuid_.erase(networkid); + auto size = this->networkId2Uuid_.erase(networkId); if (size == 0) { - LOG_WARN("not found id:%{public}s.", networkid.c_str()); + LOG_WARN("not found id:%{public}s.", Anonymous::Change(networkId).c_str()); } break; } case DeviceChangeType::DEVICE_ONLINE: { - std::pair value = { networkid, uuid }; + std::pair value = { networkId, uuid }; auto res = this->networkId2Uuid_.insert(std::move(value)); if (!res.second) { LOG_WARN("insert failed."); diff --git a/data_object/frameworks/innerkitsimpl/src/object_radar_reporter.cpp b/data_object/frameworks/innerkitsimpl/src/object_radar_reporter.cpp new file mode 100644 index 0000000000000000000000000000000000000000..5d6db6247f070002cbc53bd4280f43489aea2b0d --- /dev/null +++ b/data_object/frameworks/innerkitsimpl/src/object_radar_reporter.cpp @@ -0,0 +1,211 @@ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "object_radar_reporter.h" + +namespace OHOS::ObjectStore { + using namespace ObjectStore; +void RadarReporter::ReportStateFinished(std::string func, int32_t scene, int32_t stage, int32_t stageRes, int32_t state) +{ + struct HiSysEventParam params[] = { + { .name = { "ORG_PKG" }, + .t = HISYSEVENT_STRING, + .v = { .s = const_cast(ORG_PKG) }, + .arraySize = 0 }, + { .name = { "FUNC" }, + .t = HISYSEVENT_STRING, + .v = { .s = const_cast(func.c_str()) }, + .arraySize = 0 }, + { .name = { "BIZ_SCENE" }, + .t = HISYSEVENT_INT32, + .v = { .i32 = scene }, + .arraySize = 0 }, + { .name = { "BIZ_STAGE" }, + .t = HISYSEVENT_INT32, + .v = { .i32 = stage }, + .arraySize = 0 }, + { .name = { "STAGE_RES" }, + .t = HISYSEVENT_INT32, + .v = { .i32 = stageRes }, + .arraySize = 0 }, + { .name = { "BIZ_STATE" }, + .t = HISYSEVENT_INT32, + .v = { .i32 = state }, + .arraySize = 0 } + }; + OH_HiSysEvent_Write( + DOMAIN, + EVENT_NAME, + HISYSEVENT_BEHAVIOR, + params, + sizeof(params) / sizeof(params[0]) + ); +} + +void RadarReporter::ReportStage(std::string func, int32_t scene, int32_t stage, int32_t stageRes) +{ + struct HiSysEventParam params[] = { + { .name = { "ORG_PKG" }, + .t = HISYSEVENT_STRING, + .v = { .s = const_cast(ORG_PKG) }, + .arraySize = 0 }, + { .name = { "FUNC" }, + .t = HISYSEVENT_STRING, + .v = { .s = const_cast(func.c_str()) }, + .arraySize = 0 }, + { .name = { "BIZ_SCENE" }, + .t = HISYSEVENT_INT32, + .v = { .i32 = scene }, + .arraySize = 0 }, + { .name = { "BIZ_STAGE" }, + .t = HISYSEVENT_INT32, + .v = { .i32 = stage }, + .arraySize = 0 }, + { .name = { "STAGE_RES" }, + .t = HISYSEVENT_INT32, + .v = { .i32 = stageRes }, + .arraySize = 0 }, + }; + OH_HiSysEvent_Write( + DOMAIN, + EVENT_NAME, + HISYSEVENT_BEHAVIOR, + params, + sizeof(params) / sizeof(params[0]) + ); +} + +void RadarReporter::ReportStateStart(std::string func, int32_t scene, int32_t stage, int32_t stageRes, + int32_t state, std::string appCaller) +{ + struct HiSysEventParam params[] = { + { .name = { "ORG_PKG" }, + .t = HISYSEVENT_STRING, + .v = { .s = const_cast(ORG_PKG) }, + .arraySize = 0 }, + { .name = { "FUNC" }, + .t = HISYSEVENT_STRING, + .v = { .s = const_cast(func.c_str()) }, + .arraySize = 0 }, + { .name = { "BIZ_SCENE" }, + .t = HISYSEVENT_INT32, + .v = { .i32 = scene }, + .arraySize = 0 }, + { .name = { "BIZ_STAGE" }, + .t = HISYSEVENT_INT32, + .v = { .i32 = stage }, + .arraySize = 0 }, + { .name = { "STAGE_RES" }, + .t = HISYSEVENT_INT32, + .v = { .i32 = stageRes }, + .arraySize = 0 }, + { .name = { "BIZ_STATE" }, + .t = HISYSEVENT_INT32, + .v = { .i32 = state }, + .arraySize = 0 }, + { .name = { "APP_CALLER" }, + .t = HISYSEVENT_INT32, + .v = { .s = const_cast(appCaller.c_str()) }, + .arraySize = 0 }, + }; + OH_HiSysEvent_Write( + DOMAIN, + EVENT_NAME, + HISYSEVENT_BEHAVIOR, + params, + sizeof(params) / sizeof(params[0]) + ); +} + +void RadarReporter::ReportStateError(std::string func, int32_t scene, int32_t stage, int32_t stageRes, + int32_t errCode, int32_t state) +{ + struct HiSysEventParam params[] = { + { .name = { "ORG_PKG" }, + .t = HISYSEVENT_STRING, + .v = { .s = const_cast(ORG_PKG) }, + .arraySize = 0 }, + { .name = { "FUNC" }, + .t = HISYSEVENT_STRING, + .v = { .s = const_cast(func.c_str()) }, + .arraySize = 0 }, + { .name = { "BIZ_SCENE" }, + .t = HISYSEVENT_INT32, + .v = { .i32 = scene }, + .arraySize = 0 }, + { .name = { "BIZ_STAGE" }, + .t = HISYSEVENT_INT32, + .v = { .i32 = stage }, + .arraySize = 0 }, + { .name = { "STAGE_RES" }, + .t = HISYSEVENT_INT32, + .v = { .i32 = stageRes }, + .arraySize = 0 }, + { .name = { "ERROR_CODE" }, + .t = HISYSEVENT_INT32, + .v = { .i32 = errCode }, + .arraySize = 0 }, + { .name = { "BIZ_STATE" }, + .t = HISYSEVENT_INT32, + .v = { .i32 = state }, + .arraySize = 0 }, + }; + OH_HiSysEvent_Write( + DOMAIN, + EVENT_NAME, + HISYSEVENT_BEHAVIOR, + params, + sizeof(params) / sizeof(params[0]) + ); +} + +void RadarReporter::ReportStageError(std::string func, int32_t scene, int32_t stage, + int32_t stageRes, int32_t errCode) +{ + struct HiSysEventParam params[] = { + { .name = { "ORG_PKG" }, + .t = HISYSEVENT_STRING, + .v = { .s = const_cast(ORG_PKG) }, + .arraySize = 0 }, + { .name = { "FUNC" }, + .t = HISYSEVENT_STRING, + .v = { .s = const_cast(func.c_str()) }, + .arraySize = 0 }, + { .name = { "BIZ_SCENE" }, + .t = HISYSEVENT_INT32, + .v = { .i32 = scene }, + .arraySize = 0 }, + { .name = { "BIZ_STAGE" }, + .t = HISYSEVENT_INT32, + .v = { .i32 = stage }, + .arraySize = 0 }, + { .name = { "STAGE_RES" }, + .t = HISYSEVENT_INT32, + .v = { .i32 = stageRes }, + .arraySize = 0 }, + { .name = { "ERROR_CODE" }, + .t = HISYSEVENT_INT32, + .v = { .i32 = errCode }, + .arraySize = 0 }, + }; + OH_HiSysEvent_Write( + DOMAIN, + EVENT_NAME, + HISYSEVENT_BEHAVIOR, + params, + sizeof(params) / sizeof(params[0]) + ); +} +} diff --git a/data_object/frameworks/innerkitsimpl/test/fuzztest/objectstore_fuzzer/BUILD.gn b/data_object/frameworks/innerkitsimpl/test/fuzztest/objectstore_fuzzer/BUILD.gn index 8a8cd1bce93b3a950bbaaadb49317f97a2d53ab0..42477193be9047c17123d2975bc6a951aa3257af 100644 --- a/data_object/frameworks/innerkitsimpl/test/fuzztest/objectstore_fuzzer/BUILD.gn +++ b/data_object/frameworks/innerkitsimpl/test/fuzztest/objectstore_fuzzer/BUILD.gn @@ -22,7 +22,6 @@ config("module_private_config") { "../../../../../frameworks/innerkitsimpl/include/adaptor", "../../../../../frameworks/innerkitsimpl/include/common", "${data_object_base_path}/frameworks/innerkitsimpl/include", - "${relational_store_path}/interfaces/inner_api/common_type/include", ] } diff --git a/data_object/frameworks/jskitsimpl/include/adaptor/js_object_wrapper.h b/data_object/frameworks/jskitsimpl/include/adaptor/js_object_wrapper.h index ffb68c40f8cc41b74273fb75fd38e7ffd89ce8ce..0f8ea760c8d82748d4df8fab04d97ba4f61ee7d4 100644 --- a/data_object/frameworks/jskitsimpl/include/adaptor/js_object_wrapper.h +++ b/data_object/frameworks/jskitsimpl/include/adaptor/js_object_wrapper.h @@ -30,9 +30,9 @@ public: DistributedObject *GetObject(); bool AddWatch(napi_env env, const char *type, napi_value handler); void DeleteWatch(napi_env env, const char *type, napi_value handler = nullptr); - bool isUndefined(char *value); - void AddUndefined(char *value); - void DeleteUndefined(char *value); + bool IsUndefined(const char *value); + void AddUndefined(const char *value); + void DeleteUndefined(const char *value); void DestroyObject(); void SetObjectId(const std::string &objectId); std::string GetObjectId(); diff --git a/data_object/frameworks/jskitsimpl/include/common/uv_queue.h b/data_object/frameworks/jskitsimpl/include/common/uv_queue.h index 3c90ddb502fcfeecc158ce95f616655ee0dc382a..d7fe19a6c614fbad370459321a402113b898e4d4 100644 --- a/data_object/frameworks/jskitsimpl/include/common/uv_queue.h +++ b/data_object/frameworks/jskitsimpl/include/common/uv_queue.h @@ -17,8 +17,8 @@ #include #include #include -#include #include +#include #include "napi/native_api.h" #include "napi/native_node_api.h" #include "uv.h" diff --git a/data_object/frameworks/jskitsimpl/src/adaptor/js_distributedobject.cpp b/data_object/frameworks/jskitsimpl/src/adaptor/js_distributedobject.cpp index a603ac31c1cb0aa9c5b2b41506bcc875c8c7c185..c932c2fc3e7bb270aab22e886bc46f4233622121 100644 --- a/data_object/frameworks/jskitsimpl/src/adaptor/js_distributedobject.cpp +++ b/data_object/frameworks/jskitsimpl/src/adaptor/js_distributedobject.cpp @@ -58,7 +58,7 @@ napi_value JSDistributedObject::JSGet(napi_env env, napi_callback_info info) status = napi_unwrap(env, thisVar, (void **)&wrapper); NOT_MATCH_RETURN_NULL(status == napi_ok && wrapper != nullptr && wrapper->GetObject() != nullptr); napi_value result = nullptr; - if (wrapper->isUndefined(key)) { + if (wrapper->IsUndefined(key)) { napi_get_undefined(env, &result); return result; } diff --git a/data_object/frameworks/jskitsimpl/src/adaptor/js_distributedobjectstore.cpp b/data_object/frameworks/jskitsimpl/src/adaptor/js_distributedobjectstore.cpp index 6af72368f815d5eeace6a1351d22a6279c61201d..f18d2787d1415d1aaa0c405482cca5570a533b3e 100644 --- a/data_object/frameworks/jskitsimpl/src/adaptor/js_distributedobjectstore.cpp +++ b/data_object/frameworks/jskitsimpl/src/adaptor/js_distributedobjectstore.cpp @@ -20,6 +20,7 @@ #include "ability_context.h" #include "accesstoken_kit.h" +#include "anonymous.h" #include "application_context.h" #include "distributed_objectstore.h" #include "js_ability.h" diff --git a/data_object/frameworks/jskitsimpl/src/adaptor/js_object_wrapper.cpp b/data_object/frameworks/jskitsimpl/src/adaptor/js_object_wrapper.cpp index aa2be5ba745cf631a38c7a230990b411d966ed29..5f3436b67b6f054d2dd2a37424d532a024b0bd2e 100644 --- a/data_object/frameworks/jskitsimpl/src/adaptor/js_object_wrapper.cpp +++ b/data_object/frameworks/jskitsimpl/src/adaptor/js_object_wrapper.cpp @@ -65,7 +65,7 @@ void JSObjectWrapper::DeleteWatch(napi_env env, const char *type, napi_value han } } -bool JSObjectWrapper::isUndefined(char *value) +bool JSObjectWrapper::IsUndefined(const char *value) { std::string tmpStr = value; auto it = std::find(undefinedProperties.begin(), undefinedProperties.end(), tmpStr); @@ -75,7 +75,7 @@ bool JSObjectWrapper::isUndefined(char *value) return true; } -void JSObjectWrapper::AddUndefined(char *value) +void JSObjectWrapper::AddUndefined(const char *value) { std::string tmpStr = value; if (std::find(undefinedProperties.begin(), undefinedProperties.end(), tmpStr) == undefinedProperties.end()) { @@ -83,7 +83,7 @@ void JSObjectWrapper::AddUndefined(char *value) } } -void JSObjectWrapper::DeleteUndefined(char *value) +void JSObjectWrapper::DeleteUndefined(const char *value) { std::string tmpStr = value; auto it = std::find(undefinedProperties.begin(), undefinedProperties.end(), tmpStr); diff --git a/data_object/interfaces/innerkits/BUILD.gn b/data_object/interfaces/innerkits/BUILD.gn index f5b8ab1bd0ad4e192ea013185f7f602a009dff01..5c76f81ece1a439a3589e5add5aa0f4f136a3aff 100644 --- a/data_object/interfaces/innerkits/BUILD.gn +++ b/data_object/interfaces/innerkits/BUILD.gn @@ -23,7 +23,6 @@ config("objectstore_config") { "../../frameworks/innerkitsimpl/include/communicator", "../../frameworks/innerkitsimpl/include", "../../interfaces/innerkits", - "${relational_store_path}/interfaces/inner_api/common_type/include", ] ldflags = [ "-Wl,--exclude-libs,ALL" ] @@ -53,11 +52,13 @@ object_source_config = [ "../../frameworks/innerkitsimpl/src/communicator/process_communicator_impl.cpp", "../../frameworks/innerkitsimpl/src/communicator/softbus_adapter_standard.cpp", "../../frameworks/innerkitsimpl/src/object_callback_stub.cpp", + "../../frameworks/innerkitsimpl/src/object_radar_reporter.cpp", "../../frameworks/innerkitsimpl/src/object_service_proxy.cpp", "../../frameworks/innerkitsimpl/src/object_types_util.cpp", ] object_deps_config = [] object_external_deps_config = [ + "access_token:libaccesstoken_sdk", "bounds_checking_function:libsec_shared", "c_utils:utils", "device_manager:devicemanagersdk", diff --git a/data_object/interfaces/jskits/BUILD.gn b/data_object/interfaces/jskits/BUILD.gn index 64fdcd1844e7aee6a05398627612eab3a9364d62..7b4c7aafa384fd3f8090d418652ef6456ec39c00 100644 --- a/data_object/interfaces/jskits/BUILD.gn +++ b/data_object/interfaces/jskits/BUILD.gn @@ -11,7 +11,7 @@ # See the License for the specific language governing permissions and # limitations under the License. -import("//arkcompiler/ets_frontend/es2panda/es2abc_config.gni") +import("//build/config/components/ets_frontend/es2abc_config.gni") import("//build/ohos.gni") import("//build/ohos/ace/ace.gni") import("//foundation/distributeddatamgr/data_object/data_object.gni") @@ -42,7 +42,6 @@ config("objectstore_config") { "../../frameworks/innerkitsimpl/include", "../../frameworks/innerkitsimpl/include/communicator", "../../interfaces/innerkits", - "${relational_store_path}/interfaces/inner_api/common_type/include", ] } diff --git a/data_object/interfaces/jskits/distributed_data_object.js b/data_object/interfaces/jskits/distributed_data_object.js index a7656331fba01eded0c39d3c27c9b7fd6c2e4141..2882265480f90f580bb74562ff1d67e2acf7d3d3 100644 --- a/data_object/interfaces/jskits/distributed_data_object.js +++ b/data_object/interfaces/jskits/distributed_data_object.js @@ -25,6 +25,8 @@ const ASSET_KEY_SEPARATOR = '.'; const JS_ERROR = 1; const SDK_VERSION_8 = 8; const SDK_VERSION_9 = 9; +const SESSION_ID_REGEX = /^\w+$/; +const SESSION_ID_MAX_LENGTH = 128; class Distributed { constructor(obj) { @@ -147,22 +149,18 @@ function getObjectValue(object, key) { } function setObjectValue(object, key, newValue) { - console.info('start set ' + key + ' ' + newValue); + console.info('start set ' + key); if (typeof newValue === 'object') { let value = COMPLEX_TYPE + JSON.stringify(newValue); object.put(key, value); - console.info('set ' + key + ' ' + value); } else if (typeof newValue === 'string') { let value = STRING_TYPE + newValue; object.put(key, value); - console.info('set ' + key + ' ' + value); } else if (newValue == null) { let value = NULL_TYPE; object.put(key, value); - console.info('set ' + key + ' ' + value); } else { object.put(key, newValue); - console.info('set ' + key + ' ' + newValue); } } @@ -179,8 +177,7 @@ function isAsset(obj) { return false; } for (const key of ASSET_KEYS.slice(1)) { - if (!Object.prototype.hasOwnProperty.call(obj, key) || - (typeof obj[key] !== 'string' && typeof obj[key] !== 'undefined')) { + if (!Object.prototype.hasOwnProperty.call(obj, key) || typeof obj[key] !== 'string') { return false; } } @@ -200,7 +197,7 @@ function defineAsset(object, key, data) { }); let asset = object[key]; Object.keys(data).forEach(subKey => { - if (data[subKey] !== undefined) { + if (data[subKey] !== '') { asset[subKey] = data[subKey]; } }); @@ -230,7 +227,7 @@ function setAssetValue(object, key, newValue) { message: 'cannot set ' + key + ' by non Asset type data' }; } - Object.values(newValue).forEach(subKey => { + Object.keys(newValue).forEach(subKey => { setObjectValue(object, key + ASSET_KEY_SEPARATOR + subKey, newValue[subKey]); }); } @@ -375,6 +372,12 @@ class DistributedV9 { } } leaveSession(this.__sdkVersion, this.__proxy); + if (sessionId.length > SESSION_ID_MAX_LENGTH || !SESSION_ID_REGEX.test(sessionId)) { + throw { + code: 401, + message: 'The sessionId allows only letters, digits, and underscores(_), and cannot exceed 128 in length.' + }; + } let object = joinSession(this.__sdkVersion, this.__proxy, this.__objectId, sessionId, this.__context); if (object != null) { this.__proxy = object; diff --git a/data_share/OAT.xml b/data_share/OAT.xml index 0e4aff54f26eb56df44cd206cbac3fb2a1e17023..0330ab10eb1bb7b729107c51ec6ccf38b0af81a9 100644 --- a/data_share/OAT.xml +++ b/data_share/OAT.xml @@ -52,15 +52,7 @@ - - - + diff --git a/data_share/frameworks/js/napi/common/include/datashare_predicates_proxy.h b/data_share/frameworks/js/napi/common/include/datashare_predicates_proxy.h index db22b37d8f9b46258acd19320cab6f8322520f54..be455506fae86ee6c363b547212769d46b14c465 100644 --- a/data_share/frameworks/js/napi/common/include/datashare_predicates_proxy.h +++ b/data_share/frameworks/js/napi/common/include/datashare_predicates_proxy.h @@ -72,6 +72,7 @@ private: static napi_value NotIn(napi_env env, napi_callback_info info); static napi_value PrefixKey(napi_env env, napi_callback_info info); static napi_value InKeys(napi_env env, napi_callback_info info); + static napi_value CreateConstructor(napi_env env); }; } // namespace DataShare } // namespace OHOS diff --git a/data_share/frameworks/js/napi/common/src/datashare_predicates_proxy.cpp b/data_share/frameworks/js/napi/common/src/datashare_predicates_proxy.cpp index ef9ccf25155626b1d417ebe9836f0111753678ee..1a68e8c597f93a11da44de9d5b9d42b4474b1e2e 100644 --- a/data_share/frameworks/js/napi/common/src/datashare_predicates_proxy.cpp +++ b/data_share/frameworks/js/napi/common/src/datashare_predicates_proxy.cpp @@ -15,6 +15,9 @@ #include "datashare_predicates_proxy.h" +#include +#include + #include "datashare_log.h" #include "datashare_js_utils.h" #include "datashare_predicates.h" @@ -30,6 +33,12 @@ napi_value DataSharePredicatesProxy::GetConstructor(napi_env env) NAPI_CALL(env, napi_get_reference_value(env, constructor_, &cons)); return cons; } + return CreateConstructor(env); +} + +napi_value DataSharePredicatesProxy::CreateConstructor(napi_env env) +{ + napi_value cons; napi_property_descriptor descriptors[] = { DECLARE_NAPI_FUNCTION("equalTo", EqualTo), DECLARE_NAPI_FUNCTION("notEqualTo", NotEqualTo), @@ -62,9 +71,17 @@ napi_value DataSharePredicatesProxy::GetConstructor(napi_env env) DECLARE_NAPI_FUNCTION("prefixKey", PrefixKey), DECLARE_NAPI_FUNCTION("inKeys", InKeys), }; + int64_t start = std::chrono::duration_cast( + std::chrono::system_clock::now().time_since_epoch()).count(); NAPI_CALL(env, napi_define_class(env, "DataSharePredicates", NAPI_AUTO_LENGTH, New, nullptr, sizeof(descriptors) / sizeof(napi_property_descriptor), descriptors, &cons)); + int64_t middle = std::chrono::duration_cast( + std::chrono::system_clock::now().time_since_epoch()).count(); NAPI_CALL(env, napi_create_reference(env, cons, 1, &constructor_)); + int64_t finish = std::chrono::duration_cast( + std::chrono::system_clock::now().time_since_epoch()).count(); + LOG_INFO("Init predicates create reference, cost time: %{public}" PRIi64 + "ms , cost time:%{public}" PRIi64 "ms", middle - start, finish - middle); return cons; } @@ -74,7 +91,12 @@ void DataSharePredicatesProxy::Init(napi_env env, napi_value exports) // cause use-after-free. constructor_ = nullptr; napi_value cons = GetConstructor(env); + int64_t start = std::chrono::duration_cast( + std::chrono::system_clock::now().time_since_epoch()).count(); NAPI_CALL_RETURN_VOID(env, napi_set_named_property(env, exports, "DataSharePredicates", cons)); + int64_t end = std::chrono::duration_cast( + std::chrono::system_clock::now().time_since_epoch()).count(); + LOG_INFO("Init predicates set named property, cost time:%{public}" PRIi64 "ms", end - start); } napi_value DataSharePredicatesProxy::New(napi_env env, napi_callback_info info) diff --git a/data_share/frameworks/js/napi/dataShare/src/async_call.cpp b/data_share/frameworks/js/napi/dataShare/src/async_call.cpp index a7e436802ac533ee856ae43e0070d02af335281e..b4e1bf9b6f461b326706cb47963915861327fc0a 100644 --- a/data_share/frameworks/js/napi/dataShare/src/async_call.cpp +++ b/data_share/frameworks/js/napi/dataShare/src/async_call.cpp @@ -19,8 +19,8 @@ #include "napi_common_data.h" namespace OHOS::DataShare { -AsyncCall::AsyncCall(napi_env env, napi_callback_info info, std::shared_ptr context) - : env_(env) +__attribute__((no_sanitize("undefined"))) AsyncCall::AsyncCall(napi_env env, napi_callback_info info, + std::shared_ptr context) : env_(env) { context_ = new AsyncContext(); size_t argc = ARGS_MAX_COUNT; diff --git a/data_share/frameworks/js/napi/dataShare/src/napi_datashare_helper.cpp b/data_share/frameworks/js/napi/dataShare/src/napi_datashare_helper.cpp index 11cf632c51a01d3de01e9cc49a41638c72d2629b..9e6c535795affb34b248a0414159134620ecb5be 100644 --- a/data_share/frameworks/js/napi/dataShare/src/napi_datashare_helper.cpp +++ b/data_share/frameworks/js/napi/dataShare/src/napi_datashare_helper.cpp @@ -16,6 +16,7 @@ #include "napi_datashare_helper.h" #include "data_proxy_observer_stub.h" +#include "datashare_errno.h" #include "datashare_helper.h" #include "datashare_log.h" #include "datashare_predicates_proxy.h" @@ -31,6 +32,7 @@ using namespace OHOS::AppExecFwk; namespace OHOS { namespace DataShare { static constexpr int MAX_ARGC = 6; +static __thread napi_ref constructor_ = nullptr; static bool GetSilentUri(napi_env env, napi_value jsValue, std::string &uri) { napi_valuetype valuetype = napi_undefined; @@ -141,6 +143,10 @@ napi_value NapiDataShareHelper::Napi_CreateDataShareHelper(napi_env env, napi_ca napi_value NapiDataShareHelper::GetConstructor(napi_env env) { napi_value cons = nullptr; + if (constructor_ != nullptr) { + napi_get_reference_value(env, constructor_, &cons); + return cons; + } napi_property_descriptor clzDes[] = { DECLARE_NAPI_FUNCTION("on", Napi_On), DECLARE_NAPI_FUNCTION("off", Napi_Off), @@ -161,6 +167,7 @@ napi_value NapiDataShareHelper::GetConstructor(napi_env env) }; NAPI_CALL(env, napi_define_class(env, "DataShareHelper", NAPI_AUTO_LENGTH, Initialize, nullptr, sizeof(clzDes) / sizeof(napi_property_descriptor), clzDes, &cons)); + napi_create_reference(env, cons, 1, &constructor_); return cons; } diff --git a/data_share/frameworks/js/napi/dataShare/src/native_datashare_predicates_module.cpp b/data_share/frameworks/js/napi/dataShare/src/native_datashare_predicates_module.cpp index 27c39ed8afc03b98e2782388a8781bef1a5bca20..399ce1766e057cadf856bf213aebeb5cf8997b5f 100644 --- a/data_share/frameworks/js/napi/dataShare/src/native_datashare_predicates_module.cpp +++ b/data_share/frameworks/js/napi/dataShare/src/native_datashare_predicates_module.cpp @@ -13,11 +13,10 @@ * limitations under the License. */ -#include "napi/native_api.h" -#include "napi/native_node_api.h" - #include "datashare_log.h" #include "datashare_predicates_proxy.h" +#include "napi/native_api.h" +#include "napi/native_node_api.h" namespace OHOS { namespace DataShare { diff --git a/data_share/frameworks/js/napi/datashare_ext_ability/BUILD.gn b/data_share/frameworks/js/napi/datashare_ext_ability/BUILD.gn index e7e8367d8e2b8a0ac2d261d197e35a1c2ac2b2ce..4c45fb80fcc97cf7e4d916d8ef3140458411137e 100644 --- a/data_share/frameworks/js/napi/datashare_ext_ability/BUILD.gn +++ b/data_share/frameworks/js/napi/datashare_ext_ability/BUILD.gn @@ -11,7 +11,7 @@ # See the License for the specific language governing permissions and # limitations under the License. -import("//arkcompiler/ets_frontend/es2panda/es2abc_config.gni") +import("//build/config/components/ets_frontend/es2abc_config.gni") import("//build/ohos.gni") es2abc_gen_abc("gen_datashare_ext_ability_abc") { diff --git a/data_share/frameworks/js/napi/datashare_ext_ability/datashare_ext_ability.js b/data_share/frameworks/js/napi/datashare_ext_ability/datashare_ext_ability.js index c58357dcac12cb269f68ee3c187c7fb9be9487c7..75f507f081017bc6a4064bdd64826fbb4b3280d4 100644 --- a/data_share/frameworks/js/napi/datashare_ext_ability/datashare_ext_ability.js +++ b/data_share/frameworks/js/napi/datashare_ext_ability/datashare_ext_ability.js @@ -16,6 +16,7 @@ class DataShareExtensionAbility { onCreate(want, callback) { console.log('onCreate, want:' + want.abilityName); + callback(undefined); } getFileTypes(uri, mimeTypeFilter, callback) { diff --git a/data_share/frameworks/js/napi/datashare_ext_ability_context/BUILD.gn b/data_share/frameworks/js/napi/datashare_ext_ability_context/BUILD.gn index cce58b4315c67c52dab02d880089c7d61a141e88..31b9ac7190e63e9924daefc3a43ab5b20cff4163 100644 --- a/data_share/frameworks/js/napi/datashare_ext_ability_context/BUILD.gn +++ b/data_share/frameworks/js/napi/datashare_ext_ability_context/BUILD.gn @@ -11,7 +11,7 @@ # See the License for the specific language governing permissions and # limitations under the License. -import("//arkcompiler/ets_frontend/es2panda/es2abc_config.gni") +import("//build/config/components/ets_frontend/es2abc_config.gni") import("//build/ohos.gni") es2abc_gen_abc("gen_datashare_ext_ability_context_abc") { diff --git a/data_share/frameworks/native/common/include/call_reporter.h b/data_share/frameworks/native/common/include/call_reporter.h new file mode 100644 index 0000000000000000000000000000000000000000..52b83e91c8285ffa09d36238939ed36ab70c76e3 --- /dev/null +++ b/data_share/frameworks/native/common/include/call_reporter.h @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef DATASHARE_CALL_REPORTER_H +#define DATASHARE_CALL_REPORTER_H + +#include +#include + +namespace OHOS { +namespace DataShare { +class DataShareCallReporter { +public: + DataShareCallReporter() = default; + struct CallInfo { + int count = 0; + std::chrono::system_clock::time_point firstTime; + }; + void Count(const std::string &funcName, const std::string &uri); +private: + ConcurrentMap callCounts; + static constexpr int RESET_COUNT_THRESHOLD = 100; + static constexpr std::chrono::milliseconds TIME_THRESHOLD = std::chrono::milliseconds(30000); +}; +} // namespace DataShare +} // namespace OHOS +#endif \ No newline at end of file diff --git a/data_share/frameworks/native/common/include/datashare_block_writer_impl.h b/data_share/frameworks/native/common/include/datashare_block_writer_impl.h index dbe2dea9e98a6b2b6785a84d1e7bde6ddfa75dec..be0b9bc7394d58e7e4f644f47c7416ac95dec2c8 100644 --- a/data_share/frameworks/native/common/include/datashare_block_writer_impl.h +++ b/data_share/frameworks/native/common/include/datashare_block_writer_impl.h @@ -76,7 +76,7 @@ public: /** * Get Block */ - AppDataFwk::SharedBlock *GetBlock() const; + std::shared_ptr GetBlock(); private: /** @@ -93,7 +93,7 @@ private: } private: - AppDataFwk::SharedBlock *shareBlock_; + std::shared_ptr shareBlock_; }; } // namespace DataShare } // namespace OHOS diff --git a/data_share/frameworks/native/common/include/datashare_log.h b/data_share/frameworks/native/common/include/datashare_log.h index 9b33a6e188eb51297256979c3c6ddd428cb564ce..24eb67c3d1f42fc3b3202707efe92bfafd55a3e8 100644 --- a/data_share/frameworks/native/common/include/datashare_log.h +++ b/data_share/frameworks/native/common/include/datashare_log.h @@ -16,6 +16,7 @@ #ifndef DATASHARE_LOG_PRINT_H #define DATASHARE_LOG_PRINT_H +#include #include "hilog/log.h" namespace OHOS::DataShare { @@ -25,15 +26,13 @@ static inline OHOS::HiviewDFX::HiLogLabel LogLabel() } } // namespace OHOS::DataShare -#define FILENAME (__builtin_strrchr(__FILE__, '/') ? __builtin_strrchr(__FILE__, '/') + 1 : __FILE__) - #define LOG_DEBUG(fmt, ...) \ do { \ auto lable = LogLabel(); \ if (HiLogIsLoggable(lable.domain, lable.tag, LogLevel::LOG_DEBUG)) { \ ((void)HILOG_IMPL(lable.type, LogLevel::LOG_DEBUG, lable.domain, lable.tag, \ "[%{public}s()-%{public}s:%{public}d]: " fmt, __FUNCTION__, \ - FILENAME, __LINE__, ##__VA_ARGS__)); \ + __FILE_NAME__, __LINE__, ##__VA_ARGS__)); \ } \ } while (0) @@ -43,7 +42,7 @@ static inline OHOS::HiviewDFX::HiLogLabel LogLabel() if (HiLogIsLoggable(lable.domain, lable.tag, LogLevel::LOG_INFO)) { \ ((void)HILOG_IMPL(lable.type, LogLevel::LOG_INFO, lable.domain, lable.tag, \ "[%{public}s()-%{public}s:%{public}d]: " fmt, __FUNCTION__, \ - FILENAME, __LINE__, ##__VA_ARGS__)); \ + __FILE_NAME__, __LINE__, ##__VA_ARGS__)); \ } \ } while (0) @@ -53,7 +52,7 @@ static inline OHOS::HiviewDFX::HiLogLabel LogLabel() if (HiLogIsLoggable(lable.domain, lable.tag, LogLevel::LOG_WARN)) { \ ((void)HILOG_IMPL(lable.type, LogLevel::LOG_WARN, lable.domain, lable.tag, \ "[%{public}s()-%{public}s:%{public}d]: " fmt, __FUNCTION__, \ - FILENAME, __LINE__, ##__VA_ARGS__)); \ + __FILE_NAME__, __LINE__, ##__VA_ARGS__)); \ } \ } while (0) @@ -63,7 +62,7 @@ static inline OHOS::HiviewDFX::HiLogLabel LogLabel() if (HiLogIsLoggable(lable.domain, lable.tag, LogLevel::LOG_ERROR)) { \ ((void)HILOG_IMPL(lable.type, LogLevel::LOG_ERROR, lable.domain, lable.tag, \ "[%{public}s()-%{public}s:%{public}d]: " fmt, __FUNCTION__, \ - FILENAME, __LINE__, ##__VA_ARGS__)); \ + __FILE_NAME__, __LINE__, ##__VA_ARGS__)); \ } \ } while (0) @@ -73,7 +72,7 @@ static inline OHOS::HiviewDFX::HiLogLabel LogLabel() if (HiLogIsLoggable(lable.domain, lable.tag, LogLevel::LOG_FATAL)) { \ ((void)HILOG_IMPL(lable.type, LogLevel::LOG_FATAL, lable.domain, lable.tag, \ "[%{public}s()-%{public}s:%{public}d]: " fmt, __FUNCTION__, \ - FILENAME, __LINE__, ##__VA_ARGS__)); \ + __FILE_NAME__, __LINE__, ##__VA_ARGS__)); \ } \ } while (0) diff --git a/data_share/frameworks/native/common/include/datashare_string_utils.h b/data_share/frameworks/native/common/include/datashare_string_utils.h index be6f7f9e843a54b5534bf4f3da0269fdd3e2cfdd..24b187e92731eefd90926e04730df80b56ebc1ce 100644 --- a/data_share/frameworks/native/common/include/datashare_string_utils.h +++ b/data_share/frameworks/native/common/include/datashare_string_utils.h @@ -30,6 +30,8 @@ public: static std::string Change(const std::string &name); + static int32_t GetRandomNumber(const int32_t min, const int32_t max); + private: DataShareStringUtils(); ~DataShareStringUtils(); diff --git a/data_share/frameworks/native/common/include/distributeddata_data_share_ipc_interface_code.h b/data_share/frameworks/native/common/include/distributeddata_data_share_ipc_interface_code.h index b91a91f9b6618e646654c386faf5f69fa3e3699d..a2189936a095ce97a52319907dfecbfcbbfc3e8a 100644 --- a/data_share/frameworks/native/common/include/distributeddata_data_share_ipc_interface_code.h +++ b/data_share/frameworks/native/common/include/distributeddata_data_share_ipc_interface_code.h @@ -38,6 +38,9 @@ enum class IDataShareInterfaceCode { CMD_EXECUTE_BATCH, CMD_INSERT_EXT, CMD_BATCH_UPDATE, + CMD_INSERT_EX, + CMD_UPDATE_EX, + CMD_DELETE_EX, }; enum class ISharedResultInterfaceCode { @@ -71,9 +74,6 @@ enum class ISharedResultInterfaceCode { }; enum class DataShareServiceInterfaceCode { - DATA_SHARE_SERVICE_CMD_INSERT, - DATA_SHARE_SERVICE_CMD_DELETE, - DATA_SHARE_SERVICE_CMD_UPDATE, DATA_SHARE_SERVICE_CMD_QUERY, DATA_SHARE_SERVICE_CMD_ADD_TEMPLATE, DATA_SHARE_SERVICE_CMD_DEL_TEMPLATE, @@ -93,6 +93,9 @@ enum class DataShareServiceInterfaceCode { DATA_SHARE_SERVICE_CMD_GET_SILENT_PROXY_STATUS, DATA_SHARE_SERVICE_CMD_REGISTER_OBSERVER, DATA_SHARE_SERVICE_CMD_UNREGISTER_OBSERVER, + DATA_SHARE_SERVICE_CMD_INSERTEX, + DATA_SHARE_SERVICE_CMD_DELETEEX, + DATA_SHARE_SERVICE_CMD_UPDATEEX, DATA_SHARE_SERVICE_CMD_MAX }; diff --git a/data_share/frameworks/native/common/include/idata_share_service.h b/data_share/frameworks/native/common/include/idata_share_service.h index a09d5ac92122a931a3f70fafb67d30f064fe0b98..538e1c0fcc2a0f1300b16d188c4263251c351bac 100644 --- a/data_share/frameworks/native/common/include/idata_share_service.h +++ b/data_share/frameworks/native/common/include/idata_share_service.h @@ -19,7 +19,7 @@ #include #include "iremote_broker.h" - +#include "datashare_errno.h" #include "data_proxy_observer.h" #include "datashare_business_error.h" #include "datashare_predicates.h" @@ -34,19 +34,16 @@ class IDataShareService : public IRemoteBroker { public: DECLARE_INTERFACE_DESCRIPTOR(u"OHOS.DataShare.IDataShareService"); - enum { - DATA_SHARE_ERROR = -1, - DATA_SHARE_OK = 0, - }; - - virtual int Insert(const Uri &uri, const DataShareValuesBucket &value) = 0; + virtual int Insert(const Uri &uri, const Uri &extUri, const DataShareValuesBucket &value) = 0; - virtual int Update(const Uri &uri, const DataSharePredicates &predicates, const DataShareValuesBucket &value) = 0; + virtual int Update(const Uri &uri, const Uri &extUri, const DataSharePredicates &predicates, + const DataShareValuesBucket &value) = 0; - virtual int Delete(const Uri &uri, const DataSharePredicates &predicates) = 0; + virtual int Delete(const Uri &uri, const Uri &extUri, const DataSharePredicates &predicates) = 0; - virtual std::shared_ptr Query(const Uri &uri, const DataSharePredicates &predicates, - std::vector &columns, DatashareBusinessError &businessError) = 0; + virtual std::shared_ptr Query(const Uri &uri, const Uri &extUri, + const DataSharePredicates &predicates, std::vector &columns, + DatashareBusinessError &businessError) = 0; virtual int AddQueryTemplate(const std::string &uri, int64_t subscriberId, Template &tpl) = 0; @@ -91,6 +88,15 @@ public: virtual int UnRegisterObserver(const Uri &uri, const sptr &dataObserver) = 0; + + virtual std::pair InsertEx(const Uri &uri, const Uri &extUri, + const DataShareValuesBucket &value) = 0; + + virtual std::pair UpdateEx(const Uri &uri, const Uri &extUri, + const DataSharePredicates &predicates, const DataShareValuesBucket &value) = 0; + + virtual std::pair DeleteEx(const Uri &uri, const Uri &extUri, + const DataSharePredicates &predicates) = 0; }; } // namespace OHOS::DataShare #endif diff --git a/data_share/frameworks/native/common/include/idatashare.h b/data_share/frameworks/native/common/include/idatashare.h index eba1512869c2c51a2bee0d4390b49623727fb12d..24ba2bc5816fb4c3064fc8454750f57854829eb2 100644 --- a/data_share/frameworks/native/common/include/idatashare.h +++ b/data_share/frameworks/native/common/include/idatashare.h @@ -70,6 +70,13 @@ public: virtual Uri DenormalizeUri(const Uri &uri) = 0; virtual std::vector GetFileTypes(const Uri &uri, const std::string &mimeTypeFilter) = 0; + + virtual std::pair InsertEx(const Uri &uri, const DataShareValuesBucket &value) = 0; + + virtual std::pair UpdateEx( + const Uri &uri, const DataSharePredicates &predicates, const DataShareValuesBucket &value) = 0; + + virtual std::pair DeleteEx(const Uri &uri, const DataSharePredicates &predicates) = 0; }; } // namespace DataShare } // namespace OHOS diff --git a/data_share/frameworks/native/common/include/ikvstore_data_service.h b/data_share/frameworks/native/common/include/ikvstore_data_service.h index b18c292ea41ae33b047595bfcbe57bb4a9673dac..9bd0f6b4b96e5f239c8bbc41d908145567c468c2 100644 --- a/data_share/frameworks/native/common/include/ikvstore_data_service.h +++ b/data_share/frameworks/native/common/include/ikvstore_data_service.h @@ -19,17 +19,13 @@ #include "iremote_broker.h" #include "iremote_proxy.h" +#include "datashare_errno.h" #include "distributeddata_data_share_ipc_interface_code.h" namespace OHOS { namespace DataShare { class IKvStoreDataService : public IRemoteBroker { public: - enum { - DATA_SHARE_ERROR = -1, - DATA_SHARE_OK = 0, - }; - virtual sptr GetFeatureInterface(const std::string &name) = 0; virtual uint32_t RegisterClientDeathObserver(const std::string &appId, sptr observer) = 0; diff --git a/data_share/frameworks/native/common/src/call_reporter.cpp b/data_share/frameworks/native/common/src/call_reporter.cpp new file mode 100644 index 0000000000000000000000000000000000000000..af25b9e67725a1ad5ddd8575369371fbb8cbbd19 --- /dev/null +++ b/data_share/frameworks/native/common/src/call_reporter.cpp @@ -0,0 +1,60 @@ +/* +* Copyright (c) 2024 Huawei Device Co., Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#include "call_reporter.h" + +#include +#include "datashare_log.h" +#include "datashare_string_utils.h" + +namespace OHOS { +namespace DataShare { +void DataShareCallReporter::Count(const std::string &funcName, const std::string &uri) +{ + int overCount = 0; + int64_t firstCallTime = 0; + callCounts.Compute(funcName, [&overCount, &firstCallTime](auto &key, CallInfo &callInfo) { + auto callCount = callInfo.count; + if (callCount == 0) { + callInfo.firstTime = std::chrono::system_clock::now(); + } + if (++callCount % RESET_COUNT_THRESHOLD == 0) { + int64_t first = std::chrono::duration_cast( + callInfo.firstTime.time_since_epoch()).count(); + int64_t now = std::chrono::duration_cast( + std::chrono::system_clock::now().time_since_epoch()).count(); + ++overCount; + firstCallTime = first; + if (now - first <= TIME_THRESHOLD.count()) { + ++overCount; + } + callCount = 0; + } + callInfo.count = callCount; + return true; + }); + int64_t now = std::chrono::duration_cast( + std::chrono::system_clock::now().time_since_epoch()).count(); + if (overCount > 0) { + LOG_WARN("Call the threshold, func: %{public}s, first:%{public}" PRIi64 "ms, now:%{public}" PRIi64 + "ms, uri:%{public}s", funcName.c_str(), firstCallTime, now, DataShareStringUtils::Anonymous(uri).c_str()); + } + if (overCount > 1) { + LOG_WARN("Call too frequently, func: %{public}s, first:%{public}" PRIi64 "ms, now:%{public}" PRIi64 + "ms, uri:%{public}s", funcName.c_str(), firstCallTime, now, DataShareStringUtils::Anonymous(uri).c_str()); + } +} +} // namespace DataShare +} // namespace OHOS \ No newline at end of file diff --git a/data_share/frameworks/native/common/src/datashare_block_writer_impl.cpp b/data_share/frameworks/native/common/src/datashare_block_writer_impl.cpp index 0bd75dce310da3c4aa22fdc734f741b4696a0f9e..c76c1d3bf621ca2ed0922a75bb2671e7d9cd46b2 100644 --- a/data_share/frameworks/native/common/src/datashare_block_writer_impl.cpp +++ b/data_share/frameworks/native/common/src/datashare_block_writer_impl.cpp @@ -25,7 +25,12 @@ DataShareBlockWriterImpl::DataShareBlockWriterImpl() : shareBlock_(nullptr) DataShareBlockWriterImpl::DataShareBlockWriterImpl(const std::string &name, size_t size) : shareBlock_(nullptr) { - AppDataFwk::SharedBlock::Create(name, size, shareBlock_); + AppDataFwk::SharedBlock *shareBlock = nullptr; + AppDataFwk::SharedBlock::Create(name, size, shareBlock); + if (shareBlock == nullptr) { + return; + } + shareBlock_ = std::shared_ptr(shareBlock); } DataShareBlockWriterImpl::~DataShareBlockWriterImpl() @@ -34,75 +39,102 @@ DataShareBlockWriterImpl::~DataShareBlockWriterImpl() int DataShareBlockWriterImpl::AllocRow() { - if (shareBlock_ == nullptr) { + auto block = GetBlock(); + if (block == nullptr) { LOG_ERROR("shareBlock_ is nullptr"); return E_ERROR; } - return ConvertErrorCode(shareBlock_->AllocRow()); + return ConvertErrorCode(block->AllocRow()); } int DataShareBlockWriterImpl::Write(uint32_t column) { + auto block = GetBlock(); + if (block == nullptr) { + LOG_ERROR("shareBlock_ is nullptr"); + return E_ERROR; + } uint32_t currentRowIndex = 0; if (!GetCurrentRowIndex(currentRowIndex)) { LOG_ERROR("Write null fail"); return E_ERROR; } - return ConvertErrorCode(shareBlock_->PutNull(currentRowIndex, column)); + return ConvertErrorCode(block->PutNull(currentRowIndex, column)); } int DataShareBlockWriterImpl::Write(uint32_t column, int64_t value) { + auto block = GetBlock(); + if (block == nullptr) { + LOG_ERROR("shareBlock_ is nullptr"); + return E_ERROR; + } uint32_t currentRowIndex = 0; if (!GetCurrentRowIndex(currentRowIndex)) { LOG_ERROR("Write long fail"); return E_ERROR; } - return ConvertErrorCode(shareBlock_->PutLong(currentRowIndex, column, value)); + return ConvertErrorCode(block->PutLong(currentRowIndex, column, value)); } int DataShareBlockWriterImpl::Write(uint32_t column, double value) { + auto block = GetBlock(); + if (block == nullptr) { + LOG_ERROR("shareBlock_ is nullptr"); + return E_ERROR; + } uint32_t currentRowIndex = 0; if (!GetCurrentRowIndex(currentRowIndex)) { LOG_ERROR("Write double fail"); return E_ERROR; } - return ConvertErrorCode(shareBlock_->PutDouble(currentRowIndex, column, value)); + return ConvertErrorCode(block->PutDouble(currentRowIndex, column, value)); } int DataShareBlockWriterImpl::Write(uint32_t column, const uint8_t *value, size_t size) { + auto block = GetBlock(); + if (block == nullptr) { + LOG_ERROR("shareBlock_ is nullptr"); + return E_ERROR; + } uint32_t currentRowIndex = 0; if (!GetCurrentRowIndex(currentRowIndex)) { LOG_ERROR("Write blob fail"); return E_ERROR; } - return ConvertErrorCode(shareBlock_->PutBlob(currentRowIndex, column, value, size)); + return ConvertErrorCode(block->PutBlob(currentRowIndex, column, value, size)); } int DataShareBlockWriterImpl::Write(uint32_t column, const char *value, size_t sizeIncludingNull) { + auto block = GetBlock(); + if (block == nullptr) { + LOG_ERROR("shareBlock_ is nullptr"); + return E_ERROR; + } uint32_t currentRowIndex = 0; if (!GetCurrentRowIndex(currentRowIndex)) { LOG_ERROR("Write string fail"); return E_ERROR; } - return ConvertErrorCode(shareBlock_->PutString(currentRowIndex, column, value, sizeIncludingNull)); + return ConvertErrorCode(block->PutString(currentRowIndex, column, value, sizeIncludingNull)); } -AppDataFwk::SharedBlock *DataShareBlockWriterImpl::GetBlock() const +std::shared_ptr DataShareBlockWriterImpl::GetBlock() { return shareBlock_; } bool DataShareBlockWriterImpl::GetCurrentRowIndex(uint32_t &rowIndex) { - if (shareBlock_ == nullptr) { + auto block = GetBlock(); + if (block == nullptr) { LOG_ERROR("shareBlock_ is nullptr"); return false; } - uint32_t rowNum = shareBlock_->GetRowNum(); + uint32_t rowNum = block->GetRowNum(); if (rowNum > 0) { rowIndex = rowNum - 1; return true; diff --git a/data_share/frameworks/native/common/src/datashare_result_set.cpp b/data_share/frameworks/native/common/src/datashare_result_set.cpp index d65ecd83050c88ca6a4bba41a047bccf11955e5e..196741830dfc67ea1cf5daa2c7f6781c731515da 100644 --- a/data_share/frameworks/native/common/src/datashare_result_set.cpp +++ b/data_share/frameworks/native/common/src/datashare_result_set.cpp @@ -16,6 +16,8 @@ #include #include +#include +#include #include "adaptor.h" #include "datashare_block_writer_impl.h" @@ -46,9 +48,6 @@ DataShareResultSet::DataShareResultSet(std::shared_ptr &bridge) return; } sharedBlock_ = blockWriter_->GetBlock(); - if (sharedBlock_ == nullptr) { - return; - } } DataShareResultSet::~DataShareResultSet() @@ -58,33 +57,37 @@ DataShareResultSet::~DataShareResultSet() int DataShareResultSet::GetAllColumnNames(std::vector &columnNames) { - if (bridge_ == nullptr) { + auto bridge = GetBridge(); + if (bridge == nullptr) { LOG_ERROR("bridge_ is null!"); return E_ERROR; } - return bridge_->GetAllColumnNames(columnNames); + return bridge->GetAllColumnNames(columnNames); } int DataShareResultSet::GetRowCount(int &count) { - if (bridge_ == nullptr) { + auto bridge = GetBridge(); + if (bridge == nullptr) { LOG_ERROR("bridge_ is null!"); return E_ERROR; } - return bridge_->GetRowCount(count); + return bridge->GetRowCount(count); } bool DataShareResultSet::OnGo(int startRowIndex, int targetRowIndex, int *cachedIndex) { - if (bridge_ == nullptr || blockWriter_ == nullptr || sharedBlock_ == nullptr) { + auto block = GetBlock(); + auto bridge = GetBridge(); + if (bridge == nullptr || blockWriter_ == nullptr || block == nullptr) { LOG_ERROR("bridge_ or blockWriter_ or sharedBlock_ is null!"); return false; } std::vector columnNames; GetAllColumnNames(columnNames); - sharedBlock_->Clear(); - sharedBlock_->SetColumnNum(columnNames.size()); - int result = bridge_->OnGo(startRowIndex, targetRowIndex, *blockWriter_); + block->Clear(); + block->SetColumnNum(columnNames.size()); + int result = bridge->OnGo(startRowIndex, targetRowIndex, *blockWriter_); if (cachedIndex != nullptr) { *cachedIndex = result; } @@ -99,20 +102,35 @@ void DataShareResultSet::FillBlock(int startRowIndex, AppDataFwk::SharedBlock *b return; } +/** + * Get current bridge + */ +std::shared_ptr DataShareResultSet::GetBridge() +{ + std::shared_lock lock(mutex_); + return bridge_; +} + /** * Get current shared block */ -AppDataFwk::SharedBlock *DataShareResultSet::GetBlock() const +std::shared_ptr DataShareResultSet::GetBlock() { + std::shared_lock lock(mutex_); return sharedBlock_; } int DataShareResultSet::GetDataType(int columnIndex, DataType &dataType) { + auto block = GetBlock(); + if (block == nullptr) { + LOG_ERROR("sharedBlock is null!"); + return E_ERROR; + } int rowCount = 0; GetRowCount(rowCount); AppDataFwk::SharedBlock::CellUnit *cellUnit = - sharedBlock_->GetCellUnit(static_cast(rowPos_) - startRowPos_, static_cast(columnIndex)); + block->GetCellUnit(static_cast(rowPos_) - startRowPos_, static_cast(columnIndex)); if (!cellUnit) { return E_ERROR; } @@ -122,8 +140,9 @@ int DataShareResultSet::GetDataType(int columnIndex, DataType &dataType) int DataShareResultSet::GoToRow(int position) { - if (sharedBlock_ == nullptr) { - LOG_ERROR("sharedBlock_ is null!"); + auto block = GetBlock(); + if (block == nullptr) { + LOG_ERROR("sharedBlock is null!"); return E_ERROR; } int rowCnt = 0; @@ -162,12 +181,17 @@ int DataShareResultSet::GoToRow(int position) int DataShareResultSet::GetBlob(int columnIndex, std::vector &value) { + auto block = GetBlock(); + if (block == nullptr) { + LOG_ERROR("sharedBlock is null!"); + return E_ERROR; + } int errorCode = CheckState(columnIndex); if (errorCode != E_OK) { return errorCode; } - AppDataFwk::SharedBlock::CellUnit *cellUnit = sharedBlock_->GetCellUnit(rowPos_ - startRowPos_, columnIndex); + AppDataFwk::SharedBlock::CellUnit *cellUnit = block->GetCellUnit(rowPos_ - startRowPos_, columnIndex); if (!cellUnit) { return E_ERROR; } @@ -177,7 +201,7 @@ int DataShareResultSet::GetBlob(int columnIndex, std::vector &value) if (type == AppDataFwk::SharedBlock::CELL_UNIT_TYPE_BLOB || type == AppDataFwk::SharedBlock::CELL_UNIT_TYPE_STRING) { size_t size; - const auto *blob = static_cast(sharedBlock_->GetCellUnitValueBlob(cellUnit, &size)); + const auto *blob = static_cast(block->GetCellUnitValueBlob(cellUnit, &size)); if (size == 0 || blob == nullptr) { LOG_WARN("blob data is empty!"); } else { @@ -199,18 +223,19 @@ int DataShareResultSet::GetBlob(int columnIndex, std::vector &value) int DataShareResultSet::GetString(int columnIndex, std::string &value) { - if (sharedBlock_ == nullptr) { + auto block = GetBlock(); + if (block == nullptr) { LOG_ERROR("sharedBlock is null!"); return E_ERROR; } - AppDataFwk::SharedBlock::CellUnit *cellUnit = sharedBlock_->GetCellUnit(rowPos_ - startRowPos_, columnIndex); + AppDataFwk::SharedBlock::CellUnit *cellUnit = block->GetCellUnit(rowPos_ - startRowPos_, columnIndex); if (!cellUnit) { return E_ERROR; } int type = cellUnit->type; if (type == AppDataFwk::SharedBlock::CELL_UNIT_TYPE_STRING) { size_t sizeIncludingNull; - value = std::string(sharedBlock_->GetCellUnitValueString(cellUnit, &sizeIncludingNull)); + value = std::string(block->GetCellUnitValueString(cellUnit, &sizeIncludingNull)); return E_OK; } else if (type == AppDataFwk::SharedBlock::CELL_UNIT_TYPE_NULL) { return E_OK; @@ -235,11 +260,12 @@ int DataShareResultSet::GetString(int columnIndex, std::string &value) int DataShareResultSet::GetInt(int columnIndex, int &value) { - if (sharedBlock_ == nullptr) { + auto block = GetBlock(); + if (block == nullptr) { LOG_ERROR("sharedBlock is null!"); return E_ERROR; } - AppDataFwk::SharedBlock::CellUnit *cellUnit = sharedBlock_->GetCellUnit(rowPos_ - startRowPos_, columnIndex); + AppDataFwk::SharedBlock::CellUnit *cellUnit = block->GetCellUnit(rowPos_ - startRowPos_, columnIndex); if (!cellUnit) { return E_ERROR; } @@ -249,11 +275,12 @@ int DataShareResultSet::GetInt(int columnIndex, int &value) int DataShareResultSet::GetLong(int columnIndex, int64_t &value) { - if (sharedBlock_ == nullptr) { + auto block = GetBlock(); + if (block == nullptr) { LOG_ERROR("sharedBlock is null!"); return E_ERROR; } - AppDataFwk::SharedBlock::CellUnit *cellUnit = sharedBlock_->GetCellUnit(rowPos_ - startRowPos_, columnIndex); + AppDataFwk::SharedBlock::CellUnit *cellUnit = block->GetCellUnit(rowPos_ - startRowPos_, columnIndex); if (!cellUnit) { return E_ERROR; } @@ -265,7 +292,7 @@ int DataShareResultSet::GetLong(int columnIndex, int64_t &value) return E_OK; } else if (type == AppDataFwk::SharedBlock::CELL_UNIT_TYPE_STRING) { size_t sizeIncludingNull; - const char *tempValue = sharedBlock_->GetCellUnitValueString(cellUnit, &sizeIncludingNull); + const char *tempValue = block->GetCellUnitValueString(cellUnit, &sizeIncludingNull); value = ((sizeIncludingNull > 1) && (tempValue != nullptr)) ? long(strtoll(tempValue, nullptr, 0)) : 0L; return E_OK; } else if (type == AppDataFwk::SharedBlock::CELL_UNIT_TYPE_FLOAT) { @@ -285,11 +312,16 @@ int DataShareResultSet::GetLong(int columnIndex, int64_t &value) int DataShareResultSet::GetDouble(int columnIndex, double &value) { + auto block = GetBlock(); + if (block == nullptr) { + LOG_ERROR("sharedBlock is null!"); + return E_ERROR; + } int errorCode = CheckState(columnIndex); if (errorCode != E_OK) { return errorCode; } - AppDataFwk::SharedBlock::CellUnit *cellUnit = sharedBlock_->GetCellUnit(rowPos_ - startRowPos_, columnIndex); + AppDataFwk::SharedBlock::CellUnit *cellUnit = block->GetCellUnit(rowPos_ - startRowPos_, columnIndex); if (!cellUnit) { return E_ERROR; } @@ -299,7 +331,7 @@ int DataShareResultSet::GetDouble(int columnIndex, double &value) return E_OK; } else if (type == AppDataFwk::SharedBlock::CELL_UNIT_TYPE_STRING) { size_t sizeIncludingNull; - const char *tempValue = sharedBlock_->GetCellUnitValueString(cellUnit, &sizeIncludingNull); + const char *tempValue = block->GetCellUnitValueString(cellUnit, &sizeIncludingNull); value = ((sizeIncludingNull > 1) && (tempValue != nullptr)) ? strtod(tempValue, nullptr) : 0.0; return E_OK; } else if (type == AppDataFwk::SharedBlock::CELL_UNIT_TYPE_INTEGER) { @@ -320,11 +352,16 @@ int DataShareResultSet::GetDouble(int columnIndex, double &value) int DataShareResultSet::IsColumnNull(int columnIndex, bool &isNull) { + auto block = GetBlock(); + if (block == nullptr) { + LOG_ERROR("sharedBlock is null!"); + return E_ERROR; + } int errorCode = CheckState(columnIndex); if (errorCode != E_OK) { return errorCode; } - AppDataFwk::SharedBlock::CellUnit *cellUnit = sharedBlock_->GetCellUnit(rowPos_ - startRowPos_, columnIndex); + AppDataFwk::SharedBlock::CellUnit *cellUnit = block->GetCellUnit(rowPos_ - startRowPos_, columnIndex); if (!cellUnit) { return E_ERROR; } @@ -340,8 +377,7 @@ int DataShareResultSet::Close() { DISTRIBUTED_DATA_HITRACE(std::string(__FUNCTION__)); DataShareAbsResultSet::Close(); - ClosedBlock(); - bridge_ = nullptr; + ClosedBlockAndBridge(); return E_OK; } @@ -350,29 +386,34 @@ int DataShareResultSet::Close() */ void DataShareResultSet::SetBlock(AppDataFwk::SharedBlock *block) { - if (sharedBlock_ != block) { - ClosedBlock(); - sharedBlock_ = block; + std::unique_lock lock(mutex_); + if (sharedBlock_ != nullptr) { + if (sharedBlock_.get() != block) { + sharedBlock_ = std::shared_ptr(block); + } + } else { + if (block != nullptr) { + sharedBlock_ = std::shared_ptr(block); + } } } /** * Checks whether an {@code DataShareResultSet} object contains shared blocks */ -bool DataShareResultSet::HasBlock() const +bool DataShareResultSet::HasBlock() { - return sharedBlock_ != nullptr; + return GetBlock() != nullptr; } /** * Closes a shared block that is not empty in this {@code DataShareResultSet} object */ -void DataShareResultSet::ClosedBlock() +void DataShareResultSet::ClosedBlockAndBridge() { - if (sharedBlock_ != nullptr) { - delete sharedBlock_; - sharedBlock_ = nullptr; - } + std::unique_lock lock(mutex_); + sharedBlock_ = nullptr; + bridge_ = nullptr; } void DataShareResultSet::Finalize() @@ -385,10 +426,6 @@ void DataShareResultSet::Finalize() */ int DataShareResultSet::CheckState(int columnIndex) { - if (sharedBlock_ == nullptr) { - LOG_ERROR("sharedBlock is null!"); - return E_ERROR; - } int cnt = 0; GetColumnCount(cnt); if (columnIndex >= cnt || columnIndex < 0) { @@ -402,19 +439,24 @@ int DataShareResultSet::CheckState(int columnIndex) bool DataShareResultSet::Marshalling(MessageParcel &parcel) { - if (sharedBlock_ == nullptr) { + auto block = GetBlock(); + if (block == nullptr) { LOG_ERROR("sharedBlock is null."); return false; } - return sharedBlock_->WriteMessageParcel(parcel); + return block->WriteMessageParcel(parcel); } bool DataShareResultSet::Unmarshalling(MessageParcel &parcel) { - if (sharedBlock_ != nullptr) { + auto block = GetBlock(); + if (block != nullptr) { + LOG_ERROR("sharedBlock is not null."); return false; } - int result = AppDataFwk::SharedBlock::ReadMessageParcel(parcel, sharedBlock_); + AppDataFwk::SharedBlock *sharedBlock = nullptr; + int result = AppDataFwk::SharedBlock::ReadMessageParcel(parcel, sharedBlock); + SetBlock(sharedBlock); if (result < 0) { LOG_ERROR("create from parcel error is %{public}d.", result); } diff --git a/data_share/frameworks/native/common/src/datashare_string_utils.cpp b/data_share/frameworks/native/common/src/datashare_string_utils.cpp index 94d33047c74b98aa12bf47edd96c987f4c7edd36..604843ff94a72b2c444e6652c57899491297f7cd 100644 --- a/data_share/frameworks/native/common/src/datashare_string_utils.cpp +++ b/data_share/frameworks/native/common/src/datashare_string_utils.cpp @@ -14,6 +14,8 @@ */ #include "datashare_string_utils.h" +#include +#include namespace OHOS { namespace DataShare { @@ -45,6 +47,14 @@ std::string DataShareStringUtils::Change(const std::string &name) } return DEFAULT_ANONYMOUS + name.substr(ANONYMOUS_SIZE); } + +int32_t DataShareStringUtils::GetRandomNumber(const int32_t min, const int32_t max) +{ + std::random_device rd; + std::mt19937 gen(rd()); + std::uniform_int_distribution<> dis(min, max); + return dis(gen); +} DataShareStringUtils::DataShareStringUtils() {} DataShareStringUtils::~DataShareStringUtils() {} } // namespace DataShare diff --git a/data_share/frameworks/native/consumer/controller/common/general_controller.h b/data_share/frameworks/native/consumer/controller/common/general_controller.h index c8f7ee857073d836dbdb3fc64fee7fed92d2a014..3a1f6fd7a3ce8a1c28fe757994c6d8eb7d8feb00 100644 --- a/data_share/frameworks/native/consumer/controller/common/general_controller.h +++ b/data_share/frameworks/native/consumer/controller/common/general_controller.h @@ -20,6 +20,7 @@ #include #include "datashare_business_error.h" +#include "datashare_errno.h" #include "datashare_predicates.h" #include "datashare_result_set.h" #include "datashare_values_bucket.h" @@ -49,6 +50,13 @@ public: virtual void UnregisterObserver(const Uri &uri, const sptr &dataObserver) = 0; virtual void NotifyChange(const Uri &uri) = 0; + + virtual std::pair InsertEx(const Uri &uri, const DataShareValuesBucket &value) = 0; + + virtual std::pair UpdateEx( + const Uri &uri, const DataSharePredicates &predicates, const DataShareValuesBucket &value) = 0; + + virtual std::pair DeleteEx(const Uri &uri, const DataSharePredicates &predicates) = 0; }; } // namespace DataShare } // namespace OHOS diff --git a/data_share/frameworks/native/consumer/controller/provider/include/general_controller_provider_impl.h b/data_share/frameworks/native/consumer/controller/provider/include/general_controller_provider_impl.h index 1f75d74ce09037eb87a8199879b6ec5e19506348..e6c5c93166aa3974612df14e8772ddce097b4170 100644 --- a/data_share/frameworks/native/consumer/controller/provider/include/general_controller_provider_impl.h +++ b/data_share/frameworks/native/consumer/controller/provider/include/general_controller_provider_impl.h @@ -46,6 +46,14 @@ public: void UnregisterObserver(const Uri &uri, const sptr &dataObserver) override; void NotifyChange(const Uri &uri) override; + + std::pair InsertEx(const Uri &uri, const DataShareValuesBucket &value) override; + + std::pair UpdateEx( + const Uri &uri, const DataSharePredicates &predicates, const DataShareValuesBucket &value) override; + + std::pair DeleteEx(const Uri &uri, const DataSharePredicates &predicates) override; + private: std::shared_ptr connection_ = nullptr; sptr token_ = {}; diff --git a/data_share/frameworks/native/consumer/controller/provider/src/general_controller_provider_impl.cpp b/data_share/frameworks/native/consumer/controller/provider/src/general_controller_provider_impl.cpp index e7b1c812693888b2dc1aa8f17dc108922f8a006f..6c3420f4c2ef8fd2ab522f29a5217b35445d423e 100644 --- a/data_share/frameworks/native/consumer/controller/provider/src/general_controller_provider_impl.cpp +++ b/data_share/frameworks/native/consumer/controller/provider/src/general_controller_provider_impl.cpp @@ -20,18 +20,17 @@ namespace OHOS { namespace DataShare { -constexpr int INVALID_VALUE = -1; int GeneralControllerProviderImpl::Insert(const Uri &uri, const DataShareValuesBucket &value) { auto connection = connection_; if (connection == nullptr) { LOG_ERROR("connection is nullptr"); - return INVALID_VALUE; + return DATA_SHARE_ERROR; } auto proxy = connection->GetDataShareProxy(uri_, token_); if (proxy == nullptr) { LOG_ERROR("proxy is nullptr"); - return INVALID_VALUE; + return DATA_SHARE_ERROR; } return proxy->Insert(uri, value); } @@ -42,12 +41,12 @@ int GeneralControllerProviderImpl::Update(const Uri &uri, const DataSharePredica auto connection = connection_; if (connection == nullptr) { LOG_ERROR("connection is nullptr"); - return INVALID_VALUE; + return DATA_SHARE_ERROR; } auto proxy = connection->GetDataShareProxy(uri_, token_); if (proxy == nullptr) { LOG_ERROR("proxy is nullptr"); - return INVALID_VALUE; + return DATA_SHARE_ERROR; } return proxy->Update(uri, predicates, value); } @@ -57,16 +56,64 @@ int GeneralControllerProviderImpl::Delete(const Uri &uri, const DataSharePredica auto connection = connection_; if (connection == nullptr) { LOG_ERROR("connection is nullptr"); - return INVALID_VALUE; + return DATA_SHARE_ERROR; } auto proxy = connection->GetDataShareProxy(uri_, token_); if (proxy == nullptr) { LOG_ERROR("proxy is nullptr"); - return INVALID_VALUE; + return DATA_SHARE_ERROR; } return proxy->Delete(uri, predicates); } +std::pair GeneralControllerProviderImpl::InsertEx(const Uri &uri, + const DataShareValuesBucket &value) +{ + auto connection = connection_; + if (connection == nullptr) { + LOG_ERROR("connection is nullptr"); + return std::make_pair(DATA_SHARE_ERROR, 0); + } + auto proxy = connection->GetDataShareProxy(uri_, token_); + if (proxy == nullptr) { + LOG_ERROR("proxy is nullptr"); + return std::make_pair(DATA_SHARE_ERROR, 0); + } + return proxy->InsertEx(uri, value); +} + +std::pair GeneralControllerProviderImpl::UpdateEx( + const Uri &uri, const DataSharePredicates &predicates, const DataShareValuesBucket &value) +{ + auto connection = connection_; + if (connection == nullptr) { + LOG_ERROR("connection is nullptr"); + return std::make_pair(DATA_SHARE_ERROR, 0); + } + auto proxy = connection->GetDataShareProxy(uri_, token_); + if (proxy == nullptr) { + LOG_ERROR("proxy is nullptr"); + return std::make_pair(DATA_SHARE_ERROR, 0); + } + return proxy->UpdateEx(uri, predicates, value); +} + +std::pair GeneralControllerProviderImpl::DeleteEx(const Uri &uri, + const DataSharePredicates &predicates) +{ + auto connection = connection_; + if (connection == nullptr) { + LOG_ERROR("connection is nullptr"); + return std::make_pair(DATA_SHARE_ERROR, 0); + } + auto proxy = connection->GetDataShareProxy(uri_, token_); + if (proxy == nullptr) { + LOG_ERROR("proxy is nullptr"); + return std::make_pair(DATA_SHARE_ERROR, 0); + } + return proxy->DeleteEx(uri, predicates); +} + std::shared_ptr GeneralControllerProviderImpl::Query(const Uri &uri, const DataSharePredicates &predicates, std::vector &columns, DatashareBusinessError &businessError) { diff --git a/data_share/frameworks/native/consumer/controller/service/include/general_controller_service_impl.h b/data_share/frameworks/native/consumer/controller/service/include/general_controller_service_impl.h index 6d3ac96934263d9fd693fe2c2988e62156d4e3b0..a6d26e32f0786aba483df28569e433bfe77f2295 100644 --- a/data_share/frameworks/native/consumer/controller/service/include/general_controller_service_impl.h +++ b/data_share/frameworks/native/consumer/controller/service/include/general_controller_service_impl.h @@ -31,7 +31,7 @@ class IDataAbilityObserver; namespace DataShare { class GeneralControllerServiceImpl : public GeneralController { public: - GeneralControllerServiceImpl() = default; + GeneralControllerServiceImpl(const std::string &ext); virtual ~GeneralControllerServiceImpl(); @@ -49,12 +49,28 @@ public: void UnregisterObserver(const Uri &uri, const sptr &dataObserver) override; void NotifyChange(const Uri &uri) override; + + std::pair InsertEx(const Uri &uri, const DataShareValuesBucket &value) override; + + std::pair UpdateEx( + const Uri &uri, const DataSharePredicates &predicates, const DataShareValuesBucket &value) override; + + std::pair DeleteEx(const Uri &uri, const DataSharePredicates &predicates) override; + private: void ReRegisterObserver(); void SetRegisterCallback(); ConcurrentMap, std::list> observers_; + + std::string extUri_; + + static constexpr int MAX_RETRY_COUNT = 3; + + static constexpr int RANDOM_MIN = 50; + + static constexpr int RANDOM_MAX = 150; }; } // namespace DataShare } // namespace OHOS diff --git a/data_share/frameworks/native/consumer/controller/service/src/general_controller_service_impl.cpp b/data_share/frameworks/native/consumer/controller/service/src/general_controller_service_impl.cpp index 4605e9595a7f5f4793be0acd64d4a63d38ce2108..fa26bc1a58a6e2812be3b9e60797462ccb8a0c73 100644 --- a/data_share/frameworks/native/consumer/controller/service/src/general_controller_service_impl.cpp +++ b/data_share/frameworks/native/consumer/controller/service/src/general_controller_service_impl.cpp @@ -14,6 +14,7 @@ */ #include "general_controller_service_impl.h" +#include #include "dataobs_mgr_client.h" #include "dataobs_mgr_errors.h" @@ -22,7 +23,11 @@ namespace OHOS { namespace DataShare { -constexpr int INVALID_VALUE = -1; +GeneralControllerServiceImpl::GeneralControllerServiceImpl(const std::string &ext) +{ + extUri_ = ext; +} + GeneralControllerServiceImpl::~GeneralControllerServiceImpl() { auto manager = DataShareManagerImpl::GetInstance(); @@ -31,49 +36,137 @@ GeneralControllerServiceImpl::~GeneralControllerServiceImpl() int GeneralControllerServiceImpl::Insert(const Uri &uri, const DataShareValuesBucket &value) { + auto manager = DataShareManagerImpl::GetInstance(); + if (manager == nullptr) { + LOG_ERROR("Manager is nullptr"); + return DATA_SHARE_ERROR; + } + manager->SetCallCount(__FUNCTION__, uri.ToString()); auto proxy = DataShareManagerImpl::GetServiceProxy(); if (proxy == nullptr) { LOG_ERROR("proxy is nullptr"); - return INVALID_VALUE; + return DATA_SHARE_ERROR; } - return proxy->Insert(uri, value); + return proxy->Insert(uri, Uri(extUri_), value); } int GeneralControllerServiceImpl::Update(const Uri &uri, const DataSharePredicates &predicates, const DataShareValuesBucket &value) { + auto manager = DataShareManagerImpl::GetInstance(); + if (manager == nullptr) { + LOG_ERROR("Manager is nullptr"); + return DATA_SHARE_ERROR; + } + manager->SetCallCount(__FUNCTION__, uri.ToString()); auto proxy = DataShareManagerImpl::GetServiceProxy(); if (proxy == nullptr) { LOG_ERROR("proxy is nullptr"); - return INVALID_VALUE; + return DATA_SHARE_ERROR; } - return proxy->Update(uri, predicates, value); + return proxy->Update(uri, Uri(extUri_), predicates, value); } int GeneralControllerServiceImpl::Delete(const Uri &uri, const DataSharePredicates &predicates) { + auto manager = DataShareManagerImpl::GetInstance(); + if (manager == nullptr) { + LOG_ERROR("Manager is nullptr"); + return DATA_SHARE_ERROR; + } + manager->SetCallCount(__FUNCTION__, uri.ToString()); + auto proxy = DataShareManagerImpl::GetServiceProxy(); + if (proxy == nullptr) { + LOG_ERROR("proxy is nullptr"); + return DATA_SHARE_ERROR; + } + return proxy->Delete(uri, Uri(extUri_), predicates); +} + +std::pair GeneralControllerServiceImpl::InsertEx(const Uri &uri, const DataShareValuesBucket &value) +{ + auto manager = DataShareManagerImpl::GetInstance(); + if (manager == nullptr) { + LOG_ERROR("Manager is nullptr"); + return std::make_pair(DATA_SHARE_ERROR, 0); + } + manager->SetCallCount(__FUNCTION__, uri.ToString()); auto proxy = DataShareManagerImpl::GetServiceProxy(); if (proxy == nullptr) { LOG_ERROR("proxy is nullptr"); - return INVALID_VALUE; + return std::make_pair(DATA_SHARE_ERROR, 0); } - return proxy->Delete(uri, predicates); + return proxy->InsertEx(uri, Uri(extUri_), value); +} + +std::pair GeneralControllerServiceImpl::UpdateEx( + const Uri &uri, const DataSharePredicates &predicates, const DataShareValuesBucket &value) +{ + auto manager = DataShareManagerImpl::GetInstance(); + if (manager == nullptr) { + LOG_ERROR("Manager is nullptr"); + return std::make_pair(DATA_SHARE_ERROR, 0); + } + manager->SetCallCount(__FUNCTION__, uri.ToString()); + auto proxy = DataShareManagerImpl::GetServiceProxy(); + if (proxy == nullptr) { + LOG_ERROR("proxy is nullptr"); + return std::make_pair(DATA_SHARE_ERROR, 0); + } + return proxy->UpdateEx(uri, Uri(extUri_), predicates, value); +} + +std::pair GeneralControllerServiceImpl::DeleteEx(const Uri &uri, + const DataSharePredicates &predicates) +{ + auto manager = DataShareManagerImpl::GetInstance(); + if (manager == nullptr) { + LOG_ERROR("Manager is nullptr"); + return std::make_pair(DATA_SHARE_ERROR, 0); + } + manager->SetCallCount(__FUNCTION__, uri.ToString()); + auto proxy = DataShareManagerImpl::GetServiceProxy(); + if (proxy == nullptr) { + LOG_ERROR("proxy is nullptr"); + return std::make_pair(DATA_SHARE_ERROR, 0); + } + return proxy->DeleteEx(uri, Uri(extUri_), predicates); } std::shared_ptr GeneralControllerServiceImpl::Query(const Uri &uri, const DataSharePredicates &predicates, std::vector &columns, DatashareBusinessError &businessError) { + auto manager = DataShareManagerImpl::GetInstance(); + if (manager == nullptr) { + LOG_ERROR("Manager is nullptr"); + return nullptr; + } + manager->SetCallCount(__FUNCTION__, uri.ToString()); auto proxy = DataShareManagerImpl::GetServiceProxy(); if (proxy == nullptr) { LOG_ERROR("proxy is nullptr"); return nullptr; } - return proxy->Query(uri, predicates, columns, businessError); + auto resultSet = proxy->Query(uri, Uri(extUri_), predicates, columns, businessError); + int retryCount = 0; + while (resultSet == nullptr && businessError.GetCode() == E_RESULTSET_BUSY && retryCount++ < MAX_RETRY_COUNT) { + LOG_ERROR("resultSet busy retry, uri: %{public}s", DataShareStringUtils::Anonymous(uri.ToString()).c_str()); + std::this_thread::sleep_for(std::chrono::milliseconds( + DataShareStringUtils::GetRandomNumber(RANDOM_MIN, RANDOM_MAX))); + resultSet = proxy->Query(uri, Uri(extUri_), predicates, columns, businessError); + } + return resultSet; } void GeneralControllerServiceImpl::RegisterObserver(const Uri &uri, const sptr &dataObserver) { + auto manager = DataShareManagerImpl::GetInstance(); + if (manager == nullptr) { + LOG_ERROR("Manager is nullptr"); + return; + } + manager->SetCallCount(__FUNCTION__, uri.ToString()); auto obsMgrClient = OHOS::AAFwk::DataObsMgrClient::GetInstance(); if (obsMgrClient == nullptr) { LOG_ERROR("get DataObsMgrClient failed"); diff --git a/data_share/frameworks/native/consumer/include/datashare_connection.h b/data_share/frameworks/native/consumer/include/datashare_connection.h index 7326345cd921776ae9b13d6cb5525ce9dfc6721e..6e1fa9965c1b9e57e76517f4cd32ef3adce0f05f 100644 --- a/data_share/frameworks/native/consumer/include/datashare_connection.h +++ b/data_share/frameworks/native/consumer/include/datashare_connection.h @@ -23,14 +23,17 @@ #include "ability_connect_callback_stub.h" #include "datashare_proxy.h" #include "event_handler.h" +#include "executor_pool.h" #include "want.h" namespace OHOS { namespace DataShare { using namespace AppExecFwk; -class DataShareConnection : public AAFwk::AbilityConnectionStub { +class DataShareConnection : public AAFwk::AbilityConnectionStub, + public std::enable_shared_from_this { public: - DataShareConnection(const Uri &uri, const sptr &token) : uri_(uri), token_(token) {} + DataShareConnection(const Uri &uri, const sptr &token, int32_t waitTime = 2) : uri_(uri), + token_(token), waitTime_(waitTime) {} virtual ~DataShareConnection(); /** @@ -71,18 +74,34 @@ public: void SetConnectInvalid(); private: + struct DataShareConnectionInfo { + int count = 0; + int64_t firstTime = 0; + int64_t prevTime = 0; + }; struct ConnectCondition { std::condition_variable condition; std::mutex mutex; }; std::shared_ptr ConnectDataShareExtAbility(const Uri &uri, const sptr &token); + std::shared_ptr GetDataShareProxy(); ErrCode Disconnect(); + void ReconnectExtAbility(const std::string &uri); + void DelayConnectExtAbility(const std::string &uri); std::mutex mutex_{}; std::shared_ptr dataShareProxy_; ConnectCondition condition_; Uri uri_; sptr token_ = {}; std::atomic isInvalid_ = false; + static constexpr int MAX_THREADS = 2; + static constexpr int MIN_THREADS = 0; + static constexpr int MAX_RECONNECT = 6; + static constexpr std::chrono::milliseconds RECONNECT_TIME_INTERVAL = std::chrono::milliseconds(10000); + static constexpr std::chrono::milliseconds MAX_RECONNECT_TIME_INTERVAL = std::chrono::milliseconds(70000); + std::shared_ptr pool_; + DataShareConnectionInfo reConnects_; + int32_t waitTime_ = 0; }; } // namespace DataShare } // namespace OHOS diff --git a/data_share/frameworks/native/consumer/include/datashare_helper_impl.h b/data_share/frameworks/native/consumer/include/datashare_helper_impl.h index 6bd3aac2bc376f992d4588f531b115fa4d33e632..d71e4c1ccc30e3c5da88c175813d0561ed8568fa 100644 --- a/data_share/frameworks/native/consumer/include/datashare_helper_impl.h +++ b/data_share/frameworks/native/consumer/include/datashare_helper_impl.h @@ -27,7 +27,7 @@ class DataShareHelperImpl : public DataShareHelper { public: DataShareHelperImpl(const Uri &uri, const sptr &token, std::shared_ptr connection); - DataShareHelperImpl(); + DataShareHelperImpl(std::string extUri = ""); ~DataShareHelperImpl() override; @@ -98,6 +98,13 @@ public: std::vector DisablePubSubs(const std::vector &uris, int64_t subscriberId) override; + std::pair InsertEx(Uri &uri, const DataShareValuesBucket &value) override; + + std::pair UpdateEx( + Uri &uri, const DataSharePredicates &predicates, const DataShareValuesBucket &value) override; + + std::pair DeleteEx(Uri &uri, const DataSharePredicates &predicates) override; + private: std::shared_ptr extSpCtl_ = nullptr; std::shared_ptr generalCtl_ = nullptr; diff --git a/data_share/frameworks/native/consumer/include/datashare_proxy.h b/data_share/frameworks/native/consumer/include/datashare_proxy.h index ee79de3b974527a8141056a1a36a3b632cc41188..7c5fad2af42ca21aa675e45d36832d73c929df97 100644 --- a/data_share/frameworks/native/consumer/include/datashare_proxy.h +++ b/data_share/frameworks/native/consumer/include/datashare_proxy.h @@ -65,6 +65,13 @@ public: virtual Uri DenormalizeUri(const Uri &uri) override; + virtual std::pair InsertEx(const Uri &uri, const DataShareValuesBucket &value) override; + + virtual std::pair UpdateEx(const Uri &uri, const DataSharePredicates &predicates, + const DataShareValuesBucket &value) override; + + virtual std::pair DeleteEx(const Uri &uri, const DataSharePredicates &predicates) override; + private: bool CheckSize(const UpdateOperations &operations); static inline BrokerDelegator delegator_; diff --git a/data_share/frameworks/native/consumer/src/datashare_connection.cpp b/data_share/frameworks/native/consumer/src/datashare_connection.cpp index 55d8efba6d96d737f89bf07960fd47be2eccac86..84f2953365951dd9ced043705044ffd584dd6adc 100644 --- a/data_share/frameworks/native/consumer/src/datashare_connection.cpp +++ b/data_share/frameworks/native/consumer/src/datashare_connection.cpp @@ -25,7 +25,6 @@ namespace OHOS { namespace DataShare { using namespace AppExecFwk; -constexpr int WAIT_TIME = 2; /** * @brief This method is called back to receive the connection result after an ability calls the * ConnectAbility method to connect it to an extension ability. @@ -83,14 +82,78 @@ void DataShareConnection::OnAbilityDisconnectDone(const AppExecFwk::ElementName if (uri.empty()) { return; } - AmsMgrProxy* instance = AmsMgrProxy::GetInstance(); - if (instance == nullptr) { - LOG_ERROR("get proxy failed uri:%{public}s", DataShareStringUtils::Change(uri_.ToString()).c_str()); + if (pool_ == nullptr) { + std::lock_guard lock(mutex_); + if (pool_ == nullptr) { + pool_ = std::make_shared(MAX_THREADS, MIN_THREADS); + } + } + ReconnectExtAbility(uri); +} + +void DataShareConnection::ReconnectExtAbility(const std::string &uri) +{ + if (reConnects_.count == 0) { + AmsMgrProxy* instance = AmsMgrProxy::GetInstance(); + if (instance == nullptr) { + LOG_ERROR("get proxy failed uri:%{public}s", DataShareStringUtils::Change(uri_.ToString()).c_str()); + return; + } + ErrCode ret = instance->Connect(uri, this, token_); + LOG_INFO("reconnect ability, uri:%{public}s, ret = %{public}d", + DataShareStringUtils::Change(uri).c_str(), ret); + if (ret == E_OK) { + auto curr = std::chrono::system_clock::now().time_since_epoch(); + reConnects_.count = 1; + reConnects_.firstTime = std::chrono::duration_cast(curr).count(); + reConnects_.prevTime = std::chrono::duration_cast(curr).count(); + } + return; + } + return DelayConnectExtAbility(uri); +} + +void DataShareConnection::DelayConnectExtAbility(const std::string &uri) +{ + int64_t now = std::chrono::duration_cast( + std::chrono::system_clock::now().time_since_epoch()).count(); + if (now - reConnects_.prevTime >= MAX_RECONNECT_TIME_INTERVAL.count()) { + reConnects_.count = 0; + reConnects_.firstTime = now; + reConnects_.prevTime = now; + } + if (reConnects_.count >= MAX_RECONNECT) { return; } - ErrCode ret = instance->Connect(uri, this, token_); - LOG_INFO("reconnect ability, uri:%{public}s, ret = %{public}d", - DataShareStringUtils::Change(uri_.ToString()).c_str(), ret); + auto delay = RECONNECT_TIME_INTERVAL; + if (now - reConnects_.prevTime >= RECONNECT_TIME_INTERVAL.count()) { + delay = std::chrono::seconds(0); + } + std::weak_ptr self = weak_from_this(); + auto taskid = pool_->Schedule(delay, [uri, self]() { + auto selfSharedPtr = self.lock(); + if (selfSharedPtr) { + AmsMgrProxy* instance = AmsMgrProxy::GetInstance(); + if (instance == nullptr) { + LOG_ERROR("get proxy failed uri:%{public}s", DataShareStringUtils::Change(uri).c_str()); + return; + } + ErrCode ret = instance->Connect(uri, selfSharedPtr.get(), selfSharedPtr->token_); + LOG_INFO("reconnect ability, uri:%{public}s, ret = %{public}d", + DataShareStringUtils::Change(uri).c_str(), ret); + if (ret == E_OK) { + selfSharedPtr->reConnects_.count++; + selfSharedPtr->reConnects_.prevTime = std::chrono::duration_cast( + std::chrono::system_clock::now().time_since_epoch()).count(); + } + } + }); + if (taskid == ExecutorPool::INVALID_TASK_ID) { + LOG_ERROR("create scheduler failed, over the max capacity"); + return; + } + LOG_DEBUG("create scheduler success"); + return; } /** @@ -119,22 +182,22 @@ std::shared_ptr DataShareConnection::ConnectDataShareExtAbility( return nullptr; } std::unique_lock condLock(condition_.mutex); - if (condition_.condition.wait_for(condLock, std::chrono::seconds(WAIT_TIME), + if (condition_.condition.wait_for(condLock, std::chrono::seconds(waitTime_), [this] { return dataShareProxy_ != nullptr; })) { LOG_DEBUG("connect ability ended successfully uri:%{public}s", DataShareStringUtils::Change(reqUri).c_str()); RADAR_REPORT(__FUNCTION__, RadarReporter::CREATE_DATASHARE_HELPER, RadarReporter::CONNECT_EXT, RadarReporter::SUCCESS, RadarReporter::LOCAL_SESS_NAME, Str16ToStr8(token->GetObjectDescriptor()), - RadarReporter::PEER_SESS_NAME, reqUri); + RadarReporter::PEER_SESS_NAME, DataShareStringUtils::Change(reqUri)); } else { LOG_WARN("connect timeout uri:%{public}s", DataShareStringUtils::Change(reqUri).c_str()); RADAR_REPORT(__FUNCTION__, RadarReporter::CREATE_DATASHARE_HELPER, RadarReporter::CONNECT_EXT, RadarReporter::FAILED, RadarReporter::ERROR_CODE, RadarReporter::EXT_CONNECT_TIMEOUT_ERROR, RadarReporter::LOCAL_SESS_NAME, Str16ToStr8(token->GetObjectDescriptor()), - RadarReporter::PEER_SESS_NAME, reqUri); + RadarReporter::PEER_SESS_NAME, DataShareStringUtils::Change(reqUri)); } - return dataShareProxy_; + return GetDataShareProxy(); } /** @@ -158,14 +221,14 @@ void DataShareConnection::DisconnectDataShareExtAbility() RADAR_REPORT(__FUNCTION__, RadarReporter::CREATE_DATASHARE_HELPER, RadarReporter::DIS_CONNECT_EXT, RadarReporter::SUCCESS, RadarReporter::LOCAL_SESS_NAME, Str16ToStr8(token_->GetObjectDescriptor()), - RadarReporter::PEER_SESS_NAME, uri); + RadarReporter::PEER_SESS_NAME, DataShareStringUtils::Change(uri)); return; } RADAR_REPORT(__FUNCTION__, RadarReporter::CREATE_DATASHARE_HELPER, RadarReporter::DIS_CONNECT_EXT, RadarReporter::FAILED, RadarReporter::ERROR_CODE, RadarReporter::EXT_DIS_CONNECT_ERROR, RadarReporter::LOCAL_SESS_NAME, Str16ToStr8(token_->GetObjectDescriptor()), - RadarReporter::PEER_SESS_NAME, uri); + RadarReporter::PEER_SESS_NAME, DataShareStringUtils::Change(uri)); } DataShareConnection::~DataShareConnection() @@ -191,5 +254,11 @@ ErrCode DataShareConnection::Disconnect() } return instance->DisConnect(this); } + +std::shared_ptr DataShareConnection::GetDataShareProxy() +{ + std::lock_guard lock(mutex_); + return dataShareProxy_; +} } // namespace DataShare } // namespace OHOS \ No newline at end of file diff --git a/data_share/frameworks/native/consumer/src/datashare_helper.cpp b/data_share/frameworks/native/consumer/src/datashare_helper.cpp index 1fed4972386d5c1bedce55b17eaa308bea783959..7f11998b2172e19910862480751c021fe492466b 100644 --- a/data_share/frameworks/native/consumer/src/datashare_helper.cpp +++ b/data_share/frameworks/native/consumer/src/datashare_helper.cpp @@ -24,7 +24,6 @@ #include "dataobs_mgr_client.h" #include "datashare_errno.h" #include "datashare_log.h" -#include "datashare_radar_reporter.h" #include "datashare_string_utils.h" namespace OHOS { @@ -34,7 +33,6 @@ namespace { static constexpr const char *DATA_SHARE_PREFIX = "datashare:///"; static constexpr const char *FILE_PREFIX = "file://"; } // namespace -constexpr int INVALID_VALUE = -1; class ObserverImpl : public AAFwk::DataAbilityObserverStub { public: explicit ObserverImpl(const std::shared_ptr dataShareObserver) @@ -77,13 +75,10 @@ std::string DataShareHelper::TransferUriPrefix(const std::string &originPrefix, * @return Returns the created DataShareHelper instance. */ std::shared_ptr DataShareHelper::Creator( - const sptr &token, const std::string &strUri, const std::string &extUri) + const sptr &token, const std::string &strUri, const std::string &extUri, const int waitTime) { DISTRIBUTED_DATA_HITRACE(std::string(LOG_TAG) + "::" + std::string(__FUNCTION__)); - RadarReporter::RadarReport report(RadarReporter::CREATE_DATASHARE_HELPER, - RadarReporter::CREATE_HELPER, __FUNCTION__); if (token == nullptr) { - report.SetError(RadarReporter::INVALID_PARAM_ERROR); LOG_ERROR("token == nullptr"); return nullptr; } @@ -92,12 +87,11 @@ std::shared_ptr DataShareHelper::Creator( Uri uri(replacedUriStr); std::shared_ptr helper = nullptr; if (uri.GetQuery().find("Proxy=true") != std::string::npos) { - auto result = CreateServiceHelper(); + auto result = CreateServiceHelper(extUri, ""); if (result != nullptr && GetSilentProxyStatus(strUri) == E_OK) { return result; } if (extUri.empty()) { - report.SetError(RadarReporter::INVALID_PARAM_ERROR); return nullptr; } Uri ext(extUri); @@ -105,55 +99,44 @@ std::shared_ptr DataShareHelper::Creator( } else { helper = CreateExtHelper(uri, token); } - if (helper == nullptr) { - report.SetError(RadarReporter::CREATE_HELPER_ERROR); - } return helper; } std::shared_ptr DataShareHelper::Creator(const string &strUri, const CreateOptions &options, - const std::string &bundleName) + const std::string &bundleName, const int waitTime) { - RadarReporter::RadarReport report(RadarReporter::CREATE_DATASHARE_HELPER, - RadarReporter::CREATE_HELPER, __FUNCTION__); DISTRIBUTED_DATA_HITRACE(std::string(LOG_TAG) + "::" + std::string(__FUNCTION__)); Uri uri(strUri); if (!options.isProxy_ && options.token_ == nullptr) { LOG_ERROR("token is nullptr"); - report.SetError(RadarReporter::INVALID_PARAM_ERROR); return nullptr; } - auto helper = options.isProxy_ ? CreateServiceHelper(bundleName) : CreateExtHelper(uri, options.token_); - if (helper == nullptr) { - report.SetError(RadarReporter::CREATE_HELPER_ERROR); - } - return helper; + return options.isProxy_ ? CreateServiceHelper("", bundleName) : CreateExtHelper(uri, options.token_); } std::pair> DataShareHelper::Create(const sptr &token, - const std::string &strUri, const std::string &extUri) + const std::string &strUri, const std::string &extUri, const int waitTime) { - RadarReporter::RadarReport report(RadarReporter::CREATE_DATASHARE_HELPER, - RadarReporter::CREATE_HELPER, __FUNCTION__); DISTRIBUTED_DATA_HITRACE(std::string(LOG_TAG) + "::" + std::string(__FUNCTION__)); if (token == nullptr) { LOG_ERROR("Create helper failed, err: %{public}d", E_TOKEN_EMPTY); - report.SetError(RadarReporter::INVALID_PARAM_ERROR); return std::make_pair(E_TOKEN_EMPTY, nullptr); } Uri uri(strUri); if (IsProxy(uri)) { - auto [ret, helper] = CreateProxyHelper(strUri); + auto [ret, helper] = CreateProxyHelper(strUri, extUri); if (helper != nullptr) { return std::make_pair(E_OK, helper); } if (ret == E_BMS_NOT_READY) { - report.SetError(RadarReporter::GET_BMS_FAILED); - LOG_ERROR("BMS not ready, err: %{public}d", E_BMS_NOT_READY); + LOG_ERROR("BMS not ready, uri:%{publish}s", DataShareStringUtils::Change(strUri).c_str()); return std::make_pair(E_DATA_SHARE_NOT_READY, nullptr); } + if (ret == E_BUNDLE_NAME_NOT_EXIST) { + LOG_ERROR("BundleName not exist, uri:%{publish}s", DataShareStringUtils::Change(strUri).c_str()); + return std::make_pair(E_BUNDLE_NAME_NOT_EXIST, nullptr); + } if (extUri.empty()) { - report.SetError(RadarReporter::INVALID_PARAM_ERROR); LOG_ERROR("Ext uri empty, err: %{public}d", E_EXT_URI_INVALID); return std::make_pair(E_EXT_URI_INVALID, nullptr); } @@ -163,11 +146,11 @@ std::pair> DataShareHelper::Create(const s if (helper != nullptr) { return std::make_pair(E_OK, helper); } - report.SetError(RadarReporter::CREATE_HELPER_ERROR); return std::make_pair(E_ERROR, nullptr); } -std::shared_ptr DataShareHelper::CreateServiceHelper(const std::string &bundleName) +std::shared_ptr DataShareHelper::CreateServiceHelper(const std::string &extUri, + const std::string &bundleName) { auto manager = DataShareManagerImpl::GetInstance(); if (manager == nullptr) { @@ -179,7 +162,7 @@ std::shared_ptr DataShareHelper::CreateServiceHelper(const std: LOG_ERROR("Service proxy is nullptr."); return nullptr; } - return std::make_shared(); + return std::make_shared(extUri); } int DataShareHelper::GetSilentProxyStatus(const std::string &uri) @@ -192,9 +175,10 @@ int DataShareHelper::GetSilentProxyStatus(const std::string &uri) return proxy->GetSilentProxyStatus(uri); } -std::shared_ptr DataShareHelper::CreateExtHelper(Uri &uri, const sptr &token) +std::shared_ptr DataShareHelper::CreateExtHelper(Uri &uri, const sptr &token, + const int waitTime) { - sptr connection = new (std::nothrow) DataShareConnection(uri, token); + sptr connection = new (std::nothrow) DataShareConnection(uri, token, waitTime); if (connection == nullptr) { LOG_ERROR("Create DataShareConnection failed."); return nullptr; @@ -204,6 +188,12 @@ std::shared_ptr DataShareHelper::CreateExtHelper(Uri &uri, cons holder->SetConnectInvalid(); holder->DisconnectDataShareExtAbility(); }); + auto manager = DataShareManagerImpl::GetInstance(); + if (manager == nullptr) { + LOG_ERROR("Manager is nullptr"); + return nullptr; + } + manager->SetCallCount(__FUNCTION__, uri.ToString()); if (dataShareConnection->GetDataShareProxy(uri, token) == nullptr) { LOG_ERROR("connect failed"); return nullptr; @@ -374,7 +364,7 @@ int DataShareHelper::SetSilentSwitch(Uri &uri, bool enable) auto proxy = DataShareManagerImpl::GetServiceProxy(); if (proxy == nullptr) { LOG_ERROR("proxy is nullptr"); - return INVALID_VALUE; + return DATA_SHARE_ERROR; } return proxy->SetSilentSwitch(uri, enable); } @@ -384,11 +374,29 @@ bool DataShareHelper::IsProxy(Uri &uri) return (uri.GetQuery().find("Proxy=true") != std::string::npos || uri.GetScheme() == "datashareproxy"); } -std::pair> DataShareHelper::CreateProxyHelper(const std::string &strUri) +std::pair> DataShareHelper::CreateProxyHelper(const std::string &strUri, + const std::string &extUri) { int ret = GetSilentProxyStatus(strUri); - auto helper = ret == E_OK ? CreateServiceHelper() : nullptr; + auto helper = ret == E_OK ? CreateServiceHelper(extUri) : nullptr; return std::make_pair(ret, helper); } + +std::pair DataShareHelper::InsertEx(Uri &uri, const DataShareValuesBucket &value) +{ + return std::make_pair(0, 0); +} + +std::pair DataShareHelper::DeleteEx(Uri &uri, const DataSharePredicates &predicates) +{ + return std::make_pair(0, 0); +} + +std::pair DataShareHelper::UpdateEx(Uri &uri, const DataSharePredicates &predicates, + const DataShareValuesBucket &value) +{ + return std::make_pair(0, 0); +} + } // namespace DataShare } // namespace OHOS \ No newline at end of file diff --git a/data_share/frameworks/native/consumer/src/datashare_helper_impl.cpp b/data_share/frameworks/native/consumer/src/datashare_helper_impl.cpp index f92398d165b2f6c4ef3c91a074b59e3900c2d211..bbf76e1250fe242ce00ade91699b761d6d411d2b 100644 --- a/data_share/frameworks/native/consumer/src/datashare_helper_impl.cpp +++ b/data_share/frameworks/native/consumer/src/datashare_helper_impl.cpp @@ -30,7 +30,6 @@ namespace OHOS { namespace DataShare { using namespace AppExecFwk; -constexpr int INVALID_VALUE = -1; DataShareHelperImpl::DataShareHelperImpl(const Uri &uri, const sptr &token, std::shared_ptr connection) { @@ -39,10 +38,10 @@ DataShareHelperImpl::DataShareHelperImpl(const Uri &uri, const sptr(connection, uri, token); } -DataShareHelperImpl::DataShareHelperImpl() +DataShareHelperImpl::DataShareHelperImpl(std::string extUri) { LOG_DEBUG("starts"); - generalCtl_ = std::make_shared(); + generalCtl_ = std::make_shared(extUri); persistentDataCtl_ = std::make_shared(); publishedDataCtl_ = std::make_shared(); } @@ -77,7 +76,7 @@ int DataShareHelperImpl::OpenFile(Uri &uri, const std::string &mode) auto extSpCtl = extSpCtl_; if (extSpCtl == nullptr) { LOG_ERROR("extSpCtl is nullptr"); - return INVALID_VALUE; + return DATA_SHARE_ERROR; } return extSpCtl->OpenFile(uri, mode); } @@ -87,7 +86,7 @@ int DataShareHelperImpl::OpenRawFile(Uri &uri, const std::string &mode) auto extSpCtl = extSpCtl_; if (extSpCtl == nullptr) { LOG_ERROR("extSpCtl is nullptr"); - return INVALID_VALUE; + return DATA_SHARE_ERROR; } return extSpCtl->OpenRawFile(uri, mode); } @@ -98,7 +97,7 @@ int DataShareHelperImpl::Insert(Uri &uri, const DataShareValuesBucket &value) auto generalCtl = generalCtl_; if (generalCtl == nullptr) { LOG_ERROR("generalCtl_ is nullptr"); - return INVALID_VALUE; + return DATA_SHARE_ERROR; } return generalCtl->Insert(uri, value); } @@ -109,7 +108,7 @@ int DataShareHelperImpl::InsertExt(Uri &uri, const DataShareValuesBucket &value, auto extSpCtl = extSpCtl_; if (extSpCtl == nullptr) { LOG_ERROR("providerSpCtl is nullptr"); - return INVALID_VALUE; + return DATA_SHARE_ERROR; } return extSpCtl->InsertExt(uri, value, result); } @@ -120,7 +119,7 @@ int DataShareHelperImpl::Update(Uri &uri, const DataSharePredicates &predicates, auto generalCtl = generalCtl_; if (generalCtl == nullptr) { LOG_ERROR("generalCtl is nullptr"); - return INVALID_VALUE; + return DATA_SHARE_ERROR; } return generalCtl->Update(uri, predicates, value); } @@ -130,7 +129,7 @@ int DataShareHelperImpl::BatchUpdate(const UpdateOperations &operations, std::ve auto extSpCtl = extSpCtl_; if (extSpCtl == nullptr) { LOG_ERROR("extSpCtl is nullptr"); - return INVALID_VALUE; + return DATA_SHARE_ERROR; } return extSpCtl->BatchUpdate(operations, results); } @@ -141,11 +140,57 @@ int DataShareHelperImpl::Delete(Uri &uri, const DataSharePredicates &predicates) auto generalCtl = generalCtl_; if (generalCtl == nullptr) { LOG_ERROR("generalCtl is nullptr"); - return INVALID_VALUE; + return DATA_SHARE_ERROR; } return generalCtl->Delete(uri, predicates); } +std::pair DataShareHelperImpl::InsertEx(Uri &uri, const DataShareValuesBucket &value) +{ + DISTRIBUTED_DATA_HITRACE(std::string(LOG_TAG) + "::" + std::string(__FUNCTION__)); + auto generalCtl = generalCtl_; + if (generalCtl == nullptr) { + LOG_ERROR("generalCtl_ is nullptr"); + return std::make_pair(DATA_SHARE_ERROR, 0); + } + auto [errCode, status] = generalCtl->InsertEx(uri, value); + if (errCode != E_OK) { + LOG_ERROR("generalCtl insert failed, errCode = %{public}d", errCode); + } + return std::make_pair(errCode, status); +} + +std::pair DataShareHelperImpl::UpdateEx( + Uri &uri, const DataSharePredicates &predicates, const DataShareValuesBucket &value) +{ + DISTRIBUTED_DATA_HITRACE(std::string(LOG_TAG) + "::" + std::string(__FUNCTION__)); + auto generalCtl = generalCtl_; + if (generalCtl == nullptr) { + LOG_ERROR("generalCtl is nullptr"); + return std::make_pair(DATA_SHARE_ERROR, 0); + } + auto [errCode, status] = generalCtl->UpdateEx(uri, predicates, value); + if (errCode != E_OK) { + LOG_ERROR("generalCtl update failed, errCode = %{public}d", errCode); + } + return std::make_pair(errCode, status); +} + +std::pair DataShareHelperImpl::DeleteEx(Uri &uri, const DataSharePredicates &predicates) +{ + DISTRIBUTED_DATA_HITRACE(std::string(LOG_TAG) + "::" + std::string(__FUNCTION__)); + auto generalCtl = generalCtl_; + if (generalCtl == nullptr) { + LOG_ERROR("generalCtl is nullptr"); + return std::make_pair(DATA_SHARE_ERROR, 0); + } + auto [errCode, status] = generalCtl->DeleteEx(uri, predicates); + if (errCode != E_OK) { + LOG_ERROR("generalCtl delete failed, errCode = %{public}d", errCode); + } + return std::make_pair(errCode, status); +} + std::shared_ptr DataShareHelperImpl::Query(Uri &uri, const DataSharePredicates &predicates, std::vector &columns, DatashareBusinessError *businessError) { @@ -179,7 +224,7 @@ int DataShareHelperImpl::BatchInsert(Uri &uri, const std::vectorBatchInsert(uri, values); } @@ -189,7 +234,7 @@ int DataShareHelperImpl::ExecuteBatch(const std::vector &sta auto extSpCtl = extSpCtl_; if (extSpCtl == nullptr) { LOG_ERROR("extSpCtl is nullptr"); - return INVALID_VALUE; + return DATA_SHARE_ERROR; } return extSpCtl->ExecuteBatch(statements, result); } @@ -271,7 +316,7 @@ int DataShareHelperImpl::AddQueryTemplate(const std::string &uri, int64_t subscr if (persistentDataCtl == nullptr) { LOG_ERROR("persistentDataCtl is nullptr"); report.SetError(RadarReporter::DATA_SHARE_DIED_ERROR); - return INVALID_VALUE; + return DATA_SHARE_ERROR; } return persistentDataCtl->AddQueryTemplate(uri, subscriberId, tpl); } @@ -284,7 +329,7 @@ int DataShareHelperImpl::DelQueryTemplate(const std::string &uri, int64_t subscr if (persistentDataCtl == nullptr) { LOG_ERROR("persistentDataCtl is nullptr"); report.SetError(RadarReporter::DATA_SHARE_DIED_ERROR); - return INVALID_VALUE; + return DATA_SHARE_ERROR; } return persistentDataCtl->DelQueryTemplate(uri, subscriberId); } @@ -326,8 +371,8 @@ std::vector DataShareHelperImpl::SubscribeRdbData(const std::ve return persistentDataCtl->SubscribeRdbData(this, uris, templateId, callback); } -std::vector DataShareHelperImpl::UnsubscribeRdbData(const std::vector &uris, - const TemplateId &templateId) +__attribute__((no_sanitize("cfi"))) std::vector DataShareHelperImpl::UnsubscribeRdbData( + const std::vector &uris, const TemplateId &templateId) { LOG_DEBUG("Start UnsubscribeRdbData"); RadarReporter::RadarReport report(RadarReporter::TEMPLATE_DATA_MANAGER, diff --git a/data_share/frameworks/native/consumer/src/datashare_proxy.cpp b/data_share/frameworks/native/consumer/src/datashare_proxy.cpp index 29bba953cd037b1a634989f1f70c0823e7f227ce..11f9c7a9bda7fd17eba09c25f1b8f3ee80f5955a 100644 --- a/data_share/frameworks/native/consumer/src/datashare_proxy.cpp +++ b/data_share/frameworks/native/consumer/src/datashare_proxy.cpp @@ -56,7 +56,7 @@ std::vector DataShareProxy::GetFileTypes(const Uri &uri, const std: int32_t err = Remote()->SendRequest( static_cast(IDataShareInterfaceCode::CMD_GET_FILE_TYPES), data, reply, option); - if (err != DATA_SHARE_NO_ERROR) { + if (err != E_OK) { LOG_ERROR("GetFileTypes fail to SendRequest. err: %{public}d", err); } @@ -90,7 +90,7 @@ int DataShareProxy::OpenFile(const Uri &uri, const std::string &mode) MessageOption option; int32_t err = Remote()->SendRequest( static_cast(IDataShareInterfaceCode::CMD_OPEN_FILE), data, reply, option); - if (err != DATA_SHARE_NO_ERROR) { + if (err != E_OK) { LOG_ERROR("OpenFile fail to SendRequest. err: %{public}d", err); return fd; } @@ -127,7 +127,7 @@ int DataShareProxy::OpenRawFile(const Uri &uri, const std::string &mode) MessageOption option; int32_t err = Remote()->SendRequest( static_cast(IDataShareInterfaceCode::CMD_OPEN_RAW_FILE), data, reply, option); - if (err != DATA_SHARE_NO_ERROR) { + if (err != E_OK) { LOG_ERROR("OpenRawFile fail to SendRequest. err: %{public}d", err); return fd; } @@ -157,7 +157,7 @@ int DataShareProxy::Insert(const Uri &uri, const DataShareValuesBucket &value) MessageOption option; int32_t err = Remote()->SendRequest( static_cast(IDataShareInterfaceCode::CMD_INSERT), data, reply, option); - if (err != DATA_SHARE_NO_ERROR) { + if (err != E_OK) { LOG_ERROR("Insert fail to SendRequest. err: %{public}d", err); return err == PERMISSION_ERR ? PERMISSION_ERR_CODE : index; } @@ -186,7 +186,7 @@ int DataShareProxy::InsertExt(const Uri &uri, const DataShareValuesBucket &value MessageOption option; int32_t err = Remote()->SendRequest( static_cast(IDataShareInterfaceCode::CMD_INSERT_EXT), data, reply, option); - if (err != DATA_SHARE_NO_ERROR) { + if (err != E_OK) { LOG_ERROR("Insert fail to SendRequest. err: %{public}d", err); return index; } @@ -214,7 +214,7 @@ int DataShareProxy::Update(const Uri &uri, const DataSharePredicates &predicates MessageOption option; int32_t err = Remote()->SendRequest( static_cast(IDataShareInterfaceCode::CMD_UPDATE), data, reply, option); - if (err != DATA_SHARE_NO_ERROR) { + if (err != E_OK) { LOG_ERROR("Update fail to SendRequest. err: %{public}d", err); return err == PERMISSION_ERR ? PERMISSION_ERR_CODE : index; } @@ -245,7 +245,7 @@ int DataShareProxy::BatchUpdate(const UpdateOperations &operations, std::vector< MessageOption option; int32_t err = Remote()->SendRequest( static_cast(IDataShareInterfaceCode::CMD_BATCH_UPDATE), data, reply, option); - if (err != DATA_SHARE_NO_ERROR) { + if (err != E_OK) { LOG_ERROR("fail to SendRequest. err: %{public}d", err); return err; } @@ -274,7 +274,7 @@ int DataShareProxy::Delete(const Uri &uri, const DataSharePredicates &predicates MessageOption option; int32_t err = Remote()->SendRequest( static_cast(IDataShareInterfaceCode::CMD_DELETE), data, reply, option); - if (err != DATA_SHARE_NO_ERROR) { + if (err != E_OK) { LOG_ERROR("Delete fail to SendRequest. err: %{public}d", err); return err == PERMISSION_ERR ? PERMISSION_ERR_CODE : index; } @@ -285,6 +285,100 @@ int DataShareProxy::Delete(const Uri &uri, const DataSharePredicates &predicates return index; } +std::pair DataShareProxy::InsertEx(const Uri &uri, const DataShareValuesBucket &value) +{ + MessageParcel data; + data.SetMaxCapacity(MTU_SIZE); + if (!data.WriteInterfaceToken(DataShareProxy::GetDescriptor())) { + LOG_ERROR("WriteInterfaceToken failed"); + return std::make_pair(E_WRITE_TO_PARCE_ERROR, 0); + } + if (!ITypesUtil::Marshal(data, uri, value)) { + LOG_ERROR("fail to Marshal value"); + return std::make_pair(E_MARSHAL_ERROR, 0); + } + + int32_t errCode = -1; + int32_t result = -1; + MessageParcel reply; + MessageOption option; + int32_t err = Remote()->SendRequest( + static_cast(IDataShareInterfaceCode::CMD_INSERT_EX), data, reply, option); + if (err != E_OK) { + LOG_ERROR("InsertEx fail to SendRequest. err: %{public}d", err); + return std::make_pair((err == PERMISSION_ERR ? PERMISSION_ERR_CODE : errCode), 0); + } + + if (!ITypesUtil::Unmarshal(reply, errCode, result)) { + LOG_ERROR("fail to Unmarshal"); + return std::make_pair(E_UNMARSHAL_ERROR, 0); + } + return std::make_pair(errCode, result); +} + +std::pair DataShareProxy::UpdateEx(const Uri &uri, const DataSharePredicates &predicates, + const DataShareValuesBucket &value) +{ + MessageParcel data; + data.SetMaxCapacity(MTU_SIZE); + if (!data.WriteInterfaceToken(DataShareProxy::GetDescriptor())) { + LOG_ERROR("WriteInterfaceToken failed"); + return std::make_pair(E_WRITE_TO_PARCE_ERROR, 0); + } + if (!ITypesUtil::Marshal(data, uri, predicates, value)) { + LOG_ERROR("fail to Marshal value"); + return std::make_pair(E_MARSHAL_ERROR, 0); + } + + int32_t errCode = -1; + int32_t result = -1; + MessageParcel reply; + MessageOption option; + int32_t err = Remote()->SendRequest( + static_cast(IDataShareInterfaceCode::CMD_UPDATE_EX), data, reply, option); + if (err != E_OK) { + LOG_ERROR("UpdateEx fail to SendRequest. err: %{public}d", err); + return std::make_pair((err == PERMISSION_ERR ? PERMISSION_ERR_CODE : errCode), 0); + } + + if (!ITypesUtil::Unmarshal(reply, errCode, result)) { + LOG_ERROR("fail to Unmarshal"); + return std::make_pair(E_UNMARSHAL_ERROR, 0); + } + return std::make_pair(errCode, result); +} + +std::pair DataShareProxy::DeleteEx(const Uri &uri, const DataSharePredicates &predicates) +{ + MessageParcel data; + data.SetMaxCapacity(MTU_SIZE); + if (!data.WriteInterfaceToken(DataShareProxy::GetDescriptor())) { + LOG_ERROR("WriteInterfaceToken failed"); + return std::make_pair(E_WRITE_TO_PARCE_ERROR, 0); + } + if (!ITypesUtil::Marshal(data, uri, predicates)) { + LOG_ERROR("fail to Marshalling predicates"); + return std::make_pair(E_MARSHAL_ERROR, 0); + } + + int32_t errCode = -1; + int32_t result = -1; + MessageParcel reply; + MessageOption option; + int32_t err = Remote()->SendRequest( + static_cast(IDataShareInterfaceCode::CMD_DELETE_EX), data, reply, option); + if (err != E_OK) { + LOG_ERROR("DeleteEx fail to SendRequest. err: %{public}d", err); + return std::make_pair((err == PERMISSION_ERR ? PERMISSION_ERR_CODE : errCode), 0); + } + + if (!ITypesUtil::Unmarshal(reply, errCode, result)) { + LOG_ERROR("fail to Unmarshal"); + return std::make_pair(E_UNMARSHAL_ERROR, 0); + } + return std::make_pair(errCode, result); +} + std::shared_ptr DataShareProxy::Query(const Uri &uri, const DataSharePredicates &predicates, std::vector &columns, DatashareBusinessError &businessError) { @@ -304,7 +398,7 @@ std::shared_ptr DataShareProxy::Query(const Uri &uri, const auto result = ISharedResultSet::ReadFromParcel(reply); businessError.SetCode(reply.ReadInt32()); businessError.SetMessage(reply.ReadString()); - if (err != DATA_SHARE_NO_ERROR) { + if (err != E_OK) { LOG_ERROR("Query fail to SendRequest. err: %{public}d", err); return nullptr; } @@ -329,7 +423,7 @@ std::string DataShareProxy::GetType(const Uri &uri) MessageOption option; int32_t err = Remote()->SendRequest( static_cast(IDataShareInterfaceCode::CMD_GET_TYPE), data, reply, option); - if (err != DATA_SHARE_NO_ERROR) { + if (err != E_OK) { LOG_ERROR("GetFileTypes fail to SendRequest. err: %{public}d", err); return type; } @@ -363,7 +457,7 @@ int DataShareProxy::BatchInsert(const Uri &uri, const std::vectorSendRequest( static_cast(IDataShareInterfaceCode::CMD_BATCH_INSERT), data, reply, option); - if (err != DATA_SHARE_NO_ERROR) { + if (err != E_OK) { LOG_ERROR("fail to SendRequest. err: %{public}d", err); return err == PERMISSION_ERR ? PERMISSION_ERR_CODE : ret; } @@ -391,7 +485,7 @@ int DataShareProxy::ExecuteBatch(const std::vector &statemen MessageOption option; int32_t err = Remote()->SendRequest( static_cast(IDataShareInterfaceCode::CMD_EXECUTE_BATCH), data, reply, option); - if (err != DATA_SHARE_NO_ERROR) { + if (err != E_OK) { LOG_ERROR("fail to SendRequest. err: %{public}d", err); return -1; } @@ -488,7 +582,7 @@ Uri DataShareProxy::NormalizeUri(const Uri &uri) MessageOption option; int32_t err = Remote()->SendRequest( static_cast(IDataShareInterfaceCode::CMD_NORMALIZE_URI), data, reply, option); - if (err != DATA_SHARE_NO_ERROR) { + if (err != E_OK) { LOG_ERROR("NormalizeUri fail to SendRequest. err: %{public}d", err); return Uri(""); } @@ -517,7 +611,7 @@ Uri DataShareProxy::DenormalizeUri(const Uri &uri) MessageOption option; int32_t err = Remote()->SendRequest( static_cast(IDataShareInterfaceCode::CMD_DENORMALIZE_URI), data, reply, option); - if (err != DATA_SHARE_NO_ERROR) { + if (err != E_OK) { LOG_ERROR("DenormalizeUri fail to SendRequest. err: %{public}d", err); return Uri(""); } diff --git a/data_share/frameworks/native/provider/include/datashare_stub.h b/data_share/frameworks/native/provider/include/datashare_stub.h index b4d71b43bb2252af7f76b4777b4f2f0866751eaf..6bd397537fa8eeed4246bb49e20dbb7516895dec 100644 --- a/data_share/frameworks/native/provider/include/datashare_stub.h +++ b/data_share/frameworks/native/provider/include/datashare_stub.h @@ -20,6 +20,7 @@ #include #include "datashare_business_error.h" +#include "datashare_errno.h" #include "idatashare.h" namespace OHOS { @@ -48,10 +49,17 @@ private: ErrCode CmdExecuteBatch(MessageParcel &data, MessageParcel &reply); ErrCode CmdInsertExt(MessageParcel &data, MessageParcel &reply); ErrCode CmdBatchUpdate(MessageParcel &data, MessageParcel &reply); + ErrCode CmdInsertEx(MessageParcel &data, MessageParcel &reply); + ErrCode CmdUpdateEx(MessageParcel &data, MessageParcel &reply); + ErrCode CmdDeleteEx(MessageParcel &data, MessageParcel &reply); virtual int ExecuteBatch(const std::vector &statements, ExecResultSet &result) override; virtual int InsertExt(const Uri &uri, const DataShareValuesBucket &value, std::string &result) override; virtual int BatchUpdate(const UpdateOperations &operations, std::vector &results) override; + virtual std::pair InsertEx(const Uri &uri, const DataShareValuesBucket &value) override; + virtual std::pair UpdateEx(const Uri &uri, const DataSharePredicates &predicates, + const DataShareValuesBucket &value) override; + virtual std::pair DeleteEx(const Uri &uri, const DataSharePredicates &predicates) override; using RequestFuncType = int (DataShareStub::*)(MessageParcel &data, MessageParcel &reply); std::map stubFuncMap_; diff --git a/data_share/frameworks/native/provider/include/datashare_stub_impl.h b/data_share/frameworks/native/provider/include/datashare_stub_impl.h index f0c3e358f562ab9a7af41a3ee3e3afc586cdae63..42b4cc32e16c7ce2a04e0ca885ca4dabea89979d 100644 --- a/data_share/frameworks/native/provider/include/datashare_stub_impl.h +++ b/data_share/frameworks/native/provider/include/datashare_stub_impl.h @@ -67,6 +67,13 @@ public: Uri DenormalizeUri(const Uri &uri) override; + std::pair InsertEx(const Uri &uri, const DataShareValuesBucket &value) override; + + std::pair UpdateEx(const Uri &uri, const DataSharePredicates &predicates, + const DataShareValuesBucket &value) override; + + std::pair DeleteEx(const Uri &uri, const DataSharePredicates &predicates) override; + private: std::shared_ptr GetOwner(); bool CheckCallingPermission(const std::string &permission); diff --git a/data_share/frameworks/native/provider/src/datashare_stub.cpp b/data_share/frameworks/native/provider/src/datashare_stub.cpp index 50c48eaa3119e76e0dfe07f5b572d2bf224772a7..0ebf16736af26ac1acd56295082a18eb67885700 100644 --- a/data_share/frameworks/native/provider/src/datashare_stub.cpp +++ b/data_share/frameworks/native/provider/src/datashare_stub.cpp @@ -55,6 +55,9 @@ DataShareStub::DataShareStub() stubFuncMap_[static_cast(IDataShareInterfaceCode::CMD_EXECUTE_BATCH)] = &DataShareStub::CmdExecuteBatch; stubFuncMap_[static_cast(IDataShareInterfaceCode::CMD_INSERT_EXT)] = &DataShareStub::CmdInsertExt; stubFuncMap_[static_cast(IDataShareInterfaceCode::CMD_BATCH_UPDATE)] = &DataShareStub::CmdBatchUpdate; + stubFuncMap_[static_cast(IDataShareInterfaceCode::CMD_INSERT_EX)] = &DataShareStub::CmdInsertEx; + stubFuncMap_[static_cast(IDataShareInterfaceCode::CMD_UPDATE_EX)] = &DataShareStub::CmdUpdateEx; + stubFuncMap_[static_cast(IDataShareInterfaceCode::CMD_DELETE_EX)] = &DataShareStub::CmdDeleteEx; } DataShareStub::~DataShareStub() @@ -109,7 +112,7 @@ ErrCode DataShareStub::CmdGetFileTypes(MessageParcel &data, MessageParcel &reply LOG_ERROR("Marshal value is nullptr"); return ERR_INVALID_VALUE; } - return DATA_SHARE_NO_ERROR; + return E_OK; } ErrCode DataShareStub::CmdOpenFile(MessageParcel &data, MessageParcel &reply) @@ -134,7 +137,7 @@ ErrCode DataShareStub::CmdOpenFile(MessageParcel &data, MessageParcel &reply) return ERR_INVALID_VALUE; } close(fd); - return DATA_SHARE_NO_ERROR; + return E_OK; } ErrCode DataShareStub::CmdOpenRawFile(MessageParcel &data, MessageParcel &reply) @@ -150,7 +153,7 @@ ErrCode DataShareStub::CmdOpenRawFile(MessageParcel &data, MessageParcel &reply) LOG_ERROR("Marshal value is nullptr"); return ERR_INVALID_VALUE; } - return DATA_SHARE_NO_ERROR; + return E_OK; } ErrCode DataShareStub::CmdInsert(MessageParcel &data, MessageParcel &reply) @@ -173,7 +176,7 @@ ErrCode DataShareStub::CmdInsert(MessageParcel &data, MessageParcel &reply) LOG_ERROR("fail to WriteInt32 index"); return ERR_INVALID_VALUE; } - return DATA_SHARE_NO_ERROR; + return E_OK; } ErrCode DataShareStub::CmdUpdate(MessageParcel &data, MessageParcel &reply) @@ -197,7 +200,7 @@ ErrCode DataShareStub::CmdUpdate(MessageParcel &data, MessageParcel &reply) LOG_ERROR("fail to WriteInt32 index"); return ERR_INVALID_VALUE; } - return DATA_SHARE_NO_ERROR; + return E_OK; } ErrCode DataShareStub::CmdBatchUpdate(OHOS::MessageParcel &data, OHOS::MessageParcel &reply) @@ -217,7 +220,7 @@ ErrCode DataShareStub::CmdBatchUpdate(OHOS::MessageParcel &data, OHOS::MessagePa LOG_ERROR("marshalling updateOperations is failed"); return ERR_INVALID_VALUE; } - return DATA_SHARE_NO_ERROR; + return E_OK; } ErrCode DataShareStub::CmdDelete(MessageParcel &data, MessageParcel &reply) @@ -240,7 +243,81 @@ ErrCode DataShareStub::CmdDelete(MessageParcel &data, MessageParcel &reply) LOG_ERROR("fail to WriteInt32 index"); return ERR_INVALID_VALUE; } - return DATA_SHARE_NO_ERROR; + return E_OK; +} + +ErrCode DataShareStub::CmdInsertEx(MessageParcel &data, MessageParcel &reply) +{ + Uri uri(""); + DataShareValuesBucket value; + if (!ITypesUtil::Unmarshal(data, uri, value)) { + LOG_ERROR("Unmarshalling value is nullptr"); + return E_UNMARSHAL_ERROR; + } + + auto [errCode, result] = InsertEx(uri, value); + if (errCode == DEFAULT_NUMBER) { + LOG_ERROR("Insert inner error"); + return ERR_INVALID_VALUE; + } else if (errCode == PERMISSION_ERROR_NUMBER) { + LOG_ERROR("Insert permission error"); + return ERR_PERMISSION_DENIED; + } + + if (!ITypesUtil::Marshal(reply, errCode, result)) { + LOG_ERROR("Marshal value is nullptr"); + return E_MARSHAL_ERROR; + } + return E_OK; +} + +ErrCode DataShareStub::CmdUpdateEx(MessageParcel &data, MessageParcel &reply) +{ + Uri uri(""); + DataSharePredicates predicates; + DataShareValuesBucket value; + if (!ITypesUtil::Unmarshal(data, uri, predicates, value)) { + LOG_ERROR("Unmarshalling predicates is nullptr"); + return E_UNMARSHAL_ERROR; + } + + auto [errCode, result] = UpdateEx(uri, predicates, value); + if (errCode == DEFAULT_NUMBER) { + LOG_ERROR("Update inner error"); + return ERR_INVALID_VALUE; + } else if (errCode == PERMISSION_ERROR_NUMBER) { + LOG_ERROR("Update permission error"); + return ERR_PERMISSION_DENIED; + } + + if (!ITypesUtil::Marshal(reply, errCode, result)) { + LOG_ERROR("Marshal value is nullptr"); + return E_MARSHAL_ERROR; + } + return E_OK; +} + +ErrCode DataShareStub::CmdDeleteEx(MessageParcel &data, MessageParcel &reply) +{ + Uri uri(""); + DataSharePredicates predicates; + if (!ITypesUtil::Unmarshal(data, uri, predicates)) { + LOG_ERROR("Unmarshalling predicates is nullptr"); + return E_UNMARSHAL_ERROR; + } + auto [errCode, result] = DeleteEx(uri, predicates); + if (errCode == DEFAULT_NUMBER) { + LOG_ERROR("Delete inner error"); + return ERR_INVALID_VALUE; + } else if (errCode == PERMISSION_ERROR_NUMBER) { + LOG_ERROR("Delete permission error"); + return ERR_PERMISSION_DENIED; + } + if (!ITypesUtil::Marshal(reply, errCode, result)) { + LOG_ERROR("Marshal value is nullptr"); + return E_MARSHAL_ERROR; + } + return E_OK; } ErrCode DataShareStub::CmdQuery(MessageParcel &data, MessageParcel &reply) @@ -261,7 +338,7 @@ ErrCode DataShareStub::CmdQuery(MessageParcel &data, MessageParcel &reply) LOG_ERROR("!resultSet->Marshalling(reply)"); return ERR_INVALID_VALUE; } - return DATA_SHARE_NO_ERROR; + return E_OK; } ErrCode DataShareStub::CmdGetType(MessageParcel &data, MessageParcel &reply) @@ -276,7 +353,7 @@ ErrCode DataShareStub::CmdGetType(MessageParcel &data, MessageParcel &reply) LOG_ERROR("fail to WriteString type"); return ERR_INVALID_VALUE; } - return DATA_SHARE_NO_ERROR; + return E_OK; } ErrCode DataShareStub::CmdBatchInsert(MessageParcel &data, MessageParcel &reply) @@ -300,7 +377,7 @@ ErrCode DataShareStub::CmdBatchInsert(MessageParcel &data, MessageParcel &reply) LOG_ERROR("fail to WriteInt32 ret"); return ERR_INVALID_VALUE; } - return DATA_SHARE_NO_ERROR; + return E_OK; } ErrCode DataShareStub::CmdRegisterObserver(MessageParcel &data, MessageParcel &reply) @@ -322,7 +399,7 @@ ErrCode DataShareStub::CmdRegisterObserver(MessageParcel &data, MessageParcel &r LOG_ERROR("fail to WriteInt32 ret"); return ERR_INVALID_VALUE; } - return DATA_SHARE_NO_ERROR; + return E_OK; } ErrCode DataShareStub::CmdUnregisterObserver(MessageParcel &data, MessageParcel &reply) @@ -344,7 +421,7 @@ ErrCode DataShareStub::CmdUnregisterObserver(MessageParcel &data, MessageParcel LOG_ERROR("fail to WriteInt32 ret"); return ERR_INVALID_VALUE; } - return DATA_SHARE_NO_ERROR; + return E_OK; } ErrCode DataShareStub::CmdNotifyChange(MessageParcel &data, MessageParcel &reply) @@ -360,7 +437,7 @@ ErrCode DataShareStub::CmdNotifyChange(MessageParcel &data, MessageParcel &reply LOG_ERROR("fail to WriteInt32 ret"); return ERR_INVALID_VALUE; } - return DATA_SHARE_NO_ERROR; + return E_OK; } ErrCode DataShareStub::CmdNormalizeUri(MessageParcel &data, MessageParcel &reply) @@ -375,7 +452,7 @@ ErrCode DataShareStub::CmdNormalizeUri(MessageParcel &data, MessageParcel &reply LOG_ERROR("Write to message parcel failed!"); return ERR_INVALID_VALUE; } - return DATA_SHARE_NO_ERROR; + return E_OK; } ErrCode DataShareStub::CmdDenormalizeUri(MessageParcel &data, MessageParcel &reply) @@ -391,7 +468,7 @@ ErrCode DataShareStub::CmdDenormalizeUri(MessageParcel &data, MessageParcel &rep LOG_ERROR("Write to message parcel failed!"); return ERR_INVALID_VALUE; } - return DATA_SHARE_NO_ERROR; + return E_OK; } ErrCode DataShareStub::CmdExecuteBatch(MessageParcel &data, MessageParcel &reply) @@ -411,7 +488,7 @@ ErrCode DataShareStub::CmdExecuteBatch(MessageParcel &data, MessageParcel &reply LOG_ERROR("fail to write result"); return ERR_INVALID_VALUE; } - return DATA_SHARE_NO_ERROR; + return E_OK; } ErrCode DataShareStub::CmdInsertExt(MessageParcel &data, MessageParcel &reply) @@ -432,7 +509,7 @@ ErrCode DataShareStub::CmdInsertExt(MessageParcel &data, MessageParcel &reply) LOG_ERROR("fail to write result"); return ERR_INVALID_VALUE; } - return DATA_SHARE_NO_ERROR; + return E_OK; } int DataShareStub::ExecuteBatch(const std::vector &statements, ExecResultSet &result) @@ -449,5 +526,19 @@ int DataShareStub::BatchUpdate(const UpdateOperations &operations, std::vector DataShareStub::InsertEx(const Uri &uri, const DataShareValuesBucket &value) +{ + return std::make_pair(0, 0); +} +std::pair DataShareStub::UpdateEx(const Uri &uri, const DataSharePredicates &predicates, + const DataShareValuesBucket &value) +{ + return std::make_pair(0, 0); +} +std::pair DataShareStub::DeleteEx(const Uri &uri, const DataSharePredicates &predicates) +{ + return std::make_pair(0, 0); +} + } // namespace DataShare } // namespace OHOS \ No newline at end of file diff --git a/data_share/frameworks/native/provider/src/datashare_stub_impl.cpp b/data_share/frameworks/native/provider/src/datashare_stub_impl.cpp index 1246d09972d156106c45ca05c8ec80472369ed7e..bee637f5292604c1b0ad0f9fbc2a473141707974 100644 --- a/data_share/frameworks/native/provider/src/datashare_stub_impl.cpp +++ b/data_share/frameworks/native/provider/src/datashare_stub_impl.cpp @@ -247,6 +247,106 @@ int DataShareStubImpl::Delete(const Uri &uri, const DataSharePredicates &predica return ret; } +std::pair DataShareStubImpl::InsertEx(const Uri &uri, const DataShareValuesBucket &value) +{ + CallingInfo info; + GetCallingInfo(info); + + auto client = sptr(this); + auto extension = client->GetOwner(); + if (extension == nullptr) { + return std::make_pair(DATA_SHARE_ERROR, 0); + } + + if (!CheckCallingPermission(extension->abilityInfo_->writePermission)) { + LOG_ERROR("Check calling permission failed."); + return std::make_pair(PERMISSION_ERROR_NUMBER, 0); + } + + int ret = 0; + std::function syncTaskFunc = [extension, info, uri, value]() { + extension->SetCallingInfo(info); + extension->Insert(uri, value); + }; + std::function getRetFunc = [extension, &ret]() -> bool { + if (extension == nullptr) { + return false; + } + extension->GetResult(ret); + return extension->GetRecvReply(); + }; + std::lock_guard lock(mutex_); + uvQueue_->SyncCall(syncTaskFunc, getRetFunc); + return std::make_pair(E_OK, ret); +} + +std::pair DataShareStubImpl::UpdateEx(const Uri &uri, const DataSharePredicates &predicates, + const DataShareValuesBucket &value) +{ + CallingInfo info; + GetCallingInfo(info); + + auto client = sptr(this); + auto extension = client->GetOwner(); + if (extension == nullptr) { + return std::make_pair(DATA_SHARE_ERROR, 0); + } + + if (!CheckCallingPermission(extension->abilityInfo_->writePermission)) { + LOG_ERROR("Check calling permission failed."); + return std::make_pair(PERMISSION_ERROR_NUMBER, 0); + } + + int ret = 0; + std::function syncTaskFunc = [extension, info, uri, predicates, value]() { + extension->SetCallingInfo(info); + extension->Update(uri, predicates, value); + }; + std::function getRetFunc = [extension, &ret]() -> bool { + if (extension == nullptr) { + return false; + } + extension->GetResult(ret); + return extension->GetRecvReply(); + }; + std::lock_guard lock(mutex_); + uvQueue_->SyncCall(syncTaskFunc, getRetFunc); + return std::make_pair(E_OK, ret); +} + +std::pair DataShareStubImpl::DeleteEx(const Uri &uri, const DataSharePredicates &predicates) +{ + CallingInfo info; + GetCallingInfo(info); + + auto client = sptr(this); + auto extension = client->GetOwner(); + if (extension == nullptr) { + return std::make_pair(DATA_SHARE_ERROR, 0); + } + + if (!CheckCallingPermission(extension->abilityInfo_->writePermission)) { + LOG_ERROR("Check calling permission failed."); + return std::make_pair(PERMISSION_ERROR_NUMBER, 0); + } + + int ret = 0; + std::function syncTaskFunc = [extension, info, uri, predicates]() { + extension->SetCallingInfo(info); + extension->Delete(uri, predicates); + }; + std::function getRetFunc = [extension, &ret]() -> bool { + if (extension == nullptr) { + return false; + } + extension->GetResult(ret); + return extension->GetRecvReply(); + }; + std::lock_guard lock(mutex_); + uvQueue_->SyncCall(syncTaskFunc, getRetFunc); + return std::make_pair(E_OK, ret); +} + std::shared_ptr DataShareStubImpl::Query(const Uri &uri, const DataSharePredicates &predicates, std::vector &columns, DatashareBusinessError &businessError) { @@ -273,9 +373,10 @@ std::shared_ptr DataShareStubImpl::Query(const Uri &uri, if (extension == nullptr) { return false; } + auto isRecvReply = extension->GetRecvReply(); extension->GetResultSet(resultSet); extension->GetBusinessError(businessError); - return extension->GetRecvReply(); + return isRecvReply; }; std::lock_guard lock(mutex_); uvQueue_->SyncCall(syncTaskFunc, getRetFunc); diff --git a/data_share/frameworks/native/proxy/include/ams_mgr_proxy.h b/data_share/frameworks/native/proxy/include/ams_mgr_proxy.h index 3a4fdac873aa6e21646564fb5fa585111636d502..080f428b7ec3a80117b0ba75d9d091d8f99308d5 100644 --- a/data_share/frameworks/native/proxy/include/ams_mgr_proxy.h +++ b/data_share/frameworks/native/proxy/include/ams_mgr_proxy.h @@ -24,15 +24,16 @@ namespace OHOS::DataShare { class AmsMgrProxy { public: ~AmsMgrProxy(); - static AmsMgrProxy* GetInstance(); + static AmsMgrProxy *GetInstance(); int Connect(const std::string &uri, const sptr &connect, const sptr &callerToken); int DisConnect(sptr connect); + private: using Proxy = AAFwk::ExtensionManagerProxy; AmsMgrProxy() = default; class ServiceDeathRecipient : public IRemoteObject::DeathRecipient { public: - explicit ServiceDeathRecipient(AmsMgrProxy* owner) : owner_(owner) + explicit ServiceDeathRecipient(AmsMgrProxy *owner) : owner_(owner) { } void OnRemoteDied(const wptr &object) override @@ -43,7 +44,7 @@ private: } private: - AmsMgrProxy* owner_; + AmsMgrProxy *owner_; }; void OnProxyDied(); bool ConnectSA(); diff --git a/data_share/frameworks/native/proxy/include/data_share_manager_impl.h b/data_share/frameworks/native/proxy/include/data_share_manager_impl.h index dcb38fe99dd81dd038f90d3dcae13e208aac3f8f..8ff96ca25dd5ebc997e7168e915f41f476127c10 100644 --- a/data_share/frameworks/native/proxy/include/data_share_manager_impl.h +++ b/data_share/frameworks/native/proxy/include/data_share_manager_impl.h @@ -16,13 +16,17 @@ #ifndef DATASHARESERVICE_DATA_SHARE_MANAGER_IMPL_H #define DATASHARESERVICE_DATA_SHARE_MANAGER_IMPL_H +#include #include #include #include +#include +#include +#include "call_reporter.h" #include "concurrent_map.h" #include "data_share_service_proxy.h" -#include "data_share_errno.h" +#include "datashare_errno.h" #include "idata_share_client_death_observer.h" #include "iremote_object.h" #include "refbase.h" @@ -85,6 +89,8 @@ public: void RemoveRegisterCallback(GeneralControllerServiceImpl* ptr); void OnAddSystemAbility(int32_t systemAbilityId, const std::string& deviceId); + + void SetCallCount(const std::string &funcName, const std::string &uri); private: DataShareManagerImpl(); @@ -108,13 +114,10 @@ private: sptr dataMgrService_; std::shared_ptr dataShareService_; std::string bundleName_; - static constexpr int WAIT_TIME = 2; - static constexpr int MAX_THREADS = 2; - static constexpr int MIN_THREADS = 0; - std::shared_ptr pool_; std::function)> deathCallback_ = {}; sptr clientDeathObserverPtr_; ConcurrentMap> observers_; + DataShareCallReporter dataShareCallReporter_; }; } } // namespace OHOS::DataShare diff --git a/data_share/frameworks/native/proxy/include/data_share_service_proxy.h b/data_share/frameworks/native/proxy/include/data_share_service_proxy.h index 5b7658cac1cfb61ea5b21d9a6254daccc87876d9..ab1028ee6c0b112318c8e46e5d09b355b72d9de5 100644 --- a/data_share/frameworks/native/proxy/include/data_share_service_proxy.h +++ b/data_share/frameworks/native/proxy/include/data_share_service_proxy.h @@ -26,14 +26,14 @@ namespace OHOS::DataShare { class DataShareServiceProxy final : public IRemoteProxy { public: explicit DataShareServiceProxy(const sptr &object); - int Insert(const Uri &uri, const DataShareValuesBucket &valuesBucket) override; + int Insert(const Uri &uri, const Uri &extUri, const DataShareValuesBucket &valuesBucket) override; - int Update(const Uri &uri, const DataSharePredicates &predicate, + int Update(const Uri &uri, const Uri &extUri, const DataSharePredicates &predicate, const DataShareValuesBucket &valuesBucket) override; - int Delete(const Uri &uri, const DataSharePredicates &predicate) override; + int Delete(const Uri &uri, const Uri &extUri, const DataSharePredicates &predicate) override; - std::shared_ptr Query(const Uri &uri, const DataSharePredicates &predicates, + std::shared_ptr Query(const Uri &uri, const Uri &extUri, const DataSharePredicates &predicates, std::vector &columns, DatashareBusinessError &businessError) override; int AddQueryTemplate(const std::string &uri, int64_t subscriberId, Template &tpl) override; @@ -79,6 +79,15 @@ public: int UnRegisterObserver(const Uri &uri, const sptr &dataObserver) override; + std::pair InsertEx(const Uri &uri, const Uri &extUri, + const DataShareValuesBucket &valuesBucket) override; + + std::pair UpdateEx(const Uri &uri, const Uri &extUri, const DataSharePredicates &predicate, + const DataShareValuesBucket &valuesBucket) override; + + std::pair DeleteEx(const Uri &uri, const Uri &extUri, + const DataSharePredicates &predicate) override; + private: static inline BrokerDelegator delegator_; }; diff --git a/data_share/frameworks/native/proxy/src/ams_mgr_proxy.cpp b/data_share/frameworks/native/proxy/src/ams_mgr_proxy.cpp index 73bdba459e004207901043bbbc14363be903e5c8..0ae950daa5dad90c07b4975750c1b5e9c1b63c47 100644 --- a/data_share/frameworks/native/proxy/src/ams_mgr_proxy.cpp +++ b/data_share/frameworks/native/proxy/src/ams_mgr_proxy.cpp @@ -45,11 +45,8 @@ AmsMgrProxy::~AmsMgrProxy() AmsMgrProxy* AmsMgrProxy::GetInstance() { - static AmsMgrProxy* proxy = nullptr; - if (proxy != nullptr) { - return proxy; - } std::lock_guard lock(pmutex_); + static AmsMgrProxy* proxy = nullptr; if (proxy != nullptr) { return proxy; } diff --git a/data_share/frameworks/native/proxy/src/data_share_manager_impl.cpp b/data_share/frameworks/native/proxy/src/data_share_manager_impl.cpp index 8395eb12c388d68e0e476a69d945eaa7b32e281d..df392164097bf685a14fbfd883d79e0ad8514721 100644 --- a/data_share/frameworks/native/proxy/src/data_share_manager_impl.cpp +++ b/data_share/frameworks/native/proxy/src/data_share_manager_impl.cpp @@ -23,7 +23,6 @@ #include "ipc_skeleton.h" #include "iservice_registry.h" #include "system_ability_definition.h" -#include "executor_pool.h" #include "rdb_subscriber_manager.h" #include "published_data_subscriber_manager.h" @@ -35,9 +34,6 @@ DataShareManagerImpl* DataShareManagerImpl::manager_ = nullptr; DataShareManagerImpl* DataShareManagerImpl::GetInstance() { - if (manager_ != nullptr) { - return manager_; - } std::lock_guard lock(pmutex_); if (manager_ != nullptr) { return manager_; @@ -133,7 +129,6 @@ void DataShareManagerImpl::RegisterClientDeathObserver() DataShareManagerImpl::DataShareManagerImpl() { - pool_ = std::make_shared(MAX_THREADS, MIN_THREADS); SetDeathCallback([](std::shared_ptr proxy) { LOG_INFO("RecoverObs start"); RdbSubscriberManager::GetInstance().RecoverObservers(proxy); @@ -147,10 +142,6 @@ DataShareManagerImpl::~DataShareManagerImpl() std::shared_ptr DataShareManagerImpl::GetProxy() { - if (dataShareService_ != nullptr) { - return dataShareService_; - } - std::lock_guard lock(mutex_); if (dataShareService_ != nullptr) { return dataShareService_; @@ -199,16 +190,6 @@ void DataShareManagerImpl::OnRemoteDied() { LOG_INFO("#######datashare service has dead"); ResetServiceHandle(); - auto taskid = pool_->Schedule(std::chrono::seconds(WAIT_TIME), [this]() { - if (GetServiceProxy() != nullptr) { - deathCallback_(dataShareService_); - } - }); - if (taskid == ExecutorPool::INVALID_TASK_ID) { - LOG_ERROR("create scheduler failed, over the max capacity"); - return; - } - LOG_DEBUG("create scheduler success"); } void DataShareManagerImpl::SetRegisterCallback(GeneralControllerServiceImpl* ptr, @@ -235,6 +216,15 @@ void DataShareManagerImpl::OnAddSystemAbility(int32_t systemAbilityId, const std callback(); return false; }); + auto serviceProxy = GetServiceProxy(); + if (serviceProxy != nullptr) { + deathCallback_(serviceProxy); + } +} + +void DataShareManagerImpl::SetCallCount(const std::string &funcName, const std::string &uri) +{ + dataShareCallReporter_.Count(funcName, uri); } } } diff --git a/data_share/frameworks/native/proxy/src/data_share_service_proxy.cpp b/data_share/frameworks/native/proxy/src/data_share_service_proxy.cpp index bc14154c1bae9063fe13e64d9f350486aea4beb3..66ae66a06f02c75540d000182c59a34574681c34 100644 --- a/data_share/frameworks/native/proxy/src/data_share_service_proxy.cpp +++ b/data_share/frameworks/native/proxy/src/data_share_service_proxy.cpp @@ -25,90 +25,146 @@ namespace OHOS { namespace DataShare { using InterfaceCode = OHOS::DistributedShare::DataShare::DataShareServiceInterfaceCode; - DataShareServiceProxy::DataShareServiceProxy(const sptr &object) : IRemoteProxy(object) { } -int32_t DataShareServiceProxy::Insert(const Uri &uri, const DataShareValuesBucket &value) +int32_t DataShareServiceProxy::Insert(const Uri &uri, const Uri &extUri, const DataShareValuesBucket &value) +{ + auto [errCode, status] = InsertEx(uri, extUri, value); + if (errCode == NO_ERROR) { + return status; + } else if (errCode < NO_ERROR) { + return errCode; + } + LOG_ERROR("DataShareServiceProxy insert failed, errCode = %{public}d", errCode); + return DATA_SHARE_ERROR; +} + +int32_t DataShareServiceProxy::Update(const Uri &uri, const Uri &extUri, + const DataSharePredicates &predicate, const DataShareValuesBucket &valuesBucket) +{ + auto [errCode, status] = UpdateEx(uri, extUri, predicate, valuesBucket); + if (errCode == NO_ERROR) { + return status; + } else if (errCode < NO_ERROR) { + return errCode; + } + LOG_ERROR("DataShareServiceProxy update failed, errCode = %{public}d", errCode); + return DATA_SHARE_ERROR; +} + +int32_t DataShareServiceProxy::Delete(const Uri &uri, const Uri &extUri, const DataSharePredicates &predicate) +{ + auto [errCode, status] = DeleteEx(uri, extUri, predicate); + if (errCode == NO_ERROR) { + return status; + } else if (errCode < NO_ERROR) { + return errCode; + } + LOG_ERROR("DataShareServiceProxy delete failed, errCode = %{public}d", errCode); + return DATA_SHARE_ERROR; +} + +std::pair DataShareServiceProxy::InsertEx(const Uri &uri, const Uri &extUri, + const DataShareValuesBucket &value) { const std::string &uriStr = uri.ToString(); MessageParcel data; if (!data.WriteInterfaceToken(IDataShareService::GetDescriptor())) { LOG_ERROR("Write descriptor failed!"); - return DATA_SHARE_ERROR; + return std::make_pair(E_WRITE_TO_PARCE_ERROR, 0); } - if (!ITypesUtil::Marshal(data, uriStr, value)) { + if (!ITypesUtil::Marshal(data, uriStr, extUri.ToString(), value)) { LOG_ERROR("Write to message parcel failed!"); - return DATA_SHARE_ERROR; + return std::make_pair(E_MARSHAL_ERROR, 0); } + int32_t result = -1; + int32_t errCode = -1; MessageParcel reply; MessageOption option; int32_t err = Remote()->SendRequest( - static_cast(InterfaceCode::DATA_SHARE_SERVICE_CMD_INSERT), data, reply, option); + static_cast(InterfaceCode::DATA_SHARE_SERVICE_CMD_INSERTEX), data, reply, option); if (err != NO_ERROR) { - LOG_ERROR("Insert fail to sendRequest. uri: %{public}s, err: %{public}d", + LOG_ERROR("InsertEx fail to sendRequest. uri: %{public}s, err: %{public}d", DataShareStringUtils::Anonymous(uriStr).c_str(), err); - return DATA_SHARE_ERROR; + return std::make_pair(DATA_SHARE_ERROR, 0); } - return reply.ReadInt32(); + if (!ITypesUtil::Unmarshal(reply, errCode, result)) { + LOG_ERROR("fail to Unmarshal"); + return std::make_pair(E_UNMARSHAL_ERROR, 0); + } + return std::make_pair(errCode, result); } -int32_t DataShareServiceProxy::Update(const Uri &uri, +std::pair DataShareServiceProxy::UpdateEx(const Uri &uri, const Uri &extUri, const DataSharePredicates &predicate, const DataShareValuesBucket &valuesBucket) { const std::string &uriStr = uri.ToString(); MessageParcel data; if (!data.WriteInterfaceToken(IDataShareService::GetDescriptor())) { LOG_ERROR("Write descriptor failed!"); - return DATA_SHARE_ERROR; + return std::make_pair(E_WRITE_TO_PARCE_ERROR, 0); } - if (!ITypesUtil::Marshal(data, uriStr, predicate, valuesBucket)) { + if (!ITypesUtil::Marshal(data, uriStr, extUri.ToString(), predicate, valuesBucket)) { LOG_ERROR("Write to message parcel failed!"); - return DATA_SHARE_ERROR; + return std::make_pair(E_MARSHAL_ERROR, 0); } + int32_t result = -1; + int32_t errCode = -1; MessageParcel reply; MessageOption option; int32_t err = Remote()->SendRequest( - static_cast(InterfaceCode::DATA_SHARE_SERVICE_CMD_UPDATE), data, reply, option); + static_cast(InterfaceCode::DATA_SHARE_SERVICE_CMD_UPDATEEX), data, reply, option); if (err != NO_ERROR) { - LOG_ERROR("Update fail to sendRequest. uri: %{public}s, err: %{public}d", + LOG_ERROR("UpdateEx fail to sendRequest. uri: %{public}s, err: %{public}d", DataShareStringUtils::Anonymous(uriStr).c_str(), err); - return DATA_SHARE_ERROR; + return std::make_pair(DATA_SHARE_ERROR, 0); } - return reply.ReadInt32(); + if (!ITypesUtil::Unmarshal(reply, errCode, result)) { + LOG_ERROR("fail to Unmarshal"); + return std::make_pair(E_UNMARSHAL_ERROR, 0); + } + return std::make_pair(errCode, result); } -int32_t DataShareServiceProxy::Delete(const Uri &uri, const DataSharePredicates &predicate) +std::pair DataShareServiceProxy::DeleteEx(const Uri &uri, const Uri &extUri, + const DataSharePredicates &predicate) { const std::string &uriStr = uri.ToString(); MessageParcel data; if (!data.WriteInterfaceToken(IDataShareService::GetDescriptor())) { LOG_ERROR("Write descriptor failed!"); - return DATA_SHARE_ERROR; + return std::make_pair(E_WRITE_TO_PARCE_ERROR, 0); } - if (!ITypesUtil::Marshal(data, uriStr, predicate)) { + if (!ITypesUtil::Marshal(data, uriStr, extUri.ToString(), predicate)) { LOG_ERROR("Write to message parcel failed!"); - return DATA_SHARE_ERROR; + return std::make_pair(E_MARSHAL_ERROR, 0); } + int32_t result = -1; + int32_t errCode = -1; MessageParcel reply; MessageOption option; int32_t err = Remote()->SendRequest( - static_cast(InterfaceCode::DATA_SHARE_SERVICE_CMD_DELETE), data, reply, option); + static_cast(InterfaceCode::DATA_SHARE_SERVICE_CMD_DELETEEX), data, reply, option); if (err != NO_ERROR) { - LOG_ERROR("Delete fail to sendRequest. uri: %{public}s, err: %{public}d", + LOG_ERROR("DeleteEx fail to sendRequest. uri: %{public}s, err: %{public}d", DataShareStringUtils::Anonymous(uriStr).c_str(), err); - return DATA_SHARE_ERROR; + return std::make_pair(DATA_SHARE_ERROR, 0); } - return reply.ReadInt32(); + if (!ITypesUtil::Unmarshal(reply, errCode, result)) { + LOG_ERROR("fail to Unmarshal"); + return std::make_pair(E_UNMARSHAL_ERROR, 0); + } + return std::make_pair(errCode, result); } -std::shared_ptr DataShareServiceProxy::Query(const Uri &uri, const DataSharePredicates &predicates, - std::vector &columns, DatashareBusinessError &businessError) +std::shared_ptr DataShareServiceProxy::Query(const Uri &uri, const Uri &extUri, + const DataSharePredicates &predicates, std::vector &columns, DatashareBusinessError &businessError) { const std::string &uriStr = uri.ToString(); MessageParcel data; @@ -117,7 +173,7 @@ std::shared_ptr DataShareServiceProxy::Query(const Uri &uri, return nullptr; } - if (!ITypesUtil::Marshal(data, uriStr, predicates, columns)) { + if (!ITypesUtil::Marshal(data, uriStr, extUri.ToString(), predicates, columns)) { LOG_ERROR("Write to message parcel failed!"); return nullptr; } diff --git a/data_share/interfaces/inner_api/BUILD.gn b/data_share/interfaces/inner_api/BUILD.gn index fabe3a7cddbf334ee22da7e3fb34f10cc525b8c8..bb9b3dcef9173b1d4aa74ab49d956fa12cb62b3e 100644 --- a/data_share/interfaces/inner_api/BUILD.gn +++ b/data_share/interfaces/inner_api/BUILD.gn @@ -48,6 +48,7 @@ config("datashare_public_config") { } datashare_consumer_sources = [ + "${datashare_common_native_path}/src/call_reporter.cpp", "${datashare_common_native_path}/src/datashare_string_utils.cpp", "${datashare_native_consumer_path}/controller/provider/src/ext_special_controller.cpp", "${datashare_native_consumer_path}/controller/provider/src/general_controller_provider_impl.cpp", diff --git a/data_share/interfaces/inner_api/common/include/datashare_errno.h b/data_share/interfaces/inner_api/common/include/datashare_errno.h index 3bdf68dc2f24b54e29900d41f68ad5e88501227f..0c58659ef56431820f2923b700447579cc6567a3 100644 --- a/data_share/interfaces/inner_api/common/include/datashare_errno.h +++ b/data_share/interfaces/inner_api/common/include/datashare_errno.h @@ -18,6 +18,10 @@ namespace OHOS { namespace DataShare { +/** +* @brief The error code in the data share error case. +*/ +constexpr int DATA_SHARE_ERROR = -1; /** * @brief The error code in the correct case. @@ -99,22 +103,56 @@ constexpr int E_BMS_NOT_READY = (E_BASE + 50); * @brief metaData not exists */ constexpr int E_METADATA_NOT_EXISTS = (E_BASE + 51); + /** * @brief silent proxy is disable */ constexpr int E_SILENT_PROXY_DISABLE = (E_BASE + 52); + /** * @brief token is empty */ constexpr int E_TOKEN_EMPTY = (E_BASE + 53); + /** * @brief ext uri is empty */ constexpr int E_EXT_URI_INVALID = (E_BASE + 54); + /** * @brief DataShare not ready */ constexpr int E_DATA_SHARE_NOT_READY = (E_BASE + 55); + +/** +* @brief The error code for db error. +*/ +constexpr int E_DB_ERROR = (E_BASE + 56); + +/** +* @brief The error code for data supplier error +*/ +constexpr int E_DATA_SUPPLIER_ERROR = (E_BASE + 57); + +/** +* @brief The error code for marshal error. +*/ +constexpr int E_MARSHAL_ERROR = (E_BASE + 58); + +/** +* @brief The error code for unmarshal error. +*/ +constexpr int E_UNMARSHAL_ERROR = (E_BASE + 59); + +/** +* @brief The error code for write interface token to data error. +*/ +constexpr int E_WRITE_TO_PARCE_ERROR = (E_BASE + 60); + +/** +* @brief The error code for resultSet busy error. +*/ +constexpr int E_RESULTSET_BUSY = (E_BASE + 61); } // namespace DataShare } // namespace OHOS diff --git a/data_share/interfaces/inner_api/consumer/include/datashare_helper.h b/data_share/interfaces/inner_api/consumer/include/datashare_helper.h index 7e7efc9ac5ef6688ec0cdc1adae5804bda7f74f3..c2450aa2baf6882b33ced33d6f81b64a61bfdba1 100644 --- a/data_share/interfaces/inner_api/consumer/include/datashare_helper.h +++ b/data_share/interfaces/inner_api/consumer/include/datashare_helper.h @@ -24,6 +24,7 @@ #include "data_ability_observer_interface.h" #include "datashare_business_error.h" +#include "datashare_errno.h" #include "datashare_observer.h" #include "datashare_operation_statement.h" #include "datashare_predicates.h" @@ -56,22 +57,28 @@ public: * * @param token Indicates the System token. * @param strUri Indicates the database table or disk file to operate. + * @param waitTime connect extension waiting time. * * @return Returns the created DataShareHelper instance. */ - static std::shared_ptr Creator( - const sptr &token, const std::string &strUri, const std::string &extUri = ""); + [[deprecated( + "Use Create(const sptr &, const std::string &, const std::string &, const int &) instead.")]] + static std::shared_ptr Creator(const sptr &token, + const std::string &strUri, const std::string &extUri = "", const int waitTime = 2); /** * @brief Creates a DataShareHelper instance with the Uri and {@link #CreateOptions} . * * @param strUri Indicates the database table or disk file to operate. * @param options Indicates the optional config. + * @param waitTime connect extension waiting time. * * @return Returns the created DataShareHelper instance with a specified Uri. */ + [[deprecated( + "Use Create(const sptr &, const std::string &,const std::string &, const int &) instead.")]] static std::shared_ptr Creator(const std::string &strUri, const CreateOptions &options, - const std::string &bundleName = ""); + const std::string &bundleName = "", const int waitTime = 2); /** * @brief Creates a DataShareHelper instance, priority silent access, use non-silent access when silent is not @@ -80,11 +87,12 @@ public: * @param token Indicates the System token. * @param strUri Indicates the database table or disk file to operate for silent access. * @param extUri Indicates the database table or disk file to operate for non silent access. + * @param waitTime connect extension waiting time. * * @return Returns the created DataShareHelper instance with a specified Uri. */ static std::pair> Create(const sptr &token, - const std::string &strUri, const std::string &extUri); + const std::string &strUri, const std::string &extUri, const int waitTime = 2); /** * @brief Releases the client resource of the Data share. @@ -139,6 +147,7 @@ public: * * @return Returns the index of the inserted data record. */ + [[deprecated("Use InsertEx(Uri &, const DataShareValuesBucket &) instead.")]] virtual int Insert(Uri &uri, const DataShareValuesBucket &value) = 0; /** @@ -161,6 +170,7 @@ public: * * @return Returns the number of data records updated. */ + [[deprecated("Use UpdateEx(Uri &, const DataSharePredicates &, const DataShareValuesBucket &) instead.")]] virtual int Update(Uri &uri, const DataSharePredicates &predicates, const DataShareValuesBucket &value) = 0; /** @@ -181,6 +191,7 @@ public: * * @return Returns the number of data records deleted. */ + [[deprecated("Use DeleteEx(Uri &, const DataSharePredicates &) instead.")]] virtual int Delete(Uri &uri, const DataSharePredicates &predicates) = 0; /** @@ -413,19 +424,54 @@ public: */ static int SetSilentSwitch(Uri &uri, bool enable); + /** + * @brief Inserts a single data record into the database. + * + * @param uri Indicates the path of the data to operate. + * @param value Indicates the data record to insert. If this parameter is null, a blank row will be inserted. + * + * @return Returns pair, the errCode and the index of the inserted data record. + */ + virtual std::pair InsertEx(Uri &uri, const DataShareValuesBucket &value); + + /** + * @brief Updates data records in the database. + * + * @param uri Indicates the path of data to update. + * @param predicates Indicates filter criteria. You should define the processing logic when this parameter is null. + * @param value Indicates the data to update. This parameter can be null. + * + * @return Returns pair, the errCode and the index of data records updated. + */ + virtual std::pair UpdateEx( + Uri &uri, const DataSharePredicates &predicates, const DataShareValuesBucket &value); + + /** + * @brief Deletes one or more data records from the database. + * + * @param uri Indicates the path of the data to operate. + * @param predicates Indicates filter criteria. You should define the processing logic when this parameter is null. + * + * @return Returns pair, the errCode and the index of data records deleted. + */ + virtual std::pair DeleteEx(Uri &uri, const DataSharePredicates &predicates); + private: - static std::shared_ptr CreateServiceHelper(const std::string &bundleName = ""); + static std::shared_ptr CreateServiceHelper(const std::string &extUri = "", + const std::string &bundleName = ""); static int GetSilentProxyStatus(const std::string &uri); - static std::shared_ptr CreateExtHelper(Uri &uri, const sptr &token); + static std::shared_ptr CreateExtHelper(Uri &uri, const sptr &token, + const int waitTime = 2); static std::string TransferUriPrefix(const std::string &originPrefix, const std::string &replacedPrefix, const std::string &originUriStr); static bool IsProxy(Uri &uri); - static std::pair> CreateProxyHelper(const std::string &strUri); + static std::pair> CreateProxyHelper(const std::string &strUri, + const std::string &extUri); }; } // namespace DataShare } // namespace OHOS diff --git a/data_share/interfaces/inner_api/consumer/include/datashare_result_set.h b/data_share/interfaces/inner_api/consumer/include/datashare_result_set.h index 29983c73f577e161e254f534ba9d747e358723d9..9a2a94d4979c71c7063cb29180274ac791edfc4c 100644 --- a/data_share/interfaces/inner_api/consumer/include/datashare_result_set.h +++ b/data_share/interfaces/inner_api/consumer/include/datashare_result_set.h @@ -17,6 +17,7 @@ #define DATASHARE_RESULT_SET_H #include +#include #include #include #include @@ -134,7 +135,7 @@ public: /** * Obtains a block from the SharedResultSet. */ - AppDataFwk::SharedBlock *GetBlock() const override; + std::shared_ptr GetBlock() override; /** * Called when the position of the result set changes. @@ -159,11 +160,12 @@ public: /** * Checks whether an DataShareResultSet object contains shared blocks. */ - bool HasBlock() const; + bool HasBlock(); + std::shared_ptr GetBridge(); protected: int CheckState(int columnIndex); - void ClosedBlock(); + void ClosedBlockAndBridge(); virtual void Finalize(); friend class ISharedResultSetStub; @@ -178,7 +180,8 @@ private: // The actual position of the last row of data in the shareblock int endRowPos_ = -1; // The SharedBlock owned by this DataShareResultSet - AppDataFwk::SharedBlock *sharedBlock_ = nullptr; + std::shared_mutex mutex_; + std::shared_ptr sharedBlock_ = nullptr; std::shared_ptr blockWriter_ = nullptr; std::shared_ptr bridge_ = nullptr; }; diff --git a/data_share/interfaces/inner_api/consumer/include/datashare_shared_result_set.h b/data_share/interfaces/inner_api/consumer/include/datashare_shared_result_set.h index 2b5aaafd342c955e10810ef5dc902dcc1fa06290..8335aca7f56587e183f8744e20107cb32b357f37 100644 --- a/data_share/interfaces/inner_api/consumer/include/datashare_shared_result_set.h +++ b/data_share/interfaces/inner_api/consumer/include/datashare_shared_result_set.h @@ -30,7 +30,7 @@ public: /** * Obtains a block from the {@link SharedResultSet} */ - virtual AppDataFwk::SharedBlock *GetBlock() const = 0; + virtual std::shared_ptr GetBlock() = 0; /** * Adds the data of a {@code SharedResultSet} to a {@link SharedBlock} */ diff --git a/data_share/test/native/BUILD.gn b/data_share/test/native/BUILD.gn index f2ac1cffbedce19111e03be77be4dfe07b84af15..1fc9557d8e92e5861d2914ef626694171b778cba 100644 --- a/data_share/test/native/BUILD.gn +++ b/data_share/test/native/BUILD.gn @@ -404,6 +404,7 @@ ohos_unittest("ValueProxyTest") { deps = [ "${datashare_innerapi_path}/common:datashare_common_static" ] external_deps = [ + "ability_base:zuri", "c_utils:utils", "hilog:libhilog", "ipc:ipc_single", diff --git a/data_share/test/native/resource/datashare_ext_bundle/entry/src/main/ets/DataShareExtAbility/DataShareExtAbility.ts b/data_share/test/native/resource/datashare_ext_bundle/entry/src/main/ets/DataShareExtAbility/DataShareExtAbility.ts index 82bf0301fca42055b311dd8657f8fff726bf0674..ea35214f1d5666bec1d8bc543b70782d687eb057 100644 --- a/data_share/test/native/resource/datashare_ext_bundle/entry/src/main/ets/DataShareExtAbility/DataShareExtAbility.ts +++ b/data_share/test/native/resource/datashare_ext_bundle/entry/src/main/ets/DataShareExtAbility/DataShareExtAbility.ts @@ -13,7 +13,8 @@ * limitations under the License. */ -import Extension from '@ohos.application.DataShareExtensionAbility' +import Extension from '@ohos.application.DataShareExtensionAbility'; +import { UpdateOperation } from '@ohos.application.DataShareExtensionAbility'; import rdb from '@ohos.data.relationalStore'; import rpc from '@ohos.rpc'; @@ -68,6 +69,25 @@ extends Extension { console.info('[ttt] [DataShareTest] [insert] leave'); } + async batchUpdate(operations, callback) { + let recordOps : Record> = operations; + let results : Record> = {}; + for (const [key, values] of Object.entries(recordOps)) { + let result : number[] = []; + for (const value of values) { + await rdbStore.update(TBL_NAME, value.values, value.predicates).then(async (rows) => { + console.info('[ttt] [DataShareTest] [batchUpdate] row count is ' + rows); + result.push(rows); + }).catch((err) => { + console.info("[ttt] [DataShareTest] [batchUpdate] failed, err is " + err); + result.push(-1) + }) + } + results[key] = result; + } + callback(null, results); + } + async update(uri, predicates, value, callback) { console.info('[ttt] [DataShareTest] [update] enter'); if (predicates == null || predicates == undefined) { diff --git a/data_share/test/native/unittest/datashareproxy_test/proxydatas_with_permission_test.cpp b/data_share/test/native/unittest/datashareproxy_test/proxydatas_with_permission_test.cpp index adabe3e696c83e31ccc8bb6c38085d129fea0951..4ef42d23eef1df47b6228d1d715e3447def57ce4 100644 --- a/data_share/test/native/unittest/datashareproxy_test/proxydatas_with_permission_test.cpp +++ b/data_share/test/native/unittest/datashareproxy_test/proxydatas_with_permission_test.cpp @@ -141,11 +141,9 @@ HWTEST_F(ProxyDatasTest, ProxyDatasTest_ResultSet_Test_001, TestSize.Level0) resultSet->GetRowCount(result); EXPECT_EQ(result, 1); - AppDataFwk::SharedBlock *block = nullptr; bool hasBlock = resultSet->HasBlock(); EXPECT_EQ(hasBlock, true); - block = resultSet->GetBlock(); - EXPECT_NE(block, nullptr); + EXPECT_NE(resultSet->GetBlock(), nullptr); std::vector blob; int err = resultSet->GetBlob(-1, blob); diff --git a/data_share/test/native/unittest/mediadatashare_test/src/mediadatashare_unit_test.cpp b/data_share/test/native/unittest/mediadatashare_test/src/mediadatashare_unit_test.cpp index 2b466b0ad0dfbab0efff4039761e94c97c6b62ff..2eb0d0129bc4d9a25947aae0a03214daf780dfa6 100644 --- a/data_share/test/native/unittest/mediadatashare_test/src/mediadatashare_unit_test.cpp +++ b/data_share/test/native/unittest/mediadatashare_test/src/mediadatashare_unit_test.cpp @@ -899,13 +899,12 @@ HWTEST_F(MediaDataShareUnitTest, MediaDataShare_ResultSet_Test_003, TestSize.Lev bool hasBlock = resultSet->HasBlock(); EXPECT_EQ(hasBlock, true); - block = resultSet->GetBlock(); - EXPECT_NE(block, nullptr); - + EXPECT_NE(resultSet->GetBlock(), nullptr); + block = (resultSet->GetBlock()).get(); resultSet->SetBlock(block); - EXPECT_EQ(block, resultSet->GetBlock()); + EXPECT_EQ(block, (resultSet->GetBlock()).get()); resultSet->FillBlock(0, block); - EXPECT_EQ(block, resultSet->GetBlock()); + EXPECT_EQ(block, (resultSet->GetBlock()).get()); LOG_INFO("MediaDataShare_ResultSet_Test_003, End"); } @@ -1073,7 +1072,44 @@ HWTEST_F(MediaDataShareUnitTest, MediaDataShare_CRUD_Test_001, TestSize.Level0) LOG_INFO("MediaDataShare_CRUD_Test_001, End"); } -HWTEST_F(MediaDataShareUnitTest, MediaDataShare_NotImplPredicates_Test_zyp, TestSize.Level0) +HWTEST_F(MediaDataShareUnitTest, MediaDataShare_CRUDEX_Test_001, TestSize.Level0) +{ + LOG_INFO("MediaDataShare_CRUDEX_Test_001::Start"); + std::shared_ptr helper = g_dataShareHelper; + ASSERT_TRUE(helper != nullptr); + Uri uri(MEDIALIBRARY_DATA_URI); + DataShare::DataShareValuesBucket valuesBucket; + valuesBucket.Put("name", "Datashare_CRUDEX_Test001"); + auto [errCode, retVal] = helper->InsertEx(uri, valuesBucket); + EXPECT_EQ((errCode == 0), true); + EXPECT_EQ((retVal >= 0), true); + DataShare::DataSharePredicates predicates; + predicates.EqualTo("name", "Datashare_CRUDEX_Test001"); + + valuesBucket.Clear(); + valuesBucket.Put("name", "Datashare_CRUDEX_Test002"); + auto [errCode1, retVal1] = helper->UpdateEx(uri, predicates, valuesBucket); + EXPECT_EQ((errCode1 == 0), true); + EXPECT_EQ((retVal1 >= 0), true); + DataShare::DataSharePredicates queryPredicates; + queryPredicates.EqualTo("name", "Datashare_CRUDEX_Test002"); + vector columns; + auto resultSet = helper->Query(uri, queryPredicates, columns); + int result = 0; + if (resultSet != nullptr) { + resultSet->GetRowCount(result); + } + EXPECT_EQ(result, 1); + + DataShare::DataSharePredicates deletePredicates; + deletePredicates.EqualTo("name", "Datashare_CRUDEX_Test002'"); + auto [errCode2, retVal2] = helper->DeleteEx(uri, deletePredicates); + EXPECT_EQ((errCode2 == 0), true); + EXPECT_EQ((retVal2 >= 0), true); + LOG_INFO("MediaDataShare_CRUDEX_Test_001, End"); +} + +HWTEST_F(MediaDataShareUnitTest, MediaDataShare_ImplPredicates_Test_001, TestSize.Level0) { LOG_INFO("MediaDataShare_ImplPredicates_Test_001::Start"); DataShare::DataSharePredicates predicates; @@ -1574,5 +1610,68 @@ HWTEST_F(MediaDataShareUnitTest, MediaDataShare_UnregisterObserverExt_002, TestS dataObserver->Clear(); LOG_INFO("MediaDataShare_UnregisterObserverExt_002 end"); } + +HWTEST_F(MediaDataShareUnitTest, MediaDataShare_BatchUpdate_Test_001, TestSize.Level0) +{ + LOG_INFO("MediaDataShare_BatchUpdate_Test_001::Start"); + std::shared_ptr helper = g_dataShareHelper; + ASSERT_TRUE(helper != nullptr); + Uri uri(MEDIALIBRARY_DATA_URI); + DataShare::DataShareValuesBucket valuesBucket; + valuesBucket.Put("name", "batchUpdateTest"); + int ret = helper->Insert(uri, valuesBucket); + EXPECT_GT(ret, 0); + + DataShare::UpdateOperations operations; + std::vector updateOperations1; + DataShare::UpdateOperation updateOperation1; + updateOperation1.valuesBucket.Put("name", "batchUpdateTested"); + updateOperation1.predicates.EqualTo("name", "batchUpdateTest"); + updateOperations1.push_back(updateOperation1); + + std::vector updateOperations2; + DataShare::UpdateOperation updateOperation2; + updateOperation2.valuesBucket.Put("name", "undefined1"); + updateOperation2.predicates.EqualTo("name", "undefined"); + updateOperations1.push_back(updateOperation2); + updateOperations2.push_back(updateOperation2); + + operations.emplace("uri1", updateOperations1); + operations.emplace("uri2", updateOperations2); + std::vector results; + ret = helper->BatchUpdate(operations, results); + EXPECT_EQ(results.size(), 2); + EXPECT_EQ(results[0].codes[0], 1); + EXPECT_EQ(results[0].codes[1], 0); + EXPECT_EQ(results[1].codes[0], 0); + DataShare::DataSharePredicates predicates3; + predicates3.EqualTo("name", "batchUpdateTested"); + ret = helper->Delete(uri, predicates3); + EXPECT_GT(ret, 0); + LOG_INFO("MediaDataShare_BatchUpdate_Test_001 End"); +} + +HWTEST_F(MediaDataShareUnitTest, MediaDataShare_BatchUpdateThanLimit_Test_001, TestSize.Level0) +{ + LOG_INFO("MediaDataShare_BatchUpdateThanLimit_Test_001::Start"); + std::shared_ptr helper = g_dataShareHelper; + ASSERT_TRUE(helper != nullptr); + Uri uri(MEDIALIBRARY_DATA_URI); + + DataShare::UpdateOperations operations; + std::vector updateOperations1; + DataShare::UpdateOperation updateOperation1; + updateOperation1.valuesBucket.Put("name", "batchUpdateTested"); + updateOperation1.predicates.EqualTo("name", "batchUpdateTest"); + for (int i = 0; i < 4001; i++) { + updateOperations1.push_back(updateOperation1); + } + operations.emplace("uri1", updateOperations1); + std::vector results; + int ret = helper->BatchUpdate(operations, results); + EXPECT_EQ(ret, -1); + EXPECT_EQ(results.size(), 0); + LOG_INFO("MediaDataShare_BatchUpdateThanLimit_Test_001 End"); +} } // namespace DataShare } // namespace OHOS \ No newline at end of file diff --git a/data_share/test/native/unittest/mediadatashare_test/src/slientaccess_test.cpp b/data_share/test/native/unittest/mediadatashare_test/src/slientaccess_test.cpp index a5ab5b7aa9c360aeeea4294d7dad1989a14d32a3..bc6a74f65ee96fe640f4e15fc8eb448d530f4d35 100644 --- a/data_share/test/native/unittest/mediadatashare_test/src/slientaccess_test.cpp +++ b/data_share/test/native/unittest/mediadatashare_test/src/slientaccess_test.cpp @@ -83,6 +83,7 @@ protected: std::string TBL_STU_NAME = "name"; std::string TBL_STU_AGE = "age"; std::string SLIENT_ACCESS_PERMISSION1_URI = "datashare:///com.acts.datasharetest/entry/DB00/permission1?Proxy=true"; + std::string SLIENT_ERROR_URI = "datashare:///com.acts.datashare/entry/DB00/TBL00?Proxy=true"; std::string SLIENT_PROXY_PERMISSION1_URI = "datashareproxy://com.acts.datasharetest/entry/DB00/permission1"; std::string SLIENT_ACCESS_PERMISSION2_URI = "datashare:///com.acts.datasharetest/entry/DB00/permission2?Proxy=true"; std::string SLIENT_PROXY_PERMISSION2_URI = "datashareproxy://com.acts.datasharetest/entry/DB00/permission2"; @@ -218,6 +219,126 @@ void SlientAccessTest::TearDownTestCase(void) void SlientAccessTest::SetUp(void) {} void SlientAccessTest::TearDown(void) {} +HWTEST_F(SlientAccessTest, SlientAccess_Creator_Errorcode_Test_001, TestSize.Level0) +{ + LOG_INFO("SlientAccess_Creator_Errorcode_Test_001::Start"); + std::string uriStr1(SLIENT_ACCESS_URI); + std::string uriStr2 (DATA_SHARE_URI); + auto saManager = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager(); + if (saManager == nullptr) { + LOG_ERROR("GetSystemAbilityManager get samgr failed."); + } + auto remoteObj = saManager->GetSystemAbility(STORAGE_MANAGER_MANAGER_ID); + if (remoteObj == nullptr) { + LOG_ERROR("GetSystemAbility service failed."); + } + auto [ret, helper] = DataShare::DataShareHelper::Create(remoteObj, uriStr1, uriStr2); + EXPECT_EQ(ret, DataShare::E_OK); + EXPECT_NE(helper, nullptr); + helper = nullptr; + LOG_INFO("SlientAccess_Creator_Errorcode_Test_001::End"); +} + +HWTEST_F(SlientAccessTest, SlientAccess_Creator_Errorcode_Test_002, TestSize.Level0) +{ + LOG_INFO("SlientAccess_Creator_Errorcode_Test_002::Start"); + std::string uriStr1(SLIENT_ACCESS_URI); + std::string uriStr2 (DATA_SHARE_URI); + auto [ret, helper] = DataShare::DataShareHelper::Create(nullptr, uriStr1, uriStr2); + EXPECT_EQ(ret, DataShare::E_TOKEN_EMPTY); + EXPECT_EQ(helper, nullptr); + LOG_INFO("SlientAccess_Creator_Errorcode_Test_002::End"); +} + +HWTEST_F(SlientAccessTest, SlientAccess_Creator_Errorcode_Test_003, TestSize.Level0) +{ + LOG_INFO("SlientAccess_Creator_Errorcode_Test_003::Start"); + std::string uriStr1(SLIENT_ERROR_URI); + std::string uriStr2 (DATA_SHARE_URI); + auto saManager = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager(); + if (saManager == nullptr) { + LOG_ERROR("GetSystemAbilityManager get samgr failed."); + } + auto remoteObj = saManager->GetSystemAbility(STORAGE_MANAGER_MANAGER_ID); + if (remoteObj == nullptr) { + LOG_ERROR("GetSystemAbility service failed."); + } + auto [ret, helper] = DataShare::DataShareHelper::Create(remoteObj, uriStr1, uriStr2); + EXPECT_EQ(ret, DataShare::E_BUNDLE_NAME_NOT_EXIST); + EXPECT_EQ(helper, nullptr); + helper = nullptr; + LOG_INFO("SlientAccess_Creator_Errorcode_Test_003::End"); +} + +HWTEST_F(SlientAccessTest, SlientAccess_Creator_Errorcode_Test_004, TestSize.Level0) +{ + LOG_INFO("SlientAccess_Creator_Errorcode_Test_004::Start"); + std::string uriStr1(DATA_SHARE_URI); + std::string uriStr2 (DATA_SHARE_URI); + auto saManager = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager(); + if (saManager == nullptr) { + LOG_ERROR("GetSystemAbilityManager get samgr failed."); + } + auto remoteObj = saManager->GetSystemAbility(STORAGE_MANAGER_MANAGER_ID); + if (remoteObj == nullptr) { + LOG_ERROR("GetSystemAbility service failed."); + } + auto [ret, helper] = DataShare::DataShareHelper::Create(remoteObj, uriStr1, uriStr2); + EXPECT_EQ(ret, DataShare::E_OK); + EXPECT_NE(helper, nullptr); + helper = nullptr; + LOG_INFO("SlientAccess_Creator_Errorcode_Test_004::End"); +} + +HWTEST_F(SlientAccessTest, SlientAccess_InsertEx_Test_001, TestSize.Level0) +{ + LOG_INFO("SlientAccess_InsertEx_Test_001::Start"); + auto helper = g_slientAccessHelper; + Uri uri(SLIENT_ACCESS_URI); + DataShare::DataShareValuesBucket valuesBucket; + std::string value = "lisi"; + valuesBucket.Put(TBL_STU_NAME, value); + int age = 25; + valuesBucket.Put(TBL_STU_AGE, age); + + auto [errCode, retVal] = helper->InsertEx(uri, valuesBucket); + EXPECT_EQ((errCode == 0), true); + EXPECT_EQ((retVal > 0), true); + LOG_INFO("SlientAccess_InsertEx_Test_001::End"); +} + +HWTEST_F(SlientAccessTest, SlientAccess_UpdateEx_Test_001, TestSize.Level0) +{ + LOG_INFO("SlientAccess_UpdateEx_Test_001::Start"); + auto helper = g_slientAccessHelper; + Uri uri(SLIENT_ACCESS_URI); + DataShare::DataShareValuesBucket valuesBucket; + int value = 50; + valuesBucket.Put(TBL_STU_AGE, value); + DataShare::DataSharePredicates predicates; + std::string selections = TBL_STU_NAME + " = 'lisi'"; + predicates.SetWhereClause(selections); + auto [errCode, retVal] = helper->UpdateEx(uri, predicates, valuesBucket); + EXPECT_EQ((errCode == 0), true); + EXPECT_EQ((retVal > 0), true); + LOG_INFO("SlientAccess_UpdateEx_Test_001::End"); +} + +HWTEST_F(SlientAccessTest, SlientAccess_DeleteEx_Test_001, TestSize.Level0) +{ + LOG_INFO("SlientAccess_DeleteEx_Test_001::Start"); + auto helper = g_slientAccessHelper; + Uri uri(SLIENT_ACCESS_URI); + + DataShare::DataSharePredicates deletePredicates; + std::string selections = TBL_STU_NAME + " = 'lisi'"; + deletePredicates.SetWhereClause(selections); + auto [errCode, retVal] = helper->DeleteEx(uri, deletePredicates); + EXPECT_EQ((errCode == 0), true); + EXPECT_EQ((retVal > 0), true); + LOG_INFO("SlientAccess_DeleteEx_Test_001::End"); +} + HWTEST_F(SlientAccessTest, SlientAccess_Insert_Test_001, TestSize.Level0) { LOG_INFO("SlientAccess_Insert_Test_001::Start"); diff --git a/datamgr_service/bundle.json b/datamgr_service/bundle.json index c4a0ef434248559bdeba768ca403ef9ca822d0d1..3d202f77f9ca819bc51277026e36ba3a3454bde4 100644 --- a/datamgr_service/bundle.json +++ b/datamgr_service/bundle.json @@ -80,6 +80,7 @@ "resource_management", "safwk", "samgr", + "screenlock_mgr", "time_service", "udmf", "app_file_service", @@ -107,6 +108,7 @@ "name": "//foundation/distributeddatamgr/datamgr_service/services/distributeddataservice/framework:distributeddatasvcfwk", "header": { "header_files": [ + "account/account_delegate.h", "backuprule/backup_rule_manager.h", "checker/checker_manager.h", "cloud/asset_loader.h", @@ -135,6 +137,7 @@ "metadata/store_meta_data_local.h", "metadata/strategy_meta_data.h", "metadata/user_meta_data.h", + "screen/screen_manager.h", "serializable/serializable.h", "snapshot/bind_event.h", "snapshot/machine_status.h", diff --git a/datamgr_service/services/distributeddataservice/adapter/BUILD.gn b/datamgr_service/services/distributeddataservice/adapter/BUILD.gn index ae76a3ce05c556d556e10e88c28317866cacb3cd..15f7c5f80409ee949dc0c5e2a6263b5cb0bb44aa 100644 --- a/datamgr_service/services/distributeddataservice/adapter/BUILD.gn +++ b/datamgr_service/services/distributeddataservice/adapter/BUILD.gn @@ -54,13 +54,18 @@ ohos_shared_library("distributeddata_adapter") { configs = [ ":distributeddata_adapter_private_config" ] deps = [ + "${data_service_path}/adapter/account:distributeddata_account_static", + "${data_service_path}/adapter/communicator:distributeddata_communicator_static", + "${data_service_path}/adapter/dfx:distributeddata_dfx_static", + "${data_service_path}/adapter/permission:distributeddata_permission_static", "${data_service_path}/framework:distributeddatasvcfwk", - "//foundation/distributeddatamgr/datamgr_service/services/distributeddataservice/adapter/account:distributeddata_account_static", - "//foundation/distributeddatamgr/datamgr_service/services/distributeddataservice/adapter/communicator:distributeddata_communicator_static", - "//foundation/distributeddatamgr/datamgr_service/services/distributeddataservice/adapter/dfx:distributeddata_dfx_static", - "//foundation/distributeddatamgr/datamgr_service/services/distributeddataservice/adapter/permission:distributeddata_permission_static", ] + if (defined(global_parts_info) && + defined(global_parts_info.theme_screenlock_mgr)) { + deps += [ "${data_service_path}/adapter/screenlock:distributeddata_screenlock_static" ] + } + external_deps = [ "c_utils:utils", "hilog:libhilog", diff --git a/datamgr_service/services/distributeddataservice/adapter/CMakeLists.txt b/datamgr_service/services/distributeddataservice/adapter/CMakeLists.txt index 3f76667f64ea9b96c5cda1173337b03054bb2dcc..3b7c83fd04d0bdfdd70e3f25b102c8368c1fd89d 100644 --- a/datamgr_service/services/distributeddataservice/adapter/CMakeLists.txt +++ b/datamgr_service/services/distributeddataservice/adapter/CMakeLists.txt @@ -19,6 +19,7 @@ aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/dfx/src/fault adapterSrc) aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/dfx/src/statistic adapterSrc) aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/dfx/src adapterSrc) aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/permission/src adapterSrc) +aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/screenlock/src adapterSrc) aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/utils/src adapterSrc) list(REMOVE_ITEM adapterSrc "${CMAKE_CURRENT_SOURCE_DIR}/account/src/account_delegate_default_impl.cpp") @@ -50,4 +51,5 @@ target_include_directories(adapter PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include/br target_include_directories(adapter PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include/communicator) target_include_directories(adapter PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include/dfx) target_include_directories(adapter PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include/permission) +target_include_directories(adapter PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include/screenlock) target_include_directories(adapter PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include/utils) diff --git a/datamgr_service/services/distributeddataservice/adapter/account/BUILD.gn b/datamgr_service/services/distributeddataservice/adapter/account/BUILD.gn index 95465797ce4eb1ea4b0382aa0f86e502a09a748b..2bc40d6e4c1560edd1bd02d6e24868b246ae9bdb 100644 --- a/datamgr_service/services/distributeddataservice/adapter/account/BUILD.gn +++ b/datamgr_service/services/distributeddataservice/adapter/account/BUILD.gn @@ -22,13 +22,10 @@ ohos_static_library("distributeddata_account_static") { boundary_sanitize = true ubsan = true } - sources = [ - "src/account_delegate.cpp", - "src/account_delegate_impl.cpp", - ] + sources = [ "src/account_delegate_impl.cpp" ] include_dirs = [ - "../include/account", + "../../framework/include/account", "../include/autils", "../include/log", "../include/permission", diff --git a/datamgr_service/services/distributeddataservice/adapter/account/src/account_delegate_default_impl.cpp b/datamgr_service/services/distributeddataservice/adapter/account/src/account_delegate_default_impl.cpp index 7cf335879f4fa11584617f47560f1a91f8f3c6f3..444d7b29986cdc7e7d99098cdd69d7464038aa6b 100644 --- a/datamgr_service/services/distributeddataservice/adapter/account/src/account_delegate_default_impl.cpp +++ b/datamgr_service/services/distributeddataservice/adapter/account/src/account_delegate_default_impl.cpp @@ -22,13 +22,7 @@ namespace DistributedKv { namespace { constexpr const char *DEFAULT_OHOS_ACCOUNT_UID = ""; // default UID } - -AccountDelegate::BaseInstance AccountDelegate::getInstance_ = AccountDelegateDefaultImpl::GetBaseInstance; -AccountDelegate *AccountDelegateDefaultImpl::GetBaseInstance() -{ - static AccountDelegateDefaultImpl accountDelegate; - return &accountDelegate; -} +__attribute__((used)) static bool g_isInit = AccountDelegateDefaultImpl::Init(); std::string AccountDelegateDefaultImpl::GetCurrentAccountId() const { @@ -87,5 +81,13 @@ void AccountDelegateDefaultImpl::BindExecutor(std::shared_ptr exec { ZLOGD("no account part"); } -} // namespace DistributedKv + +bool AccountDelegateDefaultImpl::Init() +{ + static AccountDelegateDefaultImpl defaultAccountDelegate; + static std::once_flag onceFlag; + std::call_once(onceFlag, [&]() { AccountDelegate::RegisterAccountInstance(&defaultAccountDelegate); }); + return true; +} +} // namespace DistributedKv } // namespace OHOS \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/adapter/account/src/account_delegate_default_impl.h b/datamgr_service/services/distributeddataservice/adapter/account/src/account_delegate_default_impl.h index 74298cb527cf025187096a84e660cde313f13f3a..04ebda1d6e45fd6e1de5073019b2fad5c0bde08b 100644 --- a/datamgr_service/services/distributeddataservice/adapter/account/src/account_delegate_default_impl.h +++ b/datamgr_service/services/distributeddataservice/adapter/account/src/account_delegate_default_impl.h @@ -21,7 +21,6 @@ namespace OHOS { namespace DistributedKv { class AccountDelegateDefaultImpl final : public AccountDelegateImpl { public: - static AccountDelegate *GetBaseInstance(); std::string GetCurrentAccountId() const override; int32_t GetUserByToken(uint32_t tokenId) const override; bool QueryUsers(std::vector &users) override; @@ -31,6 +30,7 @@ public: void SubscribeAccountEvent() override; void UnsubscribeAccountEvent() override; void BindExecutor(std::shared_ptr executors) override; + static bool Init(); private: ~AccountDelegateDefaultImpl(); diff --git a/datamgr_service/services/distributeddataservice/adapter/account/src/account_delegate_normal_impl.cpp b/datamgr_service/services/distributeddataservice/adapter/account/src/account_delegate_normal_impl.cpp index edc5a7a95a82e6afc44e29427c6f7d976caa4bdc..e59d08a22b9b51369673673cda2d2dd7f52a84c6 100644 --- a/datamgr_service/services/distributeddataservice/adapter/account/src/account_delegate_normal_impl.cpp +++ b/datamgr_service/services/distributeddataservice/adapter/account/src/account_delegate_normal_impl.cpp @@ -17,7 +17,6 @@ #include "account_delegate_normal_impl.h" #include #include -#include #include #include #include @@ -32,12 +31,7 @@ using namespace OHOS::EventFwk; using namespace OHOS::AAFwk; using namespace OHOS::DistributedData; using namespace Security::AccessToken; -AccountDelegate::BaseInstance AccountDelegate::getInstance_ = AccountDelegateNormalImpl::GetBaseInstance; -AccountDelegate *AccountDelegateNormalImpl::GetBaseInstance() -{ - static AccountDelegateNormalImpl accountDelegate; - return &accountDelegate; -} +__attribute__((used)) static bool g_isInit = AccountDelegateNormalImpl::Init(); std::string AccountDelegateNormalImpl::GetCurrentAccountId() const { @@ -216,7 +210,20 @@ std::string AccountDelegateNormalImpl::GetUnencryptedAccountId(int32_t userId) c bool AccountDelegateNormalImpl::QueryForegroundUserId(int &foregroundUserId) { - return AccountSA::OsAccountManager::GetForegroundOsAccountLocalId(foregroundUserId); + int32_t status = AccountSA::OsAccountManager::GetForegroundOsAccountLocalId(foregroundUserId); + if (status != ERR_OK) { + ZLOGE("GetForegroundOsAccountLocalId failed, status: %{public}d", status); + return false; + } + return true; +} + +bool AccountDelegateNormalImpl::Init() +{ + static AccountDelegateNormalImpl normalAccountDelegate; + static std::once_flag onceFlag; + std::call_once(onceFlag, [&]() { AccountDelegate::RegisterAccountInstance(&normalAccountDelegate); }); + return true; } -} // namespace DistributedKv +} // namespace DistributedKv } // namespace OHOS \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/adapter/account/src/account_delegate_normal_impl.h b/datamgr_service/services/distributeddataservice/adapter/account/src/account_delegate_normal_impl.h index 758e25d4178d5e0a71c7c4434e5507438611c0b8..63c86d66243187fbc4e176f30baf4204194033e7 100644 --- a/datamgr_service/services/distributeddataservice/adapter/account/src/account_delegate_normal_impl.h +++ b/datamgr_service/services/distributeddataservice/adapter/account/src/account_delegate_normal_impl.h @@ -26,7 +26,6 @@ namespace OHOS { namespace DistributedKv { class AccountDelegateNormalImpl final : public AccountDelegateImpl { public: - static AccountDelegate *GetBaseInstance(); std::string GetCurrentAccountId() const override; int32_t GetUserByToken(uint32_t tokenId) const override; bool QueryUsers(std::vector &users) override; @@ -38,6 +37,7 @@ public: void BindExecutor(std::shared_ptr executors) override; std::string GetUnencryptedAccountId(int32_t userId = 0) const override; bool QueryForegroundUserId(int &foregroundUserId) override; + static bool Init(); private: ~AccountDelegateNormalImpl(); diff --git a/datamgr_service/services/distributeddataservice/adapter/account/test/BUILD.gn b/datamgr_service/services/distributeddataservice/adapter/account/test/BUILD.gn index 1fb62f2e83fa3f2df1de64e589511b4810ffb1fe..3b3df7fe0223d123b0e44b0675d0973c7e385ae6 100644 --- a/datamgr_service/services/distributeddataservice/adapter/account/test/BUILD.gn +++ b/datamgr_service/services/distributeddataservice/adapter/account/test/BUILD.gn @@ -18,10 +18,13 @@ module_output_path = "datamgr_service/distributeddatafwk" ohos_unittest("AccountDelegateTest") { module_out_path = module_output_path - sources = [ "account_delegate_test.cpp" ] + sources = [ + "${data_service_path}/framework/account/account_delegate.cpp", + "account_delegate_test.cpp", + ] include_dirs = [ "//commonlibrary/c_utils/base/include", - "//foundation/distributeddatamgr/datamgr_service/services/distributeddataservice/adapter/include/account", + "${data_service_path}/framework/include/account", "//foundation/distributeddatamgr/kv_store/interfaces/innerkits/distributeddata/include", "//foundation/distributeddatamgr/datamgr_service/services/distributeddataservice/adapter/include/autils", "//foundation/distributeddatamgr/datamgr_service/services/distributeddataservice/adapter/include/utils", @@ -51,6 +54,13 @@ ohos_unittest("AccountDelegateTest") { "os_account:libaccountkits", "os_account:os_account_innerkits", ] + if (os_account_part_is_enabled) { + sources += [ "${data_service_path}/adapter/account/src/account_delegate_normal_impl.cpp" ] + cflags_cc = [ "-DOS_ACCOUNT_PART_IS_ENABLED" ] + external_deps += [ "access_token:libaccesstoken_sdk" ] + } else { + sources += [ "${data_service_path}/adapter/account/src/account_delegate_default_impl.cpp" ] + } defines = [ "OPENSSL_SUPPRESS_DEPRECATED" ] } diff --git a/datamgr_service/services/distributeddataservice/adapter/communicator/src/device_manager_adapter.cpp b/datamgr_service/services/distributeddataservice/adapter/communicator/src/device_manager_adapter.cpp index 1f9db2632ae357eb76c8f66c0fbe1dcf89356632..cd9f85c726f63758895f8fff8ef1d0d51de625f7 100644 --- a/datamgr_service/services/distributeddataservice/adapter/communicator/src/device_manager_adapter.cpp +++ b/datamgr_service/services/distributeddataservice/adapter/communicator/src/device_manager_adapter.cpp @@ -747,4 +747,14 @@ std::string DeviceManagerAdapter::GetEncryptedUuidByNetworkId(const std::string } return encryptedUuid; } + +bool DeviceManagerAdapter::IsSameAccount(const std::string &id) +{ + if (id.empty()) { + ZLOGE("params id is empty"); + return false; + } + auto networkId = DeviceManagerAdapter::GetInstance().ToNetworkID(id); + return DeviceManager::GetInstance().IsSameAccount(networkId); +} } // namespace OHOS::DistributedData diff --git a/datamgr_service/services/distributeddataservice/adapter/communicator/src/softbus_adapter.h b/datamgr_service/services/distributeddataservice/adapter/communicator/src/softbus_adapter.h index 3d1638982d936057e9a4e074e7724f116e3a0787..c1d5ffeaf11f492fe568288c348aae8141a813b5 100644 --- a/datamgr_service/services/distributeddataservice/adapter/communicator/src/softbus_adapter.h +++ b/datamgr_service/services/distributeddataservice/adapter/communicator/src/softbus_adapter.h @@ -91,6 +91,10 @@ private: std::string DelConnect(int32_t socket); void StartCloseSessionTask(const std::string &deviceId); Task GetCloseSessionTask(); + bool CloseSession(const std::string &networkId); + void Reuse(const PipeInfo &pipeInfo, const DeviceId &deviceId, + uint32_t qosType, std::shared_ptr &conn); + void GetExpireTime(std::shared_ptr &conn); static constexpr const char *PKG_NAME = "distributeddata-default"; static constexpr Time INVALID_NEXT = std::chrono::steady_clock::time_point::max(); static constexpr uint32_t QOS_COUNT = 3; diff --git a/datamgr_service/services/distributeddataservice/adapter/communicator/src/softbus_adapter_standard.cpp b/datamgr_service/services/distributeddataservice/adapter/communicator/src/softbus_adapter_standard.cpp index e5237c4a531be5a360fffcb76ed08b05ef459c5f..0827053dd03c0dc42fd3c579571769841d4a3cc0 100644 --- a/datamgr_service/services/distributeddataservice/adapter/communicator/src/softbus_adapter_standard.cpp +++ b/datamgr_service/services/distributeddataservice/adapter/communicator/src/softbus_adapter_standard.cpp @@ -17,6 +17,7 @@ #include #include "communicator_context.h" +#include "communication/connect_manager.h" #include "data_level.h" #include "device_manager_adapter.h" #include "dfx_types.h" @@ -108,6 +109,15 @@ SoftBusAdapter::SoftBusAdapter() Context::GetInstance().SetSessionListener([this](const std::string &deviceId) { StartCloseSessionTask(deviceId); }); + + ConnectManager::GetInstance()->RegisterCloseSessionTask([this](const std::string &networkId) { + return CloseSession(networkId); + }); + ConnectManager::GetInstance()->RegisterSessionCloseListener("context", [](const std::string &networkId) { + auto uuid = DmAdapter::GetInstance().GetUuidByNetworkId(networkId); + Context::GetInstance().NotifySessionClose(uuid); + }); + ConnectManager::GetInstance()->OnStart(); } SoftBusAdapter::~SoftBusAdapter() @@ -117,6 +127,7 @@ SoftBusAdapter::~SoftBusAdapter() UnregDataLevelChangeCb(PKG_NAME); } connects_.Clear(); + ConnectManager::GetInstance()->OnDestory(); } std::shared_ptr SoftBusAdapter::GetInstance() @@ -155,38 +166,77 @@ Status SoftBusAdapter::StopWatchDataChange(__attribute__((unused)) const AppData return Status::ERROR; } +void SoftBusAdapter::Reuse(const PipeInfo &pipeInfo, const DeviceId &deviceId, + uint32_t qosType, std::shared_ptr &conn) +{ + std::vector> connects; + auto connect = std::make_shared(pipeInfo, deviceId, qosType); + connect->isReuse = true; + connects.emplace_back(connect); + conn = connect; + connects_.Insert(deviceId.deviceId, connects); + ZLOGI("reuse connect:%{public}s", KvStoreUtils::ToBeAnonymous(deviceId.deviceId).c_str()); +} + +void SoftBusAdapter::GetExpireTime(std::shared_ptr &conn) +{ + Time now = std::chrono::steady_clock::now(); + auto expireTime = conn->GetExpireTime() > now ? conn->GetExpireTime() : now; + lock_guard lock(taskMutex_); + if (taskId_ != ExecutorPool::INVALID_TASK_ID && expireTime < next_) { + taskId_ = Context::GetInstance().GetThreadPool()->Reset(taskId_, expireTime - now); + next_ = expireTime; + } +} + Status SoftBusAdapter::SendData(const PipeInfo &pipeInfo, const DeviceId &deviceId, const DataInfo &dataInfo, uint32_t length, const MessageInfo &info) { std::shared_ptr conn; - bool isReady = DmAdapter::GetInstance().IsDeviceReady(deviceId.deviceId); - uint32_t qosType = isReady ? SoftBusClient::QOS_HML : SoftBusClient::QOS_BR; + bool isOHOSType = DmAdapter::GetInstance().IsOHOSType(deviceId.deviceId); + uint32_t qosType = isOHOSType ? SoftBusClient::QOS_HML : SoftBusClient::QOS_BR; + bool isReuse = false; connects_.Compute(deviceId.deviceId, - [&pipeInfo, &deviceId, &conn, qosType](const auto &key, + [&pipeInfo, &deviceId, &conn, qosType, isOHOSType, &isReuse](const auto &key, std::vector> &connects) -> bool { for (auto &connect : connects) { - if (connect->GetQoSType() == qosType) { - conn = connect; - return true; + if (connect->GetQoSType() != qosType) { + continue; + } + if (!isOHOSType && connect->needRemove) { + isReuse = true; + return false; } + conn = connect; + return true; } auto connect = std::make_shared(pipeInfo, deviceId, qosType); connects.emplace_back(connect); conn = connect; return true; }); + if (!isOHOSType && isReuse) { + Reuse(pipeInfo, deviceId, qosType, conn); + } if (conn == nullptr) { return Status::ERROR; } - auto status = conn->SendData(dataInfo, &clientListener_); + auto status = conn->CheckStatus(); + if (status == Status::RATE_LIMIT) { + return Status::RATE_LIMIT; + } + if (status != Status::SUCCESS) { + auto task = [this, conn]() { + conn->OpenConnect(&clientListener_); + }; + auto networkId = DmAdapter::GetInstance().GetDeviceInfo(deviceId.deviceId).networkId; + ConnectManager::GetInstance()->ApplyConnect(networkId, task); + return Status::RATE_LIMIT; + } + + status = conn->SendData(dataInfo, &clientListener_); if ((status != Status::NETWORK_ERROR) && (status != Status::RATE_LIMIT)) { - Time now = std::chrono::steady_clock::now(); - auto expireTime = conn->GetExpireTime() > now ? conn->GetExpireTime() : now; - lock_guard lock(taskMutex_); - if (taskId_ != ExecutorPool::INVALID_TASK_ID && expireTime < next_) { - taskId_ = Context::GetInstance().GetThreadPool()->Reset(taskId_, expireTime - now); - next_ = expireTime; - } + GetExpireTime(conn); } return status; } @@ -194,8 +244,8 @@ Status SoftBusAdapter::SendData(const PipeInfo &pipeInfo, const DeviceId &device void SoftBusAdapter::StartCloseSessionTask(const std::string &deviceId) { std::shared_ptr conn; - bool isReady = DmAdapter::GetInstance().IsDeviceReady(deviceId); - uint32_t qosType = isReady ? SoftBusClient::QOS_HML : SoftBusClient::QOS_BR; + bool isOHOSType = DmAdapter::GetInstance().IsOHOSType(deviceId); + uint32_t qosType = isOHOSType ? SoftBusClient::QOS_HML : SoftBusClient::QOS_BR; auto connects = connects_.Find(deviceId); if (!connects.first) { return; @@ -243,7 +293,7 @@ SoftBusAdapter::Task SoftBusAdapter::GetCloseSessionTask() }); connects_.EraseIf([](const auto &key, const auto &conn) -> bool { if (conn.empty()) { - Context::GetInstance().NotifySessionClose(key); + ConnectManager::GetInstance()->OnSessionClose(DmAdapter::GetInstance().GetDeviceInfo(key).networkId); } return conn.empty(); }); @@ -316,7 +366,8 @@ uint32_t SoftBusAdapter::GetTimeout(const DeviceId &deviceId) std::string SoftBusAdapter::DelConnect(int32_t socket) { std::string name; - connects_.ForEach([socket, &name](const auto &deviceId, auto &connects) -> bool { + std::set closedConnect; + connects_.EraseIf([socket, &name, &closedConnect](const auto &deviceId, auto &connects) -> bool { for (auto iter = connects.begin(); iter != connects.end();) { if (*iter != nullptr && **iter == socket) { name += deviceId; @@ -326,8 +377,16 @@ std::string SoftBusAdapter::DelConnect(int32_t socket) iter++; } } + if (connects.empty()) { + closedConnect.insert(deviceId); + return true; + } return false; }); + for (const auto &deviceId : closedConnect) { + auto networkId = DmAdapter::GetInstance().GetDeviceInfo(deviceId).networkId; + ConnectManager::GetInstance()->OnSessionClose(networkId); + } return name; } @@ -506,6 +565,18 @@ void SoftBusAdapter::OnBind(int32_t socket, PeerSocketInfo info) socketInfo.networkId = info.networkId; socketInfo.pkgName = info.pkgName; peerSocketInfos_.Insert(socket, socketInfo); + if (!DmAdapter::GetInstance().IsOHOSType(info.networkId)) { + auto uuid = DmAdapter::GetInstance().ToUUID(info.networkId); + auto connects = connects_.Find(uuid); + if (!connects.first) { + return; + } + for (auto &conn : connects.second) { + if (!conn->isReuse) { + conn->needRemove = true; + } + } + } } void SoftBusAdapter::OnServerShutdown(int32_t socket) @@ -518,5 +589,15 @@ void SoftBusAdapter::OnDeviceChanged(const AppDistributedKv::DeviceInfo &info, { return; } + +bool SoftBusAdapter::CloseSession(const std::string &networkId) +{ + auto uuid = DmAdapter::GetInstance().GetUuidByNetworkId(networkId); + auto ret = connects_.Erase(uuid); + if (ret != 0) { + ConnectManager::GetInstance()->OnSessionClose(networkId); + } + return ret != 0; +} } // namespace AppDistributedKv } // namespace OHOS \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/adapter/communicator/src/softbus_client.cpp b/datamgr_service/services/distributeddataservice/adapter/communicator/src/softbus_client.cpp index f46d4e0d9d89b28ee7ffb3da675bad367320e745..304b8cd204974fd2da2bac1368c6ea046a50660c 100644 --- a/datamgr_service/services/distributeddataservice/adapter/communicator/src/softbus_client.cpp +++ b/datamgr_service/services/distributeddataservice/adapter/communicator/src/softbus_client.cpp @@ -17,6 +17,7 @@ #include "softbus_client.h" #include "communicator_context.h" +#include "communication/connect_manager.h" #include "device_manager_adapter.h" #include "inner_socket.h" #include "kvstore_utils.h" @@ -64,7 +65,7 @@ uint32_t SoftBusClient::GetTimeout() const Status SoftBusClient::SendData(const DataInfo &dataInfo, const ISocketListener *listener) { std::lock_guard lock(mutex_); - auto result = OpenConnect(listener); + auto result = CheckStatus(); if (result != Status::SUCCESS) { return result; } @@ -81,15 +82,14 @@ Status SoftBusClient::SendData(const DataInfo &dataInfo, const ISocketListener * Status SoftBusClient::OpenConnect(const ISocketListener *listener) { - if (bindState_ == 0) { - return Status ::SUCCESS; + std::lock_guard lock(mutex_); + auto status = CheckStatus(); + if (status == Status::SUCCESS || status == Status::RATE_LIMIT) { + return status; } if (isOpening_.exchange(true)) { return Status::RATE_LIMIT; } - if (bindState_ == 0) { - return Status ::SUCCESS; - } SocketInfo socketInfo; std::string peerName = pipe_.pipeId; socketInfo.peerName = const_cast(peerName.c_str()); @@ -122,6 +122,20 @@ Status SoftBusClient::OpenConnect(const ISocketListener *listener) return Status::RATE_LIMIT; } +Status SoftBusClient::CheckStatus() +{ + if (bindState_ == 0) { + return Status::SUCCESS; + } + if (isOpening_.load()) { + return Status::RATE_LIMIT; + } + if (bindState_ == 0) { + return Status::SUCCESS; + } + return Status::ERROR; +} + Status SoftBusClient::Open(int32_t socket, const QosTV qos[], const ISocketListener *listener) { int32_t status = ::Bind(socket, qos, QOS_COUNT, listener); @@ -149,6 +163,7 @@ Status SoftBusClient::Open(int32_t socket, const QosTV qos[], const ISocketListe } ZLOGI("open %{public}s, session:%{public}s success, socket:%{public}d", KvStoreUtils::ToBeAnonymous(device_.deviceId).c_str(), pipe_.pipeId.c_str(), socket_); + ConnectManager::GetInstance()->OnSessionOpen(DmAdapter::GetInstance().GetDeviceInfo(device_.deviceId).networkId); return Status::SUCCESS; } diff --git a/datamgr_service/services/distributeddataservice/adapter/communicator/src/softbus_client.h b/datamgr_service/services/distributeddataservice/adapter/communicator/src/softbus_client.h index b20cf012d05ac8a873192fcb7a7d6fba6bcc8966..898a7ada78d279c172d443f218311f9b666a0477 100644 --- a/datamgr_service/services/distributeddataservice/adapter/communicator/src/softbus_client.h +++ b/datamgr_service/services/distributeddataservice/adapter/communicator/src/softbus_client.h @@ -37,6 +37,8 @@ public: using Time = std::chrono::steady_clock::time_point; using Duration = std::chrono::steady_clock::duration; + Status CheckStatus(); + Status OpenConnect(const ISocketListener *listener); Status SendData(const DataInfo &dataInfo, const ISocketListener *listener); bool operator==(int32_t socket) const; bool operator==(const std::string &deviceId) const; @@ -46,9 +48,10 @@ public: int32_t GetSocket() const; uint32_t GetQoSType() const; void UpdateExpireTime(); + bool needRemove = false; + bool isReuse = false; private: - Status OpenConnect(const ISocketListener *listener); Status Open(int32_t socket, const QosTV qos[], const ISocketListener *listener); std::pair GetMtu(int32_t socket); Time CalcExpireTime() const; diff --git a/datamgr_service/services/distributeddataservice/adapter/communicator/test/fuzztest/softbusadapter_fuzzer/BUILD.gn b/datamgr_service/services/distributeddataservice/adapter/communicator/test/fuzztest/softbusadapter_fuzzer/BUILD.gn index a7c54aff81950fd9b817d994d126740b98060939..3ee6efe2e6612b7a1f2bf07d736ce21f5c7efb9b 100644 --- a/datamgr_service/services/distributeddataservice/adapter/communicator/test/fuzztest/softbusadapter_fuzzer/BUILD.gn +++ b/datamgr_service/services/distributeddataservice/adapter/communicator/test/fuzztest/softbusadapter_fuzzer/BUILD.gn @@ -26,6 +26,7 @@ ohos_fuzztest("SoftBusAdapterFuzzTest") { "${data_service_path}/adapter/include/autils", "${data_service_path}/adapter/include/utils", "${data_service_path}/adapter/communicator/src", + "${data_service_path}/framework/include", "${dsoftbus_core_path}", "${kv_store_common_path}", "${kv_store_distributeddb_path}/interfaces/include", diff --git a/datamgr_service/services/distributeddataservice/adapter/communicator/test/unittest/softbus_adapter_standard_test.cpp b/datamgr_service/services/distributeddataservice/adapter/communicator/test/unittest/softbus_adapter_standard_test.cpp index d0c91821c843c44a00eb7cabab15b51e0d2290d8..9804ce14f625c7850cf3eb85088e90ab4dd4bb19 100644 --- a/datamgr_service/services/distributeddataservice/adapter/communicator/test/unittest/softbus_adapter_standard_test.cpp +++ b/datamgr_service/services/distributeddataservice/adapter/communicator/test/unittest/softbus_adapter_standard_test.cpp @@ -19,7 +19,6 @@ #include "gtest/gtest.h" #include #include "log_print.h" -#define private public #include "softbus_adapter.h" #include "types.h" #include diff --git a/datamgr_service/services/distributeddataservice/adapter/dfx/src/radar_reporter.cpp b/datamgr_service/services/distributeddataservice/adapter/dfx/src/radar_reporter.cpp index 56048427b341ad1dd2e48b68db4f980a1f5b0f92..0a22c8f60eaced073e65f35d05dc9c35e68bbfcd 100644 --- a/datamgr_service/services/distributeddataservice/adapter/dfx/src/radar_reporter.cpp +++ b/datamgr_service/services/distributeddataservice/adapter/dfx/src/radar_reporter.cpp @@ -49,14 +49,14 @@ void RadarReporter::Report(const RadarParam ¶m, const char *funcName, int32_ BIZ_SCENE_LABEL, param.scene_, BIZ_STAGE_LABEL, param.stage_, BIZ_STATE_LABEL, state, STAGE_RES_LABEL, res, ERROR_CODE_LABEL, param.errCode_, HOST_PKG, param.bundleName_, LOCAL_UUID_LABEL, AnonymousUuid(DmAdapter::GetInstance().GetLocalDevice().uuid), CONCURRENT_ID, - std::to_string(param.syncId_)); + std::to_string(param.syncId_), TRIGGER_MODE, param.triggerMode_, WATER_VERSION, param.changeCount); } else { HiSysEventWrite(OHOS::HiviewDFX::HiSysEvent::Domain::DISTRIBUTED_DATAMGR, eventName, OHOS::HiviewDFX::HiSysEvent::EventType::BEHAVIOR, ORG_PKG_LABEL, ORG_PKG, FUNC_LABEL, funcName, BIZ_SCENE_LABEL, param.scene_, BIZ_STAGE_LABEL, param.stage_, STAGE_RES_LABEL, res, ERROR_CODE_LABEL, param.errCode_, HOST_PKG, param.bundleName_, LOCAL_UUID_LABEL, AnonymousUuid(DmAdapter::GetInstance().GetLocalDevice().uuid), CONCURRENT_ID, - std::to_string(param.syncId_)); + std::to_string(param.syncId_), TRIGGER_MODE, param.triggerMode_, WATER_VERSION, param.changeCount); } return; } diff --git a/datamgr_service/services/distributeddataservice/adapter/include/communicator/device_manager_adapter.h b/datamgr_service/services/distributeddataservice/adapter/include/communicator/device_manager_adapter.h index f02d2891caf592c5e04fc17b1e97f9775a912374..7c99f1fb99f8faed188f1b381f504d22f29e7917 100644 --- a/datamgr_service/services/distributeddataservice/adapter/include/communicator/device_manager_adapter.h +++ b/datamgr_service/services/distributeddataservice/adapter/include/communicator/device_manager_adapter.h @@ -77,6 +77,7 @@ public: bool IsNetworkAvailable(); NetworkType GetNetworkType(bool retrieve = false); int32_t GetAuthType(const std::string& id); + bool IsSameAccount(const std::string &id); friend class DataMgrDmStateCall; friend class NetConnCallbackObserver; diff --git a/datamgr_service/services/distributeddataservice/adapter/include/dfx/radar_reporter.h b/datamgr_service/services/distributeddataservice/adapter/include/dfx/radar_reporter.h index 72a6752bb0fd38b6d76b99b1b8a8fec3dca48d9b..7a60cc064c10ea002fca58f968477249b0e74e31 100644 --- a/datamgr_service/services/distributeddataservice/adapter/include/dfx/radar_reporter.h +++ b/datamgr_service/services/distributeddataservice/adapter/include/dfx/radar_reporter.h @@ -70,6 +70,8 @@ struct RadarParam { int32_t scene_ = CLOUD_SYNC; int32_t stage_ = GENERAL_STAGE; uint64_t syncId_ = 0; + int32_t triggerMode_ = 0; + uint64_t changeCount = 0; int32_t errCode_ = 0; int32_t res_ = RES_SUCCESS; }; @@ -102,6 +104,8 @@ private: static constexpr const char *REPLACE_CHAIN = "**"; static constexpr const char *DEFAULT_ANONYMOUS = "************"; static constexpr const char *CONCURRENT_ID = "CONCURRENT_ID"; + static constexpr const char *TRIGGER_MODE = "TRIGGER_MODE"; + static constexpr const char *WATER_VERSION = "WATER_VERSION"; static constexpr const int32_t NO_ERROR = 0; static constexpr const int32_t HEAD_SIZE = 5; static constexpr const int32_t END_SIZE = 5; diff --git a/datamgr_service/services/distributeddataservice/adapter/include/screenlock/screen_lock.h b/datamgr_service/services/distributeddataservice/adapter/include/screenlock/screen_lock.h new file mode 100644 index 0000000000000000000000000000000000000000..db40555e3d797bac5d535b459933060907d7274d --- /dev/null +++ b/datamgr_service/services/distributeddataservice/adapter/include/screenlock/screen_lock.h @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef DISTRIBUTEDDATAMGR_ADAPTER_SCREEN_LOCK_H +#define DISTRIBUTEDDATAMGR_ADAPTER_SCREEN_LOCK_H + +#include "visibility.h" +#include "screen/screen_manager.h" + +namespace OHOS { +namespace DistributedData { +class ScreenLock : public ScreenManager { +public: + API_EXPORT bool IsLocked(); +}; +} // namespace DistributedData +} // namespace OHOS +#endif //DISTRIBUTEDDATAMGR_ADAPTER_SCREEN_LOCK_H diff --git a/datamgr_service/services/distributeddataservice/adapter/include/utils/visibility.h b/datamgr_service/services/distributeddataservice/adapter/include/utils/visibility.h new file mode 100644 index 0000000000000000000000000000000000000000..a5aec5485e6debf4dbf3ac16e84b701785f638f9 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/adapter/include/utils/visibility.h @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_DISTRIBUTED_DATA_FRAMEWORKS_COMMON_VISIBILITY_H +#define OHOS_DISTRIBUTED_DATA_FRAMEWORKS_COMMON_VISIBILITY_H + +#ifndef API_EXPORT +#define API_EXPORT __attribute__((visibility ("default"))) +#endif +#ifndef API_LOCAL +#define API_LOCAL __attribute__((visibility ("hidden"))) +#endif +#ifndef KVSTORE_API +#define KVSTORE_API API_EXPORT +#endif + +#endif // OHOS_DISTRIBUTED_DATA_FRAMEWORKS_COMMON_VISIBILITY_H diff --git a/datamgr_service/services/distributeddataservice/adapter/screenlock/BUILD.gn b/datamgr_service/services/distributeddataservice/adapter/screenlock/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..cb30d1da49819d8bc735ede6017e23100b23ca80 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/adapter/screenlock/BUILD.gn @@ -0,0 +1,42 @@ +# Copyright (c) 2024 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +import("//build/ohos.gni") +import("//foundation/distributeddatamgr/datamgr_service/datamgr_service.gni") + +ohos_static_library("distributeddata_screenlock_static") { + branch_protector_ret = "pac_ret" + sanitize = { + cfi = true + cfi_cross_dso = true + debug = false + boundary_sanitize = true + ubsan = true + } + sources = [ "src/screen_lock.cpp" ] + + cflags_cc = [ "-fvisibility=hidden" ] + + include_dirs = [ + "../include/screenlock", + "../include/utils", + "${data_service_path}/framework/include", + ] + + external_deps = [ + "c_utils:utils", + "screenlock_mgr:screenlock_client", + ] + subsystem_name = "distributeddatamgr" + part_name = "datamgr_service" + defines = [ "OPENSSL_SUPPRESS_DEPRECATED" ] +} diff --git a/datamgr_service/services/distributeddataservice/adapter/screenlock/src/screen_lock.cpp b/datamgr_service/services/distributeddataservice/adapter/screenlock/src/screen_lock.cpp new file mode 100644 index 0000000000000000000000000000000000000000..92e9118ee4ac025af25086638757439532651ad9 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/adapter/screenlock/src/screen_lock.cpp @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "screen_lock.h" +#include "screenlock_manager.h" + +namespace OHOS::DistributedData { +using namespace OHOS::ScreenLock; +__attribute__((used)) static bool g_init = + ScreenManager::RegisterInstance(std::static_pointer_cast(std::make_shared())); +bool ScreenLock::IsLocked() +{ + auto manager = ScreenLockManager::GetInstance(); + if (manager == nullptr) { + return false; + } + return manager->IsScreenLocked(); +} +} // namespace OHOS::DistributedData \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/app/BUILD.gn b/datamgr_service/services/distributeddataservice/app/BUILD.gn index cc59341fc4437a88df48cabd6e25960c1666013f..fd6efcbc4db415376a48c1f74cc9e0ca332547c7 100644 --- a/datamgr_service/services/distributeddataservice/app/BUILD.gn +++ b/datamgr_service/services/distributeddataservice/app/BUILD.gn @@ -58,6 +58,7 @@ config("module_private_config") { "${data_service_path}/service/permission/include", "${data_service_path}/service/matrix/include", "${data_service_path}/service/backup/include", + "${data_service_path}/service/app_id_mapping/include", "${data_service_path}/service/kvdb", "${data_service_path}/service/waterversion", "${data_service_path}/service/dumper/include", diff --git a/datamgr_service/services/distributeddataservice/app/distributed_data.cfg b/datamgr_service/services/distributeddataservice/app/distributed_data.cfg index a9e48f7b498d4e214577dbbacc4fae5396c97c6d..b4b210b2cdad4f26204c34495a716365a1de0410 100644 --- a/datamgr_service/services/distributeddataservice/app/distributed_data.cfg +++ b/datamgr_service/services/distributeddataservice/app/distributed_data.cfg @@ -17,7 +17,7 @@ "name" : "distributeddata", "path" : ["/system/bin/sa_main","/system/profile/distributeddata.json"], "uid" : "ddms", - "gid" : ["system","shell","readproc","ddms","dfs_share","netsys_socket"], + "gid" : ["system","shell","readproc","ddms","dfs_share","netsys_socket","data_reserve"], "writepid":[ "/dev/cpuset/foreground/tasks", "/dev/stune/foreground/tasks", @@ -38,7 +38,6 @@ "ohos.permission.PUBLISH_SYSTEM_COMMON_EVENT", "ohos.permission.GET_BUNDLE_INFO", "ohos.permission.GET_NETWORK_INFO", - "ohos.permission.INTERNET", "ohos.permission.DISTRIBUTED_SOFTBUS_CENTER", "ohos.permission.MONITOR_DEVICE_NETWORK_STATE", "ohos.permission.USE_CLOUD_DRIVE_SERVICE", diff --git a/datamgr_service/services/distributeddataservice/app/src/installer/installer_impl.cpp b/datamgr_service/services/distributeddataservice/app/src/installer/installer_impl.cpp index 0ec512f6fe1dd46a6381d4e4a726147de17fb957..628329961c9400a105bb11065b57e1b827e09646 100644 --- a/datamgr_service/services/distributeddataservice/app/src/installer/installer_impl.cpp +++ b/datamgr_service/services/distributeddataservice/app/src/installer/installer_impl.cpp @@ -60,10 +60,6 @@ void InstallEventSubscriber::OnReceiveEvent(const CommonEventData &event) int32_t appIndex = want.GetIntParam(SANDBOX_APP_INDEX, 0); ZLOGI("bundleName:%{public}s, user:%{public}d, appIndex:%{public}d", bundleName.c_str(), userId, appIndex); (this->*(it->second))(bundleName, userId, appIndex); - } else if (action == CommonEventSupport::COMMON_EVENT_SCREEN_UNLOCKED) { - int32_t userId = want.GetIntParam(USER_ID, -1); - ZLOGI("user:%{public}d ScreenUnlocked", userId); - OnScreenUnlocked(userId); } } @@ -119,11 +115,6 @@ void InstallEventSubscriber::OnInstall(const std::string &bundleName, int32_t us kvStoreDataService_->OnInstall(bundleName, userId, appIndex); } -void InstallEventSubscriber::OnScreenUnlocked(int32_t userId) -{ - kvStoreDataService_->OnScreenUnlocked(userId); -} - InstallerImpl::~InstallerImpl() { ZLOGD("destruct"); @@ -153,7 +144,6 @@ Status InstallerImpl::Init(KvStoreDataService *kvStoreDataService, std::shared_p matchingSkills.AddEvent(CommonEventSupport::COMMON_EVENT_PACKAGE_CHANGED); matchingSkills.AddEvent(CommonEventSupport::COMMON_EVENT_PACKAGE_ADDED); matchingSkills.AddEvent(OHOS::AppExecFwk::COMMON_EVENT_SANDBOX_PACKAGE_ADDED); - matchingSkills.AddEvent(CommonEventSupport::COMMON_EVENT_SCREEN_UNLOCKED); CommonEventSubscribeInfo info(matchingSkills); auto subscriber = std::make_shared(info, kvStoreDataService); diff --git a/datamgr_service/services/distributeddataservice/app/src/installer/installer_impl.h b/datamgr_service/services/distributeddataservice/app/src/installer/installer_impl.h index aabcd933ec4039e4ac95513f34c4213f0d3bdb55..683ae72999006e46b2217958bcde2b610796eecf 100644 --- a/datamgr_service/services/distributeddataservice/app/src/installer/installer_impl.h +++ b/datamgr_service/services/distributeddataservice/app/src/installer/installer_impl.h @@ -36,7 +36,6 @@ private: void OnUninstall(const std::string &bundleName, int32_t userId, int32_t appIndex); void OnUpdate(const std::string &bundleName, int32_t userId, int32_t appIndex); void OnInstall(const std::string &bundleName, int32_t userId, int32_t appIndex); - void OnScreenUnlocked(int32_t userId); std::map callbacks_; KvStoreDataService *kvStoreDataService_; }; diff --git a/datamgr_service/services/distributeddataservice/app/src/kvstore_data_service.cpp b/datamgr_service/services/distributeddataservice/app/src/kvstore_data_service.cpp index 94d55d6c62424f2e13d66400a430959e5044a75f..ecc50daad3474156dfd213a41e56efaf5f4315d6 100644 --- a/datamgr_service/services/distributeddataservice/app/src/kvstore_data_service.cpp +++ b/datamgr_service/services/distributeddataservice/app/src/kvstore_data_service.cpp @@ -23,7 +23,6 @@ #include "accesstoken_kit.h" #include "auth_delegate.h" #include "auto_launch_export.h" -#include "auto_sync_matrix.h" #include "bootstrap.h" #include "checker/checker_manager.h" #include "communication_provider.h" @@ -63,6 +62,7 @@ #include "utils/block_integer.h" #include "utils/crypto.h" #include "water_version_manager.h" +#include "app_id_mapping/app_id_mapping_config_manager.h" namespace OHOS::DistributedKv { using namespace std::chrono; @@ -76,6 +76,8 @@ using DBConfig = DistributedDB::RuntimeConfig; REGISTER_SYSTEM_ABILITY_BY_ID(KvStoreDataService, DISTRIBUTED_KV_DATA_SERVICE_ABILITY_ID, true); +constexpr char FOUNDATION_PROCESS_NAME[] = "foundation"; + KvStoreDataService::KvStoreDataService(bool runOnCreate) : SystemAbility(runOnCreate), clients_() { @@ -200,26 +202,14 @@ Status KvStoreDataService::RegisterClientDeathObserver(const AppId &appId, sptr< ZLOGW("check bundleName:%{public}s uid:%{public}d failed.", appId.appId.c_str(), info.uid); return Status::PERMISSION_DENIED; } - KvStoreClientDeathObserverImpl kvStoreClientDeathObserver(*this); - auto inserted = clients_.Emplace( - [&info, &appId, &kvStoreClientDeathObserver](decltype(clients_)::map_type &entries) { - auto it = entries.find(info.tokenId); - if (it == entries.end()) { - return true; - } - if (IPCSkeleton::GetCallingPid() == it->second.GetPid()) { - ZLOGW("bundleName:%{public}s, uid:%{public}d, pid:%{public}d has already registered.", - appId.appId.c_str(), info.uid, IPCSkeleton::GetCallingPid()); - return false; - } - kvStoreClientDeathObserver = std::move(it->second); - entries.erase(it); - return true; - }, - std::piecewise_construct, std::forward_as_tuple(info.tokenId), - std::forward_as_tuple(appId, *this, std::move(observer))); - ZLOGI("bundleName:%{public}s, uid:%{public}d, pid:%{public}d, inserted:%{public}s.", appId.appId.c_str(), info.uid, - IPCSkeleton::GetCallingPid(), inserted ? "success" : "failed"); + auto pid = IPCSkeleton::GetCallingPid(); + clients_.Compute( + info.tokenId, [&appId, &info, pid, this, obs = std::move(observer)](const auto tokenId, auto &clients) { + auto res = clients.try_emplace(pid, appId, *this, std::move(obs)); + ZLOGI("bundleName:%{public}s, uid:%{public}d, pid:%{public}d, inserted:%{public}s.", appId.appId.c_str(), + info.uid, pid, res.second ? "success" : "failed"); + return !clients.empty(); + }); return Status::SUCCESS; } @@ -230,9 +220,14 @@ Status KvStoreDataService::AppExit(pid_t uid, pid_t pid, uint32_t token, const A // clientDeathObserverMap_ erase, so we have to take a copy if we want to use this parameter after erase operation. AppId appIdTmp = appId; KvStoreClientDeathObserverImpl impl(*this); - clients_.ComputeIfPresent(token, [&impl](auto &, auto &value) { - impl = std::move(value); - return false; + clients_.ComputeIfPresent(token, [&impl, pid](auto &, auto &value) { + auto it = value.find(pid); + if (it == value.end()) { + return !value.empty(); + } + impl = std::move(it->second); + value.erase(it); + return !value.empty(); }); return Status::SUCCESS; } @@ -281,12 +276,7 @@ void KvStoreDataService::OnStart() ZLOGW("GetLocalDeviceId failed, retry count:%{public}d", static_cast(retry)); } ZLOGI("Bootstrap configs and plugins."); - Bootstrap::GetInstance().LoadComponents(); - Bootstrap::GetInstance().LoadDirectory(); - Bootstrap::GetInstance().LoadCheckers(); - Bootstrap::GetInstance().LoadNetworks(); - Bootstrap::GetInstance().LoadBackup(executors_); - Bootstrap::GetInstance().LoadCloud(); + LoadConfigs(); Initialize(); auto samgr = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager(); if (samgr != nullptr) { @@ -315,6 +305,17 @@ void KvStoreDataService::OnStart() StartService(); } +void KvStoreDataService::LoadConfigs() +{ + Bootstrap::GetInstance().LoadComponents(); + Bootstrap::GetInstance().LoadDirectory(); + Bootstrap::GetInstance().LoadCheckers(); + Bootstrap::GetInstance().LoadNetworks(); + Bootstrap::GetInstance().LoadBackup(executors_); + Bootstrap::GetInstance().LoadCloud(); + Bootstrap::GetInstance().LoadAppIdMappings(); +} + void KvStoreDataService::OnAddSystemAbility(int32_t systemAbilityId, const std::string &deviceId) { ZLOGI("add system abilityid:%{public}d", systemAbilityId); @@ -346,7 +347,6 @@ void KvStoreDataService::StartService() ZLOGI("begin."); KvStoreMetaManager::GetInstance().InitMetaListener(); DeviceMatrix::GetInstance().Initialize(IPCSkeleton::GetCallingTokenID(), Bootstrap::GetInstance().GetMetaDBName()); - AutoSyncMatrix::GetInstance().Initialize(); WaterVersionManager::GetInstance().Init(); LoadFeatures(); bool ret = SystemAbility::Publish(this); @@ -396,6 +396,25 @@ void KvStoreDataService::OnStoreMetaChanged( ZLOGI("dirty kv store. storeId:%{public}s", Anonymous::Change(metaData.storeId).c_str()); } +bool KvStoreDataService::CompareTripleIdentifier(const std::string &accountId, const std::string &identifier, + const StoreMetaData &storeMeta) +{ + std::vector accountIds { accountId, "ohosAnonymousUid", "default" }; + for (auto &id : accountIds) { + auto convertedIds = + AppIdMappingConfigManager::GetInstance().Convert(storeMeta.appId, storeMeta.user); + const std::string &tempTripleIdentifier = + DistributedDB::KvStoreDelegateManager::GetKvStoreIdentifier(id, convertedIds.first, + storeMeta.storeId, false); + if (tempTripleIdentifier == identifier) { + ZLOGI("find triple identifier,storeId:%{public}s,id:%{public}s", + Anonymous::Change(storeMeta.storeId).c_str(), Anonymous::Change(id).c_str()); + return true; + } + } + return false; +} + bool KvStoreDataService::ResolveAutoLaunchParamByIdentifier( const std::string &identifier, DistributedDB::AutoLaunchParam ¶m) { @@ -414,15 +433,13 @@ bool KvStoreDataService::ResolveAutoLaunchParamByIdentifier( // judge local userid and local meta continue; } - const std::string &itemTripleIdentifier = - DistributedDB::KvStoreDelegateManager::GetKvStoreIdentifier(accountId, storeMeta.appId, - storeMeta.storeId, false); + bool isTripleIdentifierEqual = CompareTripleIdentifier(accountId, identifier, storeMeta); const std::string &itemDualIdentifier = DistributedDB::KvStoreDelegateManager::GetKvStoreIdentifier("", storeMeta.appId, storeMeta.storeId, true); - if (identifier == itemTripleIdentifier && storeMeta.bundleName != Bootstrap::GetInstance().GetProcessLabel()) { + if (isTripleIdentifierEqual && storeMeta.bundleName != Bootstrap::GetInstance().GetProcessLabel()) { ResolveAutoLaunchCompatible(storeMeta, identifier, accountId); } - if (identifier == itemDualIdentifier || identifier == itemTripleIdentifier) { + if (identifier == itemDualIdentifier || isTripleIdentifierEqual) { ZLOGI("identifier find"); DistributedDB::AutoLaunchOption option; option.createIfNecessary = false; @@ -709,7 +726,8 @@ void KvStoreDataService::InitSecurityAdapter(std::shared_ptr execu ZLOGE("security is nullptr."); return; } - + + security_->InitLocalSecurity(); auto dbStatus = DistributedDB::RuntimeConfig::SetProcessSystemAPIAdapter(security_); ZLOGD("set distributed db system api adapter: %d.", static_cast(dbStatus)); @@ -809,10 +827,10 @@ int32_t KvStoreDataService::OnScreenUnlocked(int32_t user) int32_t KvStoreDataService::ClearAppStorage(const std::string &bundleName, int32_t userId, int32_t appIndex, int32_t tokenId) { - HapTokenInfo hapTokenInfo; - if (AccessTokenKit::GetHapTokenInfo(tokenId, hapTokenInfo) != RET_SUCCESS || - hapTokenInfo.bundleName != bundleName || hapTokenInfo.userID != userId || - hapTokenInfo.instIndex != appIndex) { + auto callerToken = IPCSkeleton::GetCallingTokenID(); + NativeTokenInfo nativeTokenInfo; + if (AccessTokenKit::GetNativeTokenInfo(callerToken, nativeTokenInfo) != RET_SUCCESS || + nativeTokenInfo.processName != FOUNDATION_PROCESS_NAME) { ZLOGE("passed wrong, tokenId: %{public}u, bundleName:%{public}s, user:%{public}d, appIndex:%{public}d", tokenId, bundleName.c_str(), userId, appIndex); return ERROR; diff --git a/datamgr_service/services/distributeddataservice/app/src/kvstore_data_service.h b/datamgr_service/services/distributeddataservice/app/src/kvstore_data_service.h index ae5b3b1c45d942337925c08950bb835382da4c7b..53a02afe2fd3d2026bafe15770d4d78b852afae2 100644 --- a/datamgr_service/services/distributeddataservice/app/src/kvstore_data_service.h +++ b/datamgr_service/services/distributeddataservice/app/src/kvstore_data_service.h @@ -169,13 +169,18 @@ private: bool ResolveAutoLaunchParamByIdentifier(const std::string &identifier, DistributedDB::AutoLaunchParam ¶m); void ResolveAutoLaunchCompatible(const StoreMetaData &storeMeta, const std::string &identifier, const std::string &accountId); + + void LoadConfigs(); + + bool CompareTripleIdentifier(const std::string &accountId, const std::string &identifier, + const StoreMetaData &storeMeta); static DistributedDB::SecurityOption ConvertSecurity(int securityLevel); static Status InitNbDbOption(const Options &options, const std::vector &cipherKey, DistributedDB::KvStoreNbDelegate::Option &dbOption); static constexpr int TEN_SEC = 10; - ConcurrentMap clients_; + ConcurrentMap> clients_; std::shared_ptr accountEventObserver_; std::shared_ptr security_; diff --git a/datamgr_service/services/distributeddataservice/app/src/security/security.cpp b/datamgr_service/services/distributeddataservice/app/src/security/security.cpp index b3cceb7176e9b7f7aa1d36087a88bc3a39e84120..ca7c97203742130e1ad017fcfe5c5eea3a80b180 100644 --- a/datamgr_service/services/distributeddataservice/app/src/security/security.cpp +++ b/datamgr_service/services/distributeddataservice/app/src/security/security.cpp @@ -165,6 +165,12 @@ bool Security::IsExits(const std::string &file) const return access(file.c_str(), F_OK) == 0; } +void Security::InitLocalSecurity() +{ + auto devInfo = DistributedData::DeviceManagerAdapter::GetInstance().GetLocalDevice(); + GetSensitiveByUuid(devInfo.uuid); +} + Sensitive Security::GetSensitiveByUuid(const std::string &uuid) const { auto it = devicesUdid_.Find(uuid); diff --git a/datamgr_service/services/distributeddataservice/app/src/security/security.h b/datamgr_service/services/distributeddataservice/app/src/security/security.h index 702f2af2c3217aed9c26f9354bc83a6076aa4777..bfa2a5415f53ef3aef0f784b3b6b4d424e33bb0d 100644 --- a/datamgr_service/services/distributeddataservice/app/src/security/security.h +++ b/datamgr_service/services/distributeddataservice/app/src/security/security.h @@ -58,6 +58,8 @@ public: AppDistributedKv::ChangeLevelType GetChangeLevelType() const override; + void InitLocalSecurity(); + private: enum { NO_PWD = -1, diff --git a/datamgr_service/services/distributeddataservice/app/src/session_manager/route_head_handler_impl.cpp b/datamgr_service/services/distributeddataservice/app/src/session_manager/route_head_handler_impl.cpp index 5d5dc15e4ccad8a9b7f9917bc1888c35b0b53373..318891be635eff9971a2678be69876f4f7e6deee 100644 --- a/datamgr_service/services/distributeddataservice/app/src/session_manager/route_head_handler_impl.cpp +++ b/datamgr_service/services/distributeddataservice/app/src/session_manager/route_head_handler_impl.cpp @@ -34,6 +34,7 @@ using namespace OHOS::DistributedKv; using namespace std::chrono; using DmAdapter = DistributedData::DeviceManagerAdapter; constexpr const int ALIGN_WIDTH = 8; +constexpr const char *DEFAULT_USERID = "0"; std::shared_ptr RouteHeadHandlerImpl::Create(const ExtendInfo &info) { auto handler = std::make_shared(info); @@ -58,6 +59,9 @@ void RouteHeadHandlerImpl::Init() if (deviceId_.empty()) { return; } + if (!DmAdapter::GetInstance().IsOHOSType(deviceId_) && userId_ != DEFAULT_USERID) { + userId_ = DEFAULT_USERID; + } SessionPoint localPoint { DmAdapter::GetInstance().GetLocalDevice().uuid, static_cast(atoi(userId_.c_str())), appId_, storeId_ }; session_ = SessionManager::GetInstance().GetSession(localPoint, deviceId_); diff --git a/datamgr_service/services/distributeddataservice/app/src/session_manager/session_manager.cpp b/datamgr_service/services/distributeddataservice/app/src/session_manager/session_manager.cpp index 271c1d8cbd64032b9c60611ada646bacede540e7..d46217a47b5211f88a7507c2285553ae4fa287d8 100644 --- a/datamgr_service/services/distributeddataservice/app/src/session_manager/session_manager.cpp +++ b/datamgr_service/services/distributeddataservice/app/src/session_manager/session_manager.cpp @@ -27,7 +27,7 @@ #include "user_delegate.h" #include "utils/anonymous.h" #include "utils/converter.h" - +#include "types.h" namespace OHOS::DistributedData { using namespace OHOS::DistributedKv; SessionManager &SessionManager::GetInstance() @@ -57,9 +57,17 @@ Session SessionManager::GetSession(const SessionPoint &from, const std::string & session.targetUserIds.push_back(UserDelegate::SYSTEM_USER); } } + + std::string bundleName = ""; + int32_t authType = static_cast(AuthType::DEFAULT); + if (!GetAuthParams(from, bundleName, authType)) { + ZLOGE("GetAuthParams failed"); + return session; + } for (const auto &user : users) { - bool isPermitted = AuthDelegate::GetInstance()->CheckAccess(from.userId, user.id, targetDeviceId, from.appId); + bool isPermitted = AuthDelegate::GetInstance()->CheckAccess(from.userId, user.id, + targetDeviceId, authType); ZLOGD("access to peer user %{public}d is %{public}d", user.id, isPermitted); if (isPermitted) { auto it = std::find(session.targetUserIds.begin(), session.targetUserIds.end(), user.id); @@ -72,9 +80,36 @@ Session SessionManager::GetSession(const SessionPoint &from, const std::string & return session; } +bool SessionManager::GetAuthParams(const SessionPoint &from, std::string &bundleName, int32_t &auth) const +{ + std::vector metaData; + if (!MetaDataManager::GetInstance().LoadMeta(StoreMetaData::GetPrefix({ from.deviceId }), metaData)) { + ZLOGW("load meta failed, deviceId:%{public}s", Anonymous::Change(from.deviceId).c_str()); + return false; + } + for (const auto &storeMeta : metaData) { + if (storeMeta.appId == from.appId) { + bundleName = storeMeta.bundleName; + auth = storeMeta.authType; + break; + } + } + if (bundleName.empty()) { + ZLOGE("not find bundleName"); + return false; + } + return true; +} + bool SessionManager::CheckSession(const SessionPoint &from, const SessionPoint &to) const { - return AuthDelegate::GetInstance()->CheckAccess(from.userId, to.userId, to.deviceId, from.appId); + std::string bundleName = ""; + int32_t authType = static_cast(AuthType::DEFAULT); + if (!GetAuthParams(from, bundleName, authType)) { + ZLOGE("GetAuthParams failed"); + return false; + } + return AuthDelegate::GetInstance()->CheckAccess(from.userId, to.userId, to.deviceId, authType, false); } bool Session::Marshal(json &node) const diff --git a/datamgr_service/services/distributeddataservice/app/src/session_manager/session_manager.h b/datamgr_service/services/distributeddataservice/app/src/session_manager/session_manager.h index bad2b8e2f6cad8b3d461d4aa722de72ec415d532..43c6312f78e9db26872eaace711fecde048f96c6 100644 --- a/datamgr_service/services/distributeddataservice/app/src/session_manager/session_manager.h +++ b/datamgr_service/services/distributeddataservice/app/src/session_manager/session_manager.h @@ -49,6 +49,8 @@ public: static SessionManager &GetInstance(); Session GetSession(const SessionPoint &from, const std::string &targetDeviceId) const; bool CheckSession(const SessionPoint &from, const SessionPoint &to) const; +private: + bool GetAuthParams(const SessionPoint &from, std::string &bundleName, int32_t &auth) const; }; } // namespace OHOS::DistributedData diff --git a/datamgr_service/services/distributeddataservice/app/src/session_manager/upgrade_manager.cpp b/datamgr_service/services/distributeddataservice/app/src/session_manager/upgrade_manager.cpp index 0627708fe8570dc0c352860b9ec0b0889ffc2339..65360d84898a7ca4d184594c149fb11d4513a760 100644 --- a/datamgr_service/services/distributeddataservice/app/src/session_manager/upgrade_manager.cpp +++ b/datamgr_service/services/distributeddataservice/app/src/session_manager/upgrade_manager.cpp @@ -23,6 +23,7 @@ #include "metadata/meta_data_manager.h" #include "utils/anonymous.h" #include "utils/constant.h" +#include "app_id_mapping/app_id_mapping_config_manager.h" namespace OHOS::DistributedData { using namespace OHOS::DistributedKv; @@ -119,20 +120,24 @@ void UpgradeManager::SetCompatibleIdentifyByType(DistributedDB::KvStoreNbDelegat GetIdentifierParams(sameAccountDevs, uuids, IDENTICAL_ACCOUNT); GetIdentifierParams(defaultAccountDevs, uuids, NO_ACCOUNT); if (!sameAccountDevs.empty()) { - auto syncIdentifier = - DistributedDB::KvStoreDelegateManager::GetKvStoreIdentifier(tuple.userId, tuple.appId, tuple.storeId); - ZLOGI("same account set compatible identifier store:%{public}s, user:%{public}s, device:%{public}.10s", - Anonymous::Change(tuple.storeId).c_str(), Anonymous::Change(tuple.userId).c_str(), - DistributedData::Serializable::Marshall(sameAccountDevs).c_str()); - storeDelegate->SetEqualIdentifier(syncIdentifier, sameAccountDevs); + auto convertedIds = AppIdMappingConfigManager::GetInstance().Convert(tuple.appId, tuple.userId); + auto identifier = + DistributedDB::KvStoreDelegateManager::GetKvStoreIdentifier(convertedIds.second, + convertedIds.first, tuple.storeId); + ZLOGI("same account store:%{public}s, user:%{public}s, device:%{public}.10s, appId:%{public}s", + Anonymous::Change(tuple.storeId).c_str(), Anonymous::Change(convertedIds.second).c_str(), + DistributedData::Serializable::Marshall(sameAccountDevs).c_str(), convertedIds.first.c_str()); + storeDelegate->SetEqualIdentifier(identifier, sameAccountDevs); } if (!defaultAccountDevs.empty()) { - auto syncIdentifier = - DistributedDB::KvStoreDelegateManager::GetKvStoreIdentifier(defaultAccountId, tuple.appId, tuple.storeId); - ZLOGI("no account set compatible identifier, store:%{public}s, device:%{public}.10s", + auto convertedIds = AppIdMappingConfigManager::GetInstance().Convert(tuple.appId, defaultAccountId); + auto identifier = + DistributedDB::KvStoreDelegateManager::GetKvStoreIdentifier(convertedIds.second, + convertedIds.first, tuple.storeId); + ZLOGI("no account identifier, store:%{public}s, device:%{public}.10s, appId:%{public}s", Anonymous::Change(tuple.storeId).c_str(), - DistributedData::Serializable::Marshall(defaultAccountDevs).c_str()); - storeDelegate->SetEqualIdentifier(syncIdentifier, defaultAccountDevs); + DistributedData::Serializable::Marshall(defaultAccountDevs).c_str(), convertedIds.first.c_str()); + storeDelegate->SetEqualIdentifier(identifier, defaultAccountDevs); } } } // namespace OHOS::DistributedData diff --git a/datamgr_service/services/distributeddataservice/app/src/session_manager/upgrade_manager.h b/datamgr_service/services/distributeddataservice/app/src/session_manager/upgrade_manager.h index 9fc71a2fd457682a7f7b4097b3b2026f12339a51..9348fc02b6af9952669fd0bd1e8ae26f5811853a 100644 --- a/datamgr_service/services/distributeddataservice/app/src/session_manager/upgrade_manager.h +++ b/datamgr_service/services/distributeddataservice/app/src/session_manager/upgrade_manager.h @@ -47,7 +47,7 @@ private: static constexpr int32_t NO_ACCOUNT = 0; static constexpr int32_t IDENTICAL_ACCOUNT = 1; - static constexpr const char *defaultAccountId = "default"; + static constexpr const char *defaultAccountId = "ohosAnonymousUid"; }; } // namespace OHOS::DistributedData #endif // DISTRIBUTEDDATAMGR_UPGRADE_MANAGER_H diff --git a/datamgr_service/services/distributeddataservice/app/test/unittest/kvstore_data_service_clear_test.cpp b/datamgr_service/services/distributeddataservice/app/test/unittest/kvstore_data_service_clear_test.cpp index 506d689bc354227cc177abc8bfe5a6d20e5238d3..268811200ef9a1507189c30959295ef60adda039 100644 --- a/datamgr_service/services/distributeddataservice/app/test/unittest/kvstore_data_service_clear_test.cpp +++ b/datamgr_service/services/distributeddataservice/app/test/unittest/kvstore_data_service_clear_test.cpp @@ -45,11 +45,8 @@ class KvStoreDataServiceClearTest : public testing::Test { public: static void SetUpTestCase(void); static void TearDownTestCase(void); - void SetUp(); void TearDown(); - - NativeTokenInfoParams infoInstance {0}; protected: static constexpr const char *TEST_USER = "100"; static constexpr const char *TEST_BUNDLE = "ohos.test.demo"; @@ -57,16 +54,10 @@ protected: static constexpr int32_t TEST_UID = 2000000; static constexpr int32_t TEST_USERID = 100; static constexpr const char *BUNDLE_NAME = "ohos.test.demo"; - static constexpr const char *BUNDLENAME_NO = "com.sample.helloworld"; static constexpr int32_t USER_ID = 100; - static constexpr int32_t USERID_NO = 10; static constexpr int32_t APP_INDEX = 0; - static constexpr int32_t APPINDEX_NO = 2; - static constexpr int32_t INVALID_TOKEN = 222; - DistributedData::StoreMetaData metaData_; DistributedData::StoreMetaDataLocal localMeta_; - void InitMetaData(); }; @@ -80,55 +71,12 @@ void KvStoreDataServiceClearTest::TearDownTestCase(void) void KvStoreDataServiceClearTest::SetUp(void) { - DistributedData::Bootstrap::GetInstance().LoadComponents(); DistributedData::Bootstrap::GetInstance().LoadDirectory(); DistributedData::Bootstrap::GetInstance().LoadCheckers(); - - infoInstance.dcapsNum = 0; - infoInstance.permsNum = 0; - infoInstance.aclsNum = 0; - infoInstance.dcaps = nullptr; - infoInstance.perms = nullptr; - infoInstance.acls = nullptr; - infoInstance.processName = "KvStoreDataServiceClearTest"; - infoInstance.aplStr = "system_core"; - - HapInfoParams info = { - .userID = TEST_USERID, - .bundleName = TEST_BUNDLE, - .instIndex = 0, - .appIDDesc = TEST_BUNDLE - }; - PermissionDef infoManagerTestPermDef = { - .permissionName = "ohos.permission.test", - .bundleName = TEST_BUNDLE, - .grantMode = 1, - .availableLevel = APL_NORMAL, - .label = "label", - .labelId = 1, - .description = "open the door", - .descriptionId = 1 - }; - PermissionStateFull infoManagerTestState = { - .permissionName = "ohos.permission.test", - .isGeneral = true, - .resDeviceID = {"local"}, - .grantStatus = {PermissionState::PERMISSION_GRANTED}, - .grantFlags = {1} - }; - HapPolicyParams policy = { - .apl = APL_NORMAL, - .domain = "test.domain", - .permList = {infoManagerTestPermDef}, - .permStateList = {infoManagerTestState} - }; - AccessTokenKit::AllocHapToken(info, policy); } void KvStoreDataServiceClearTest::TearDown(void) { - auto tokenId = AccessTokenKit::GetHapTokenID(TEST_USERID, TEST_BUNDLE, 0); - AccessTokenKit::DeleteToken(tokenId); } void KvStoreDataServiceClearTest::InitMetaData() @@ -155,7 +103,7 @@ void KvStoreDataServiceClearTest::InitMetaData() /** * @tc.name: ClearAppStorage001 - * @tc.desc: Test that the parameters are entered correctly + * @tc.desc: The parameters are valid but have no metaData * @tc.type: FUNC * @tc.require: * @tc.author: suoqilong @@ -163,49 +111,23 @@ void KvStoreDataServiceClearTest::InitMetaData() HWTEST_F(KvStoreDataServiceClearTest, ClearAppStorage001, TestSize.Level1) { auto kvDataService = OHOS::DistributedKv::KvStoreDataService(); - auto tokenIdOk = AccessTokenKit::GetHapTokenID(TEST_USERID, TEST_BUNDLE, 0); - auto ret = - kvDataService.ClearAppStorage(BUNDLE_NAME, USER_ID, APP_INDEX, INVALID_TOKEN); - EXPECT_EQ(ret, Status::ERROR); - - ret = kvDataService.ClearAppStorage(BUNDLENAME_NO, USER_ID, APP_INDEX, tokenIdOk); - EXPECT_EQ(ret, Status::ERROR); - - ret = kvDataService.ClearAppStorage(BUNDLE_NAME, USERID_NO, APP_INDEX, tokenIdOk); - EXPECT_EQ(ret, Status::ERROR); - - ret = kvDataService.ClearAppStorage(BUNDLE_NAME, USER_ID, APPINDEX_NO, tokenIdOk); + auto tokenIdOk = AccessTokenKit::GetNativeTokenId("foundation"); + SetSelfTokenID(tokenIdOk); + auto ret = kvDataService.ClearAppStorage(BUNDLE_NAME, USER_ID, APP_INDEX, tokenIdOk); EXPECT_EQ(ret, Status::ERROR); } /** * @tc.name: ClearAppStorage002 - * @tc.desc: The parameters are valid but have no metaData - * @tc.type: FUNC - * @tc.require: - * @tc.author: suoqilong - */ -HWTEST_F(KvStoreDataServiceClearTest, ClearAppStorage002, TestSize.Level1) -{ - auto kvDataService = OHOS::DistributedKv::KvStoreDataService(); - auto tokenIdOk = AccessTokenKit::GetHapTokenID(TEST_USERID, TEST_BUNDLE, 0); - - auto ret = - kvDataService.ClearAppStorage(BUNDLE_NAME, USER_ID, APP_INDEX, tokenIdOk); - EXPECT_EQ(ret, Status::ERROR); -} - -/** - * @tc.name: ClearAppStorage003 * @tc.desc: Test that the cleanup is implemented * @tc.type: FUNC * @tc.require: * @tc.author: suoqilong */ -HWTEST_F(KvStoreDataServiceClearTest, ClearAppStorage003, TestSize.Level1) +HWTEST_F(KvStoreDataServiceClearTest, ClearAppStorage002, TestSize.Level1) { - auto executors = std::make_shared(12, 5); - // Create an object of the ExecutorPool class and pass 12 and 5 as arguments to the constructor of the class + auto executors = std::make_shared(2, 1); + // Create an object of the ExecutorPool class and pass 2 and 1 as arguments to the constructor of the class KvStoreMetaManager::GetInstance().BindExecutor(executors); KvStoreMetaManager::GetInstance().InitMetaParameter(); DmAdapter::GetInstance().Init(executors); @@ -226,10 +148,10 @@ HWTEST_F(KvStoreDataServiceClearTest, ClearAppStorage003, TestSize.Level1) EXPECT_TRUE(MetaDataManager::GetInstance().LoadMeta(metaData_.appId, metaData_, true)); EXPECT_TRUE(MetaDataManager::GetInstance().LoadMeta(metaData_.GetKeyLocal(), localMeta_, true)); - auto tokenIdOk = AccessTokenKit::GetHapTokenID(TEST_USERID, TEST_BUNDLE, 0); + auto tokenIdOk = AccessTokenKit::GetNativeTokenId("foundation"); + SetSelfTokenID(tokenIdOk); auto kvDataService = OHOS::DistributedKv::KvStoreDataService(); - auto ret = - kvDataService.ClearAppStorage(BUNDLE_NAME, USER_ID, APP_INDEX, tokenIdOk); + auto ret = kvDataService.ClearAppStorage(BUNDLE_NAME, USER_ID, APP_INDEX, tokenIdOk); EXPECT_EQ(ret, Status::SUCCESS); EXPECT_FALSE(MetaDataManager::GetInstance().LoadMeta(metaData_.GetKey(), metaData_)); diff --git a/datamgr_service/services/distributeddataservice/app/test/unittest/session_manager_test.cpp b/datamgr_service/services/distributeddataservice/app/test/unittest/session_manager_test.cpp index 554891ba8588124854e9f1d80af250e12c48e8d2..96fa8ca77c257a42bb9749b9b1ccc184992b25ec 100644 --- a/datamgr_service/services/distributeddataservice/app/test/unittest/session_manager_test.cpp +++ b/datamgr_service/services/distributeddataservice/app/test/unittest/session_manager_test.cpp @@ -93,6 +93,7 @@ public: StoreMetaData metaData; metaData.bundleName = "ohos.test.demo"; + metaData.appId = "ohos.test.demo"; metaData.storeId = "test_store"; metaData.user = "100"; metaData.deviceId = DeviceManagerAdapter::GetInstance().GetLocalDevice().uuid; @@ -110,6 +111,7 @@ public: MetaDataManager::GetInstance().DelMeta(std::string(peerCapMetaKey.begin(), peerCapMetaKey.end())); StoreMetaData metaData; metaData.bundleName = "ohos.test.demo"; + metaData.appId = "ohos.test.demo"; metaData.storeId = "test_store"; metaData.user = "100"; metaData.deviceId = DeviceManagerAdapter::GetInstance().GetLocalDevice().uuid; @@ -142,7 +144,7 @@ HWTEST_F(SessionManagerTest, PackAndUnPack01, TestSize.Level2) ASSERT_NE(sendHandler, nullptr); uint32_t routeHeadSize = 0; sendHandler->GetHeadDataSize(routeHeadSize); - ASSERT_GT(routeHeadSize, 0); + ASSERT_EQ(routeHeadSize, 0); std::unique_ptr data = std::make_unique(routeHeadSize); sendHandler->FillHeadData(data.get(), routeHeadSize, routeHeadSize); @@ -152,7 +154,6 @@ HWTEST_F(SessionManagerTest, PackAndUnPack01, TestSize.Level2) uint32_t parseSize = 1; recvHandler->ParseHeadData(data.get(), routeHeadSize, parseSize, users); EXPECT_EQ(routeHeadSize, parseSize); - ASSERT_EQ(users.size(), 1); - EXPECT_EQ(users[0], "100"); + ASSERT_EQ(users.size(), 0); } } // namespace \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/framework/BUILD.gn b/datamgr_service/services/distributeddataservice/framework/BUILD.gn index f069d43e881f8669394ea2865e563a37d7ddd43f..ca78af920b56d92820997a5c80a0f4714d13242a 100644 --- a/datamgr_service/services/distributeddataservice/framework/BUILD.gn +++ b/datamgr_service/services/distributeddataservice/framework/BUILD.gn @@ -33,6 +33,7 @@ config("module_public_config") { visibility = [ ":*" ] include_dirs = [ "include", + "${data_service_path}/framework/include/account", "${kv_store_common_path}", ] } @@ -47,6 +48,8 @@ ohos_shared_library("distributeddatasvcfwk") { debug = false } sources = [ + "account/account_delegate.cpp", + "app_id_mapping/app_id_mapping_config_manager.cpp", "backuprule/backup_rule_manager.cpp", "changeevent/remote_change_event.cpp", "checker/checker_manager.cpp", @@ -56,6 +59,7 @@ ohos_shared_library("distributeddatasvcfwk") { "cloud/cloud_event.cpp", "cloud/cloud_extra_data.cpp", "cloud/cloud_info.cpp", + "cloud/cloud_lock_event.cpp", "cloud/cloud_server.cpp", "cloud/cloud_share_event.cpp", "cloud/cloud_sync_finished_event.cpp", @@ -65,6 +69,7 @@ ohos_shared_library("distributeddatasvcfwk") { "cloud/subscription.cpp", "cloud/sync_event.cpp", "cloud/sync_strategy.cpp", + "communication/connect_manager.cpp", "directory/directory_manager.cpp", "dump/dump_manager.cpp", "eventcenter/event.cpp", @@ -86,6 +91,7 @@ ohos_shared_library("distributeddatasvcfwk") { "metadata/switches_meta_data.cpp", "metadata/user_meta_data.cpp", "metadata/version_meta_data.cpp", + "screen/screen_manager.cpp", "serializable/serializable.cpp", "snapshot/bind_event.cpp", "snapshot/snapshot.cpp", diff --git a/datamgr_service/services/distributeddataservice/framework/CMakeLists.txt b/datamgr_service/services/distributeddataservice/framework/CMakeLists.txt index d72ea16e5797af7d76fdd04a7e56b3092c1dff3f..9166243b738ddfd32191bc8754cd8b8e242cd999 100644 --- a/datamgr_service/services/distributeddataservice/framework/CMakeLists.txt +++ b/datamgr_service/services/distributeddataservice/framework/CMakeLists.txt @@ -10,18 +10,22 @@ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fprofile-arcs -ftest-coverage") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fprofile-arcs -ftest-coverage") set(MOCK_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../../../../mock") set(KV_STORE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../../../../kv_store") +aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/account svcFwkSrc) +aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/app_id_mapping svcFwkSrc) aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/backuprule svcFwkSrc) aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/changeevent svcFwkSrc) aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/checker svcFwkSrc) +aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/cloud svcFwkSrc) +aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/communication svcFwkSrc) +aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/directory svcFwkSrc) aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/dump svcFwkSrc) -aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/metadata svcFwkSrc) aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/eventcenter svcFwkSrc) +aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/feature svcFwkSrc) +aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/metadata svcFwkSrc) +aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/screen svcFwkSrc) aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/serializable svcFwkSrc) aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/snapshot svcFwkSrc) -aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/feature svcFwkSrc) -aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/directory svcFwkSrc) aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/store svcFwkSrc) -aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/cloud svcFwkSrc) aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/utils svcFwkSrc) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../adapter/include) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../../../../utils_native/base/include) @@ -35,3 +39,4 @@ set(LIBRARY_OUTPUT_PATH "${PROJECT_BINARY_DIR}/../../../../") add_library(svcFwk SHARED ${svcFwkSrc}) target_link_libraries(svcFwk ${links}) target_include_directories(svcFwk PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include) +target_include_directories(svcFwk PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include/account) diff --git a/datamgr_service/services/distributeddataservice/framework/account/account_delegate.cpp b/datamgr_service/services/distributeddataservice/framework/account/account_delegate.cpp new file mode 100644 index 0000000000000000000000000000000000000000..1734d6541b80be85e2bbb28e63018590ba27242f --- /dev/null +++ b/datamgr_service/services/distributeddataservice/framework/account/account_delegate.cpp @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "account_delegate.h" + +namespace OHOS { +namespace DistributedKv { +AccountDelegate *AccountDelegate::instance_ = nullptr; + +bool AccountDelegate::RegisterAccountInstance(AccountDelegate *instance) +{ + if (instance_ != nullptr) { + return false; + } + instance_ = instance; + return true; +} + +AccountDelegate *AccountDelegate::GetInstance() +{ + return instance_; +} +} // namespace DistributedKv +} // namespace OHOS \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/framework/app_id_mapping/app_id_mapping_config_manager.cpp b/datamgr_service/services/distributeddataservice/framework/app_id_mapping/app_id_mapping_config_manager.cpp new file mode 100644 index 0000000000000000000000000000000000000000..3d03d5246261b7ba873aa408d3454edf801dd335 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/framework/app_id_mapping/app_id_mapping_config_manager.cpp @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define LOG_TAG "AppIdMappingConfigManager" +#include "app_id_mapping/app_id_mapping_config_manager.h" + +namespace OHOS::DistributedData { +AppIdMappingConfigManager &AppIdMappingConfigManager::GetInstance() +{ + static AppIdMappingConfigManager instance; + return instance; +} + +void AppIdMappingConfigManager::Initialize(const std::vector &mapper) +{ + for (const auto &info : mapper) { + toDstMapper_.insert_or_assign(info.srcAppId, info.dstAppId); + } +} + +std::pair AppIdMappingConfigManager::Convert(const std::string &appId, + const std::string &accountId) +{ + auto it = toDstMapper_.find(appId); + if (it == toDstMapper_.end()) { + return std::make_pair(appId, accountId); + } + return std::make_pair(it->second, "default"); +} + +} // namespace OHOS::DistributedData \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/framework/cloud/cloud_db.cpp b/datamgr_service/services/distributeddataservice/framework/cloud/cloud_db.cpp index 612c5a088f3d61d69bc773b4efdb05d677e654f9..0e3c2a4c607d79173d4e437cea11c2c61336741c 100644 --- a/datamgr_service/services/distributeddataservice/framework/cloud/cloud_db.cpp +++ b/datamgr_service/services/distributeddataservice/framework/cloud/cloud_db.cpp @@ -35,7 +35,7 @@ int32_t CloudDB::BatchUpdate(const std::string &table, VBuckets &&values, const return E_NOT_SUPPORT; } -int32_t CloudDB::BatchDelete(const std::string &table, const VBuckets &extends) +int32_t CloudDB::BatchDelete(const std::string &table, VBuckets &extends) { return E_NOT_SUPPORT; } diff --git a/datamgr_service/services/distributeddataservice/framework/cloud/cloud_event.cpp b/datamgr_service/services/distributeddataservice/framework/cloud/cloud_event.cpp index bfaf3c9eb16bf519dc41416ba55176eede336adc..701bce29cfc04cf90646f386c1dfeb254632c579 100644 --- a/datamgr_service/services/distributeddataservice/framework/cloud/cloud_event.cpp +++ b/datamgr_service/services/distributeddataservice/framework/cloud/cloud_event.cpp @@ -17,7 +17,7 @@ namespace OHOS::DistributedData { CloudEvent::CloudEvent(int32_t evtId, StoreInfo storeInfo) - : Event(evtId), storeInfo_(std::move(storeInfo)) + : Event(evtId), eventId_(evtId), storeInfo_(std::move(storeInfo)) { } @@ -25,4 +25,9 @@ const StoreInfo& CloudEvent::GetStoreInfo() const { return storeInfo_; } + +int32_t CloudEvent::GetEventId() const +{ + return eventId_; +} } \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/framework/cloud/cloud_info.cpp b/datamgr_service/services/distributeddataservice/framework/cloud/cloud_info.cpp index d723adfe5b37a57565e9ccb0bb90498f1da02852..191c6f88eff51b27cddde990cba8f51f2fa9e502 100644 --- a/datamgr_service/services/distributeddataservice/framework/cloud/cloud_info.cpp +++ b/datamgr_service/services/distributeddataservice/framework/cloud/cloud_info.cpp @@ -14,6 +14,7 @@ */ #include "cloud/cloud_info.h" + #include "utils/constant.h" namespace OHOS::DistributedData { @@ -76,8 +77,7 @@ std::map CloudInfo::GetSchemaKey() const { std::map keys; for (const auto &[bundle, app] : apps) { - const auto key = GetKey( - SCHEMA_PREFIX, { std::to_string(user), bundle, std::to_string(app.instanceId) }); + const auto key = GetKey(SCHEMA_PREFIX, { std::to_string(user), bundle, std::to_string(app.instanceId) }); keys.insert_or_assign(app.bundleName, key); } return keys; @@ -98,12 +98,12 @@ std::string CloudInfo::GetSchemaPrefix(const std::string &bundleName) const if (bundleName.empty()) { return GetKey(SCHEMA_PREFIX, { std::to_string(user) }); } - return GetKey(SCHEMA_PREFIX, { std::to_string(user), bundleName}); + return GetKey(SCHEMA_PREFIX, { std::to_string(user), bundleName }); } std::string CloudInfo::GetSchemaKey(const StoreMetaData &meta) { - return GetKey(SCHEMA_PREFIX, { meta.user, meta.bundleName, std::to_string(meta.instanceId) }); + return GetKey(SCHEMA_PREFIX, { meta.user, meta.bundleName, std::to_string(meta.instanceId) }); } bool CloudInfo::IsValid() const diff --git a/datamgr_service/services/distributeddataservice/framework/cloud/cloud_lock_event.cpp b/datamgr_service/services/distributeddataservice/framework/cloud/cloud_lock_event.cpp new file mode 100644 index 0000000000000000000000000000000000000000..c0bf9a1ad79953e6d62cd28bd48b2dece6a6cd8f --- /dev/null +++ b/datamgr_service/services/distributeddataservice/framework/cloud/cloud_lock_event.cpp @@ -0,0 +1,27 @@ +/* +* Copyright (c) 2024 Huawei Device Co., Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#include "cloud/cloud_lock_event.h" + +namespace OHOS::DistributedData { +CloudLockEvent::CloudLockEvent(int32_t evtId, StoreInfo storeInfo, Callback callback) + :CloudEvent(evtId, storeInfo), callback_(std::move(callback)) +{ +} +CloudLockEvent::Callback CloudLockEvent::GetCallback() const +{ + return callback_; +} +} // namespace OHOS::DistributedData \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/framework/cloud/schema_meta.cpp b/datamgr_service/services/distributeddataservice/framework/cloud/schema_meta.cpp index f22c28ae1f65380ba76f40914ae0f17f42d3f63b..e0df117706ce7c26f3b65e57341c37260e2dcb0a 100644 --- a/datamgr_service/services/distributeddataservice/framework/cloud/schema_meta.cpp +++ b/datamgr_service/services/distributeddataservice/framework/cloud/schema_meta.cpp @@ -39,7 +39,7 @@ std::vector Database::GetTableNames() const { std::vector tableNames; tableNames.reserve(tables.size()); - for (auto& table : tables) { + for (auto &table : tables) { tableNames.push_back(table.name); if (!table.sharedTableName.empty()) { tableNames.push_back(table.sharedTableName); diff --git a/datamgr_service/services/distributeddataservice/framework/cloud/sharing_center.cpp b/datamgr_service/services/distributeddataservice/framework/cloud/sharing_center.cpp index 0986649660c3535769b22b77e9b998a2bb11b613..cb171858d284ec4b858eb2cd85774328657fee2f 100644 --- a/datamgr_service/services/distributeddataservice/framework/cloud/sharing_center.cpp +++ b/datamgr_service/services/distributeddataservice/framework/cloud/sharing_center.cpp @@ -15,50 +15,50 @@ #include "cloud/sharing_center.h" namespace OHOS::DistributedData { -SharingCenter::Results SharingCenter::Share(int32_t userId, const std::string &bundleName, - const std::string &sharingRes, const Participants &participants) +SharingCenter::Results SharingCenter::Share( + int32_t userId, const std::string &bundleName, const std::string &sharingRes, const Participants &participants) { return {}; } -SharingCenter::Results SharingCenter::Unshare(int32_t userId, const std::string &bundleName, - const std::string &sharingRes, const Participants &participants) +SharingCenter::Results SharingCenter::Unshare( + int32_t userId, const std::string &bundleName, const std::string &sharingRes, const Participants &participants) { return {}; } -std::pair SharingCenter::Exit(int32_t userId, const std::string &bundleName, - const std::string &sharingRes) +std::pair SharingCenter::Exit( + int32_t userId, const std::string &bundleName, const std::string &sharingRes) { return {}; } -SharingCenter::Results SharingCenter::ChangePrivilege(int32_t userId, const std::string &bundleName, - const std::string &sharingRes, const Participants &participants) +SharingCenter::Results SharingCenter::ChangePrivilege( + int32_t userId, const std::string &bundleName, const std::string &sharingRes, const Participants &participants) { return {}; } -SharingCenter::QueryResults SharingCenter::Query(int32_t userId, const std::string &bundleName, - const std::string &sharingRes) +SharingCenter::QueryResults SharingCenter::Query( + int32_t userId, const std::string &bundleName, const std::string &sharingRes) { return {}; } -SharingCenter::QueryResults SharingCenter::QueryByInvitation(int32_t userId, const std::string &bundleName, - const std::string &invitation) +SharingCenter::QueryResults SharingCenter::QueryByInvitation( + int32_t userId, const std::string &bundleName, const std::string &invitation) { return {}; } -std::tuple SharingCenter::ConfirmInvitation(int32_t userId, - const std::string &bundleName, const std::string &invitation, int32_t confirmation) +std::tuple SharingCenter::ConfirmInvitation( + int32_t userId, const std::string &bundleName, const std::string &invitation, int32_t confirmation) { return {}; } -std::pair SharingCenter::ChangeConfirmation(int32_t userId, - const std::string &bundleName, const std::string &sharingRes, int32_t confirmation) +std::pair SharingCenter::ChangeConfirmation( + int32_t userId, const std::string &bundleName, const std::string &sharingRes, int32_t confirmation) { return {}; } diff --git a/datamgr_service/services/distributeddataservice/framework/cloud/subscription.cpp b/datamgr_service/services/distributeddataservice/framework/cloud/subscription.cpp index 28030d881146285152f98573b4daf1fb798c6938..1f570f3c20b3fd59a18b0e54a94e9607653a4ac1 100644 --- a/datamgr_service/services/distributeddataservice/framework/cloud/subscription.cpp +++ b/datamgr_service/services/distributeddataservice/framework/cloud/subscription.cpp @@ -14,6 +14,7 @@ */ #include "cloud/subscription.h" + #include "utils/constant.h" namespace OHOS::DistributedData { bool Subscription::Relation::Marshal(json &node) const diff --git a/datamgr_service/services/distributeddataservice/framework/cloud/sync_event.cpp b/datamgr_service/services/distributeddataservice/framework/cloud/sync_event.cpp index badf9ffee94405268fa72dd3201ee26a1618cb4c..f2c78e6c34e8b67735832ffe3d76785644c7f585 100644 --- a/datamgr_service/services/distributeddataservice/framework/cloud/sync_event.cpp +++ b/datamgr_service/services/distributeddataservice/framework/cloud/sync_event.cpp @@ -22,7 +22,7 @@ SyncEvent::EventInfo::EventInfo(int32_t mode, int32_t wait, bool retry, std::sha } SyncEvent::EventInfo::EventInfo(const SyncParam &syncParam, bool retry, std::shared_ptr query, GenAsync async) : retry_(retry), mode_(syncParam.mode), wait_(syncParam.wait), query_(std::move(query)), - asyncDetail_(std::move(async)), isCompensation_(syncParam.isCompensation) + asyncDetail_(std::move(async)), isCompensation_(syncParam.isCompensation), triggerMode_(syncParam.triggerMode) { } @@ -42,6 +42,7 @@ SyncEvent::EventInfo &SyncEvent::EventInfo::operator=(SyncEvent::EventInfo &&inf query_ = std::move(info.query_); asyncDetail_ = std::move(info.asyncDetail_); isCompensation_ = info.isCompensation_; + triggerMode_ = info.triggerMode_; return *this; } @@ -84,4 +85,9 @@ bool SyncEvent::IsCompensation() const { return info_.isCompensation_; } + +int32_t SyncEvent::GetTriggerMode() const +{ + return info_.triggerMode_; +} } // namespace OHOS::DistributedData \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/framework/communication/connect_manager.cpp b/datamgr_service/services/distributeddataservice/framework/communication/connect_manager.cpp new file mode 100644 index 0000000000000000000000000000000000000000..74f8f70a88d4e0120b66cfc9e4eada414b975c55 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/framework/communication/connect_manager.cpp @@ -0,0 +1,137 @@ +/* +* Copyright (c) 2024 Huawei Device Co., Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#define LOG_TAG "ConnectManager" +#include "communication/connect_manager.h" + +#include "log_print.h" + +namespace OHOS::AppDistributedKv { +std::mutex ConnectManager::mtx_; +std::shared_ptr ConnectManager::instance_ = nullptr; +ConnectManager::CloseSessionTask ConnectManager::closeSessionTask_ = nullptr; +ConcurrentMap ConnectManager::sessionCloseListener_; +ConcurrentMap ConnectManager::sessionOpenListener_; + +std::shared_ptr ConnectManager::GetInstance() +{ + static std::once_flag onceFlag; + std::call_once(onceFlag, [&]() { + std::lock_guard lock(mtx_); + if (instance_ == nullptr) { + instance_ = std::make_shared(); + } + }); + return instance_; +} + +bool ConnectManager::RegisterInstance(std::shared_ptr instance) +{ + std::lock_guard lock(mtx_); + if (instance_ != nullptr) { + ZLOGW("ConnectManager instance has been replaced!"); + } + instance_ = instance; + return true; +} + +bool ConnectManager::CloseSession(const std::string &networkId) +{ + if (closeSessionTask_ != nullptr) { + return closeSessionTask_(networkId); + } + return false; +} + +bool ConnectManager::RegisterCloseSessionTask(CloseSessionTask task) +{ + if (closeSessionTask_ != nullptr) { + ZLOGE("Register close session task error, task already exists."); + return false; + } + closeSessionTask_ = std::move(task); + return true; +} + +bool ConnectManager::RegisterSessionCloseListener(const std::string &name, SessionCloseListener listener) +{ + bool success = false; + sessionCloseListener_.Compute(name, [&success, &listener](const auto &key, auto &value) { + if (value != nullptr) { + ZLOGE("Register session close listener error, type:%{public}s already exists.", key.c_str()); + return true; + } + value = std::move(listener); + success = true; + return true; + }); + return success; +} + +void ConnectManager::UnRegisterSessionCloseListener(const std::string &name) +{ + sessionCloseListener_.Erase(name); +} + +void ConnectManager::OnSessionClose(const std::string &networkId) +{ + sessionCloseListener_.ForEach([&networkId](const auto &key, auto &listener) { + listener(networkId); + return false; + }); +} + +bool ConnectManager::RegisterSessionOpenListener(const std::string &name, SessionOpenListener listener) +{ + bool success = false; + sessionOpenListener_.Compute(name, [&success, &listener](const auto &key, auto &value) { + if (value != nullptr) { + ZLOGE("Register session open listener error, type:%{public}s already exists.", key.c_str()); + return true; + } + value = std::move(listener); + success = true; + return true; + }); + return success; +} + +void ConnectManager::UnRegisterSessionOpenListener(const std::string &name) +{ + sessionOpenListener_.Erase(name); +} + +void ConnectManager::OnSessionOpen(const std::string &networkId) +{ + sessionOpenListener_.ForEach([&networkId](const auto &key, auto &listener) { + listener(networkId); + return false; + }); +} + +void ConnectManager::OnStart() +{ +} + +void ConnectManager::OnDestory() +{ +} + +int32_t ConnectManager::ApplyConnect(__attribute__((unused)) const std::string &networkId, ConnectTask task) +{ + task(); + return 0; +} +} // OHOS::AppDistributedKv \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/framework/directory/directory_manager.cpp b/datamgr_service/services/distributeddataservice/framework/directory/directory_manager.cpp index 16b34ce02aff6727fdf08e8148d556e357729253..bb954fd151c1e5713d2b74c200df2b44549bd8a2 100644 --- a/datamgr_service/services/distributeddataservice/framework/directory/directory_manager.cpp +++ b/datamgr_service/services/distributeddataservice/framework/directory/directory_manager.cpp @@ -117,18 +117,18 @@ std::string DirectoryManager::GetType(const StoreMetaData &metaData) const std::string DirectoryManager::GetStore(const StoreMetaData &metaData) const { - if (metaData.storeType >= StoreMetaData::StoreType::STORE_KV_BEGIN - && metaData.storeType <= StoreMetaData::StoreType::STORE_KV_END) { + if (metaData.storeType >= StoreMetaData::StoreType::STORE_KV_BEGIN && + metaData.storeType <= StoreMetaData::StoreType::STORE_KV_END) { return "kvdb"; } // rdb use empty session - if (metaData.storeType >= StoreMetaData::StoreType::STORE_RELATIONAL_BEGIN - && metaData.storeType <= StoreMetaData::StoreType::STORE_RELATIONAL_END) { + if (metaData.storeType >= StoreMetaData::StoreType::STORE_RELATIONAL_BEGIN && + metaData.storeType <= StoreMetaData::StoreType::STORE_RELATIONAL_END) { return "rdb"; } // object use meta - if (metaData.storeType >= StoreMetaData::StoreType::STORE_OBJECT_BEGIN - && metaData.storeType <= StoreMetaData::StoreType::STORE_OBJECT_END) { + if (metaData.storeType >= StoreMetaData::StoreType::STORE_OBJECT_BEGIN && + metaData.storeType <= StoreMetaData::StoreType::STORE_OBJECT_END) { return "kvdb"; } return "other"; @@ -142,7 +142,8 @@ std::string DirectoryManager::GetSecurity(const StoreMetaData &metaData) const break; } [[fallthrough]]; - case SecurityLevel::S0: [[fallthrough]]; + case SecurityLevel::S0: + [[fallthrough]]; case SecurityLevel::S1: return "misc_de"; } @@ -271,4 +272,41 @@ bool DirectoryManager::CreateDirectory(const std::string &path) const return access(path.c_str(), F_OK) == 0; } + +bool DirectoryManager::DeleteDirectory(const char* path) +{ + if (path == nullptr) { + return false; + } + DIR* dir; + struct dirent* dirEntry; + struct stat buf; + char* curWorkDir = getcwd(nullptr, 0); + if ((dir = opendir(path)) == nullptr) { + return true; + } + if (chdir(path) == -1) { + return false; + } + while ((dirEntry = readdir(dir))) { + if ((strcmp(dirEntry->d_name, ".") == 0) || (strcmp(dirEntry->d_name, "..") == 0)) { + continue; + } + if (stat(dirEntry->d_name, &buf) == -1) { + return false; + } + if (S_ISDIR(buf.st_mode)) { + DeleteDirectory(dirEntry->d_name); + continue; + } + if (remove(dirEntry->d_name) == -1) { + return false; + } + } + closedir(dir); + if (chdir(curWorkDir) == -1 || rmdir(path) == -1) { + return false; + } + return true; +} } // namespace OHOS::DistributedData diff --git a/datamgr_service/services/distributeddataservice/adapter/include/account/account_delegate.h b/datamgr_service/services/distributeddataservice/framework/include/account/account_delegate.h similarity index 82% rename from datamgr_service/services/distributeddataservice/adapter/include/account/account_delegate.h rename to datamgr_service/services/distributeddataservice/framework/include/account/account_delegate.h index 4c6458158d39809e891642f80c566b7e2b0bae64..29a8c7e4570d660be546eeb9e992f5a762c673a0 100644 --- a/datamgr_service/services/distributeddataservice/adapter/include/account/account_delegate.h +++ b/datamgr_service/services/distributeddataservice/framework/include/account/account_delegate.h @@ -16,8 +16,9 @@ #ifndef DISTRIBUTEDDATAMGR_ACCOUNT_DELEGATE_H #define DISTRIBUTEDDATAMGR_ACCOUNT_DELEGATE_H -#include #include +#include + #include "executor_pool.h" #include "types.h" #include "visibility.h" @@ -26,11 +27,11 @@ namespace OHOS { namespace DistributedKv { enum class AccountStatus { HARMONY_ACCOUNT_LOGIN = 0, // the openHarmony account is logged in - HARMONY_ACCOUNT_LOGOUT, // the openHarmony account is logged out - HARMONY_ACCOUNT_DELETE, // the openHarmony account is deleted - DEVICE_ACCOUNT_DELETE, // the device account is deleted - DEVICE_ACCOUNT_SWITCHED, // the device account is switched - DEVICE_ACCOUNT_UNLOCKED, // the device account is unlocked + HARMONY_ACCOUNT_LOGOUT, // the openHarmony account is logged out + HARMONY_ACCOUNT_DELETE, // the openHarmony account is deleted + DEVICE_ACCOUNT_DELETE, // the device account is deleted + DEVICE_ACCOUNT_SWITCHED, // the device account is switched + DEVICE_ACCOUNT_UNLOCKED, // the device account is unlocked }; struct AccountEventInfo { @@ -54,7 +55,7 @@ public: API_EXPORT virtual std::string Name() = 0; API_EXPORT virtual LevelType GetLevel() = 0; }; - using HashFunc = std::string(*)(const void *data, size_t size, bool isUpper); + using HashFunc = std::string (*)(const void *data, size_t size, bool isUpper); API_EXPORT virtual ~AccountDelegate() = default; API_EXPORT virtual Status Subscribe(std::shared_ptr observer) = 0; API_EXPORT virtual Status Unsubscribe(std::shared_ptr observer) = 0; @@ -71,11 +72,11 @@ public: API_EXPORT virtual void BindExecutor(std::shared_ptr executors) = 0; API_EXPORT virtual std::string GetUnencryptedAccountId(int32_t userId = 0) const = 0; API_EXPORT static AccountDelegate *GetInstance(); + API_EXPORT static bool RegisterAccountInstance(AccountDelegate *instance); private: - using BaseInstance = AccountDelegate *(*)(); - static BaseInstance getInstance_; + static AccountDelegate *instance_; }; -} // namespace DistributedKv -} // namespace OHOS +} // namespace DistributedKv +} // namespace OHOS #endif // DISTRIBUTEDDATAMGR_ACCOUNT_DELEGATE_H \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/framework/include/app_id_mapping/app_id_mapping_config_manager.h b/datamgr_service/services/distributeddataservice/framework/include/app_id_mapping/app_id_mapping_config_manager.h new file mode 100644 index 0000000000000000000000000000000000000000..9799f9af673fa969a71d9d01cf57b249b6b09592 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/framework/include/app_id_mapping/app_id_mapping_config_manager.h @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef OHOS_DISTRIBUTED_DATA_SERVICES_FRAMEWORK_APP_ID_MAPPING_CONFIG_MANAGER_H +#define OHOS_DISTRIBUTED_DATA_SERVICES_FRAMEWORK_APP_ID_MAPPING_CONFIG_MANAGER_H +#include +#include +#include +#include "visibility.h" +namespace OHOS { +namespace DistributedData { +class AppIdMappingConfigManager { +public: + struct AppMappingInfo { + std::string srcAppId; + std::string dstAppId; + }; + API_EXPORT static AppIdMappingConfigManager &GetInstance(); + API_EXPORT void Initialize(const std::vector &mapper); + API_EXPORT std::pair Convert(const std::string &appId, + const std::string &accountId); + +private: + std::map toDstMapper_; +}; + +} // namespace DistributedData +} // namespace OHOS +#endif //OHOS_DISTRIBUTED_DATA_SERVICES_FRAMEWORK_APP_ID_MAPPING_CONFIG_MANAGER_H diff --git a/datamgr_service/services/distributeddataservice/framework/include/changeevent/remote_change_event.h b/datamgr_service/services/distributeddataservice/framework/include/changeevent/remote_change_event.h index 8236df1b429e76c7c73768e2152762389bb24741..bf58f4328937a5fa76140409c8baf4be77ed95fe 100644 --- a/datamgr_service/services/distributeddataservice/framework/include/changeevent/remote_change_event.h +++ b/datamgr_service/services/distributeddataservice/framework/include/changeevent/remote_change_event.h @@ -33,6 +33,7 @@ public: std::string storeId; std::string deviceId; std::string bundleName; + int changeType = 0; // 0 means CLOUD_DATA_CHANGE std::vector tables; }; diff --git a/datamgr_service/services/distributeddataservice/framework/include/cloud/cloud_db.h b/datamgr_service/services/distributeddataservice/framework/include/cloud/cloud_db.h index f0517d10c07333238fd79e0b23ec80192575e3a7..6927a277a20fdcf004960657e8d778e9c8c732ba 100644 --- a/datamgr_service/services/distributeddataservice/framework/include/cloud/cloud_db.h +++ b/datamgr_service/services/distributeddataservice/framework/include/cloud/cloud_db.h @@ -38,7 +38,7 @@ public: virtual int32_t BatchUpdate(const std::string &table, VBuckets &&values, const VBuckets &extends); - virtual int32_t BatchDelete(const std::string &table, const VBuckets &extends); + virtual int32_t BatchDelete(const std::string &table, VBuckets &extends); virtual std::shared_ptr Query(const std::string &table, const VBucket &extend); diff --git a/datamgr_service/services/distributeddataservice/framework/include/cloud/cloud_event.h b/datamgr_service/services/distributeddataservice/framework/include/cloud/cloud_event.h index 0ac070ad609a5f1731da69ace445f0b33adf2d40..8cd2d2d47b3df14737edf6ad688450dc80cf14ce 100644 --- a/datamgr_service/services/distributeddataservice/framework/include/cloud/cloud_event.h +++ b/datamgr_service/services/distributeddataservice/framework/include/cloud/cloud_event.h @@ -27,20 +27,26 @@ public: FEATURE_INIT = EVT_CLOUD, GET_SCHEMA, LOCAL_CHANGE, + CLEAN_DATA, CLOUD_SYNC, DATA_CHANGE, + SET_SEARCHABLE, CLOUD_SHARE, MAKE_QUERY, CLOUD_SYNC_FINISHED, DATA_SYNC, + LOCK_CLOUD_CONTAINER, + UNLOCK_CLOUD_CONTAINER, CLOUD_BUTT }; CloudEvent(int32_t evtId, StoreInfo storeInfo); ~CloudEvent() = default; const StoreInfo& GetStoreInfo() const; + int32_t GetEventId() const; private: + int32_t eventId_; StoreInfo storeInfo_; }; } // namespace OHOS::DistributedData diff --git a/datamgr_service/services/distributeddataservice/framework/include/cloud/cloud_lock_event.h b/datamgr_service/services/distributeddataservice/framework/include/cloud/cloud_lock_event.h new file mode 100644 index 0000000000000000000000000000000000000000..cbced1b0324d1f5046b263c1ddeed1af5ad1e8f4 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/framework/include/cloud/cloud_lock_event.h @@ -0,0 +1,34 @@ +/* +* Copyright (c) 2024 Huawei Device Co., Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#ifndef OHOS_DISTRIBUTED_DATA_SERVICES_FRAMEWORK_CLOUD_LOCK_EVENT_H +#define OHOS_DISTRIBUTED_DATA_SERVICES_FRAMEWORK_CLOUD_LOCK_EVENT_H +#include "cloud/cloud_event.h" +#include "store/general_value.h" +#include "store/general_store.h" +#include "visibility.h" + +namespace OHOS::DistributedData { +class API_EXPORT CloudLockEvent : public CloudEvent { +public: + using Callback = std::function; + CloudLockEvent(int32_t evtId, StoreInfo storeInfo, Callback callback); + ~CloudLockEvent() override = default; + Callback GetCallback() const; +private: + Callback callback_; +}; +} // namespace OHOS::DistributedData +#endif // OHOS_DISTRIBUTED_DATA_SERVICES_FRAMEWORK_CLOUD_LOCK_EVENT_H \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/framework/include/cloud/sync_event.h b/datamgr_service/services/distributeddataservice/framework/include/cloud/sync_event.h index 9887d9a77920d163297a91cee04b9a8b75bfdd1b..22a06c077f1d891121c71d1278b2462dad24349e 100644 --- a/datamgr_service/services/distributeddataservice/framework/include/cloud/sync_event.h +++ b/datamgr_service/services/distributeddataservice/framework/include/cloud/sync_event.h @@ -37,6 +37,7 @@ public: std::shared_ptr query_; GenAsync asyncDetail_; bool isCompensation_ = false; + int32_t triggerMode_ = MODE_DEFAULT; }; SyncEvent(StoreInfo storeInfo, EventInfo info); ~SyncEvent() override = default; @@ -46,7 +47,7 @@ public: std::shared_ptr GetQuery() const; GenAsync GetAsyncDetail() const; bool IsCompensation() const; - + int32_t GetTriggerMode() const; protected: SyncEvent(int32_t evtId, StoreInfo storeInfo, EventInfo info); diff --git a/datamgr_service/services/distributeddataservice/framework/include/commonevent/data_change_event.h b/datamgr_service/services/distributeddataservice/framework/include/commonevent/data_change_event.h index be3970cdf26bccc83eb53587e9b60d24c7d9553f..d66482886b232bf3715f5073b8347b9a4b5f2b84 100644 --- a/datamgr_service/services/distributeddataservice/framework/include/commonevent/data_change_event.h +++ b/datamgr_service/services/distributeddataservice/framework/include/commonevent/data_change_event.h @@ -27,6 +27,7 @@ public: using TableProperties = std::map; struct EventInfo { TableProperties tableProperties; + bool isFull; }; DataChangeEvent(StoreInfo storeInfo, EventInfo evtInfo) @@ -40,6 +41,11 @@ public: { return info_.tableProperties; } + + bool IsFull() const + { + return info_.isFull; + } private: EventInfo info_; }; diff --git a/datamgr_service/services/distributeddataservice/framework/include/commonevent/data_sync_event.h b/datamgr_service/services/distributeddataservice/framework/include/commonevent/data_sync_event.h index 51e83a7d1cd0a778fd1cd814cb25ac1cb06da2d1..5ff60b65af1c0b1025ae90b8b2b49c3f22e17a36 100644 --- a/datamgr_service/services/distributeddataservice/framework/include/commonevent/data_sync_event.h +++ b/datamgr_service/services/distributeddataservice/framework/include/commonevent/data_sync_event.h @@ -26,8 +26,9 @@ public: FINISH, }; - DataSyncEvent(StoreInfo storeInfo, uint32_t syncMode, int32_t status) - : CloudEvent(DATA_SYNC, std::move(storeInfo)), syncMode_(syncMode), status_(std::move(status)) + DataSyncEvent(StoreInfo storeInfo, uint32_t syncMode, int32_t status, uint32_t traceId, uint32_t count = 0) + : CloudEvent(DATA_SYNC, std::move(storeInfo)), syncMode_(syncMode), status_(std::move(status)), + traceId_(traceId), count_(count) { } @@ -38,14 +39,26 @@ public: return syncMode_; } - uint32_t GetSyncStatus() const + int32_t GetSyncStatus() const { return status_; } + uint32_t GetTraceId() const + { + return traceId_; + } + + uint32_t GetCount() const + { + return count_; + } + private: uint32_t syncMode_; int32_t status_; + uint32_t traceId_; + uint32_t count_; }; } // OHOS::DistributedData #endif // OHOS_DISTRIBUTED_DATA_SERVICES_FRAMEWORK_COMMON_EVENT_DATA_SYNC_EVENT_H \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/framework/include/commonevent/set_searchable_event.h b/datamgr_service/services/distributeddataservice/framework/include/commonevent/set_searchable_event.h new file mode 100644 index 0000000000000000000000000000000000000000..833ddd82e88652ff291304504dd182917008d71d --- /dev/null +++ b/datamgr_service/services/distributeddataservice/framework/include/commonevent/set_searchable_event.h @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_DISTRIBUTED_DATA_SERVICES_FRAMEWORK_COMMON_EVENT_SET_SEARCHABLE_EVENT_H +#define OHOS_DISTRIBUTED_DATA_SERVICES_FRAMEWORK_COMMON_EVENT_SET_SEARCHABLE_EVENT_H + +#include "cloud/cloud_event.h" +#include "visibility.h" +namespace OHOS::DistributedData { +class API_EXPORT SetSearchableEvent : public CloudEvent { +public: + struct EventInfo { + bool isSearchable; + }; + + SetSearchableEvent(StoreInfo storeInfo, EventInfo evtInfo) + : CloudEvent(SET_SEARCHABLE, std::move(storeInfo)), info_(std::move(evtInfo)) + { + } + + ~SetSearchableEvent() override = default; + + bool GetIsSearchabl() const + { + return info_.isSearchable; + } +private: + EventInfo info_; +}; +} // OHOS::DistributedData +#endif // OHOS_DISTRIBUTED_DATA_SERVICES_FRAMEWORK_COMMON_EVENT_SET_SEARCHABLE_EVENT_H \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/framework/include/communication/connect_manager.h b/datamgr_service/services/distributeddataservice/framework/include/communication/connect_manager.h new file mode 100644 index 0000000000000000000000000000000000000000..5e9093c75964e43dbd631edb5bbe67062129005e --- /dev/null +++ b/datamgr_service/services/distributeddataservice/framework/include/communication/connect_manager.h @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_DISTRIBUTED_DATA_SERVICES_FRAMEWORK_COMMUNICATION_CONNECT_MANAGER_H +#define OHOS_DISTRIBUTED_DATA_SERVICES_FRAMEWORK_COMMUNICATION_CONNECT_MANAGER_H + +#include +#include +#include +#include + +#include "concurrent_map.h" +#include "visibility.h" +namespace OHOS { +namespace AppDistributedKv { +class API_EXPORT ConnectManager { +public: + using ConnectTask = std::function; + using CloseSessionTask = std::function; + using SessionCloseListener = std::function; + using SessionOpenListener = std::function; + + API_EXPORT static std::shared_ptr GetInstance(); + API_EXPORT static bool RegisterInstance(std::shared_ptr instance); + + API_EXPORT static bool CloseSession(const std::string &networkId); + API_EXPORT static bool RegisterCloseSessionTask(CloseSessionTask task); + + API_EXPORT static bool RegisterSessionCloseListener(const std::string &name, SessionCloseListener listener); + API_EXPORT static void UnRegisterSessionCloseListener(const std::string &name); + API_EXPORT static void OnSessionClose(const std::string &networkId); + + API_EXPORT static bool RegisterSessionOpenListener(const std::string &name, SessionOpenListener listener); + API_EXPORT static void UnRegisterSessionOpenListener(const std::string &name); + API_EXPORT static void OnSessionOpen(const std::string &networkId); + + ConnectManager() = default; + virtual ~ConnectManager() = default; + + virtual void OnStart(); + virtual void OnDestory(); + virtual int32_t ApplyConnect(const std::string &networkId, ConnectTask task); + +private: + static std::mutex mtx_; + static std::shared_ptr instance_; + static CloseSessionTask closeSessionTask_; + static ConcurrentMap sessionCloseListener_; + static ConcurrentMap sessionOpenListener_; +}; +} // namespace AppDistributedKv +} // namespace OHOS +#endif // OHOS_DISTRIBUTED_DATA_SERVICES_FRAMEWORK_COMMUNICATION_CONNECT_MANAGER_H \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/framework/include/directory/directory_manager.h b/datamgr_service/services/distributeddataservice/framework/include/directory/directory_manager.h index 737b7f5fc51814c10fe4455d0e83d0cc2055e3b2..e2642ec86373d546adf58d50add3586c189e894b 100644 --- a/datamgr_service/services/distributeddataservice/framework/include/directory/directory_manager.h +++ b/datamgr_service/services/distributeddataservice/framework/include/directory/directory_manager.h @@ -40,6 +40,7 @@ public: API_EXPORT std::vector GetVersions(); API_EXPORT void Initialize(const std::vector &strategies); API_EXPORT bool CreateDirectory(const std::string &path) const; + API_EXPORT bool DeleteDirectory(const char* path); private: using Action = std::string (DirectoryManager::*)(const StoreMetaData &) const; diff --git a/datamgr_service/services/distributeddataservice/framework/include/error/general_error.h b/datamgr_service/services/distributeddataservice/framework/include/error/general_error.h index 25c3cdf861df2ae428d4919c96bb66704375fcf4..f798cecfceb7cb07164ccbcb8b90f63fa41117bc 100644 --- a/datamgr_service/services/distributeddataservice/framework/include/error/general_error.h +++ b/datamgr_service/services/distributeddataservice/framework/include/error/general_error.h @@ -39,6 +39,19 @@ enum GeneralError : int32_t { E_RECORD_EXIST_CONFLICT, E_WITH_INVENTORY_DATA, E_SYNC_TASK_MERGED, + E_RECORD_NOT_FOUND, + E_RECORD_ALREADY_EXISTED, + E_DB_ERROR, + E_INVALID_VALUE_FIELDS, + E_INVALID_FIELD_TYPE, + E_CONSTRAIN_VIOLATION, + E_INVALID_FORMAT, + E_INVALID_QUERY_FORMAT, + E_INVALID_QUERY_FIELD, + E_TIME_OUT, + E_OVER_MAX_LIMITS, + E_SECURITY_LEVEL_ERROR, + E_FILE_NOT_EXIST, E_BUTT, }; } diff --git a/datamgr_service/services/distributeddataservice/framework/include/metadata/auto_launch_meta_data.h b/datamgr_service/services/distributeddataservice/framework/include/metadata/auto_launch_meta_data.h index de1da05c6dbd09d4a4e1a03440b711f3afdf12d1..293e3c2a021e9ac20ba9c5147f7feb503465191d 100644 --- a/datamgr_service/services/distributeddataservice/framework/include/metadata/auto_launch_meta_data.h +++ b/datamgr_service/services/distributeddataservice/framework/include/metadata/auto_launch_meta_data.h @@ -21,6 +21,7 @@ namespace OHOS::DistributedData { struct API_EXPORT AutoLaunchMetaData final : public Serializable { std::map> datas; + bool launchForCleanData = false; API_EXPORT AutoLaunchMetaData(); API_EXPORT ~AutoLaunchMetaData() = default; diff --git a/datamgr_service/services/distributeddataservice/framework/include/metadata/matrix_meta_data.h b/datamgr_service/services/distributeddataservice/framework/include/metadata/matrix_meta_data.h index ac6ee82a4ad4d76b0e6e06dcb150a26b986fdf84..909be37dfef9c25e273986d59a5f979fc3790b91 100644 --- a/datamgr_service/services/distributeddataservice/framework/include/metadata/matrix_meta_data.h +++ b/datamgr_service/services/distributeddataservice/framework/include/metadata/matrix_meta_data.h @@ -48,4 +48,4 @@ private: static constexpr const char *RMOTE_CONSISTENT = "Consistent"; }; } // namespace OHOS::DistributedData -#endif // OHOS_DISTRIBUTED_DATA_SERVICES_FRAMEWORK_METADATA_MATRIX_META_DATA_H +#endif // OHOS_DISTRIBUTED_DATA_SERVICES_FRAMEWORK_METADATA_MATRIX_META_DATA_H \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/framework/include/metadata/store_meta_data.h b/datamgr_service/services/distributeddataservice/framework/include/metadata/store_meta_data.h index 61bf6fd04c31526e1d0cfda90e3148fb8773a371..ff5e203a0cc300898fd77dace0d2b5ff4a33361b 100644 --- a/datamgr_service/services/distributeddataservice/framework/include/metadata/store_meta_data.h +++ b/datamgr_service/services/distributeddataservice/framework/include/metadata/store_meta_data.h @@ -45,6 +45,7 @@ struct API_EXPORT StoreMetaData final : public Serializable { int32_t area = 0; int32_t uid = -1; int32_t instanceId = 0; + int32_t haMode = 0; uint32_t tokenId = 0; std::string appId = ""; std::string appType = ""; @@ -57,6 +58,7 @@ struct API_EXPORT StoreMetaData final : public Serializable { std::string storeId = ""; std::string user = ""; std::string account = ""; + int32_t authType = 0; enum StoreType { STORE_KV_BEGIN = 0, diff --git a/datamgr_service/services/distributeddataservice/framework/include/screen/screen_manager.h b/datamgr_service/services/distributeddataservice/framework/include/screen/screen_manager.h new file mode 100644 index 0000000000000000000000000000000000000000..cbf7c8666ed2fe73674f5e5039b4ae1805b14908 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/framework/include/screen/screen_manager.h @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef DISTRIBUTEDDATAMGR_FRAMEWORK_SCREEN_LOCK_H +#define DISTRIBUTEDDATAMGR_FRAMEWORK_SCREEN_LOCK_H + +#include +#include +#include "visibility.h" + +namespace OHOS { +namespace DistributedData { +class ScreenManager { +public: + API_EXPORT static std::shared_ptr GetInstance(); + API_EXPORT static bool RegisterInstance(std::shared_ptr instance); + ScreenManager() = default; + virtual ~ScreenManager() = default; + virtual bool IsLocked(); + +private: + static std::mutex mutex_; + static std::shared_ptr instance_; +}; +} // namespace DistributedData +} // namespace OHOS +#endif //DISTRIBUTEDDATAMGR_FRAMEWORK_SCREEN_LOCK_H diff --git a/datamgr_service/services/distributeddataservice/framework/include/store/auto_cache.h b/datamgr_service/services/distributeddataservice/framework/include/store/auto_cache.h index 9fcf14a4c1e0bed70eacfa045f442bbf9a52a402..0ee41a97222dd952e1d31258874cbfa73fb070c7 100644 --- a/datamgr_service/services/distributeddataservice/framework/include/store/auto_cache.h +++ b/datamgr_service/services/distributeddataservice/framework/include/store/auto_cache.h @@ -50,9 +50,7 @@ public: API_EXPORT Stores GetStoresIfPresent(uint32_t tokenId, const std::string &storeName = ""); - API_EXPORT void CloseStore(uint32_t tokenId, const std::string &storeId); - - API_EXPORT void CloseStore(uint32_t tokenId); + API_EXPORT void CloseStore(uint32_t tokenId, const std::string &storeId = ""); API_EXPORT void CloseExcept(const std::set &users); @@ -69,11 +67,14 @@ private: void StartTimer(); struct Delegate : public GeneralWatcher { Delegate(GeneralStore *delegate, const Watchers &watchers, int32_t user, const StoreMetaData &meta); + Delegate(const Delegate& delegate); ~Delegate(); operator Store(); bool operator<(const Time &time) const; bool Close(); int32_t GetUser() const; + int32_t GetArea() const; + const std::string& GetDataDir() const; void SetObservers(const Watchers &watchers); int32_t OnChange(const Origin &origin, const PRIFields &primaryFields, ChangeInfo &&values) override; int32_t OnChange(const Origin &origin, const Fields &fields, ChangeData &&datas) override; @@ -84,7 +85,7 @@ private: GeneralStore *store_ = nullptr; Watchers watchers_; int32_t user_; - StoreMetaData meta_; + const StoreMetaData meta_; std::shared_mutex mutex_; }; @@ -96,6 +97,7 @@ private: ConcurrentMap> stores_; ConcurrentMap> disables_; Creator creators_[MAX_CREATOR_NUM]; + std::set disableStores_; }; } // namespace OHOS::DistributedData -#endif // OHOS_DISTRIBUTED_DATA_SERVICES_FRAMEWORK_STORE_STORE_AUTO_CACHE_H +#endif // OHOS_DISTRIBUTED_DATA_SERVICES_FRAMEWORK_STORE_STORE_AUTO_CACHE_H \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/framework/include/store/general_store.h b/datamgr_service/services/distributeddataservice/framework/include/store/general_store.h index 17f9db29d3fb274aff98922bda8bd6ecf21c2363..efc2db665a067774de5591daa374b65148cbbb9f 100644 --- a/datamgr_service/services/distributeddataservice/framework/include/store/general_store.h +++ b/datamgr_service/services/distributeddataservice/framework/include/store/general_store.h @@ -20,10 +20,12 @@ #include #include +#include "executor_pool.h" #include "snapshot/snapshot.h" #include "store/cursor.h" #include "store/general_value.h" #include "store/general_watcher.h" + namespace OHOS::DistributedData { class CloudDB; class AssetLoader; @@ -33,6 +35,7 @@ public: using Watcher = GeneralWatcher; using DetailAsync = GenAsync; using Devices = std::vector; + using Executor = ExecutorPool; enum SyncMode { NEARBY_BEGIN, NEARBY_PUSH = NEARBY_BEGIN, @@ -60,6 +63,15 @@ public: CLEAN_MODE_BUTT }; + enum Area : int32_t { + EL0, + EL1, + EL2, + EL3, + EL4, + EL5 + }; + static inline uint32_t MixMode(uint32_t syncMode, uint32_t highMode) { return syncMode | highMode; @@ -107,6 +119,8 @@ public: virtual ~GeneralStore() = default; + virtual void SetExecutor(std::shared_ptr executor) = 0; + virtual int32_t Bind(Database &database, const std::map &bindInfos, const CloudConfig &config) = 0; @@ -129,13 +143,14 @@ public: virtual int32_t Delete(const std::string &table, const std::string &sql, Values &&args) = 0; - virtual std::shared_ptr Query(const std::string &table, const std::string &sql, Values &&args) = 0; + virtual std::pair> Query(const std::string &table, const std::string &sql, + Values &&args) = 0; - virtual std::shared_ptr Query(const std::string &table, GenQuery &query) = 0; + virtual std::pair> Query(const std::string &table, GenQuery &query) = 0; virtual int32_t Sync(const Devices &devices, GenQuery &query, DetailAsync async, SyncParam &syncParm) = 0; - virtual std::shared_ptr PreSharing(GenQuery &query) = 0; + virtual std::pair> PreSharing(GenQuery &query) = 0; virtual int32_t Clean(const std::vector &devices, int32_t mode, const std::string &tableName) = 0; @@ -147,7 +162,7 @@ public: virtual int32_t UnregisterDetailProgressObserver() = 0; - virtual int32_t Close() = 0; + virtual int32_t Close(bool isForce = false) = 0; virtual int32_t AddRef() = 0; @@ -162,6 +177,10 @@ public: virtual void SetEqualIdentifier(const std::string &appId, const std::string &storeId) {}; virtual void SetConfig(const StoreConfig &storeConfig) {}; + + virtual std::pair LockCloudDB() = 0; + + virtual int32_t UnLockCloudDB() = 0; }; } // namespace OHOS::DistributedData #endif // OHOS_DISTRIBUTED_DATA_SERVICES_FRAMEWORK_STORE_GENERAL_STORE_H diff --git a/datamgr_service/services/distributeddataservice/framework/include/store/general_value.h b/datamgr_service/services/distributeddataservice/framework/include/store/general_value.h index aed711a11da17a77f569efd88a0d1ffaddef9197..f0bc9b2504a6e6901f5d7c3149329467a6d2471a 100644 --- a/datamgr_service/services/distributeddataservice/framework/include/store/general_value.h +++ b/datamgr_service/services/distributeddataservice/framework/include/store/general_value.h @@ -31,6 +31,15 @@ enum GenProgress { SYNC_FINISH, }; +enum SyncTriggerMode { + MODE_DEFAULT = 0, + MODE_PUSH, + MODE_ONLINE, + MODE_UNLOCK, + MODE_BROADCASTER, + MODE_CONSISTENCY, +}; + struct GenStatistic { uint32_t total; uint32_t success; @@ -47,6 +56,7 @@ struct GenProgressDetail { int32_t progress; int32_t code; int32_t dbCode; + uint64_t changeCount = 0; std::map details; }; @@ -86,6 +96,7 @@ struct SyncParam { int32_t mode; int32_t wait; bool isCompensation = false; + int32_t triggerMode = MODE_DEFAULT; }; using Assets = std::vector; diff --git a/datamgr_service/services/distributeddataservice/framework/include/utils/constant.h b/datamgr_service/services/distributeddataservice/framework/include/utils/constant.h index ff0dffda86d90b6ba67a86a1496cf625c2b24056..bfeaee6b31e945ef1564d6847c8c4742d08a76ae 100644 --- a/datamgr_service/services/distributeddataservice/framework/include/utils/constant.h +++ b/datamgr_service/services/distributeddataservice/framework/include/utils/constant.h @@ -42,6 +42,8 @@ public: API_EXPORT static bool NotEqual(bool first, bool second); + API_EXPORT static std::vector Split(const std::string &str, const std::string &delim); + template inline static constexpr bool is_pod = (std::is_standard_layout_v && std::is_trivial_v); diff --git a/datamgr_service/services/distributeddataservice/framework/metadata/auto_launch_meta_data.cpp b/datamgr_service/services/distributeddataservice/framework/metadata/auto_launch_meta_data.cpp index 3224368c419088697c3fa1b26573c653afc1306b..8ecf15edddbd50137803c917fbd2b5a8de6ec88c 100644 --- a/datamgr_service/services/distributeddataservice/framework/metadata/auto_launch_meta_data.cpp +++ b/datamgr_service/services/distributeddataservice/framework/metadata/auto_launch_meta_data.cpp @@ -25,12 +25,14 @@ AutoLaunchMetaData::AutoLaunchMetaData() bool AutoLaunchMetaData::Marshal(json& node) const { SetValue(node[GET_NAME(datas)], datas); + SetValue(node[GET_NAME(launchForCleanData)], launchForCleanData); return true; } bool AutoLaunchMetaData::Unmarshal(const json& node) { GetValue(node, GET_NAME(datas), datas); + GetValue(node, GET_NAME(launchForCleanData), launchForCleanData); return true; } diff --git a/datamgr_service/services/distributeddataservice/framework/metadata/meta_data_manager.cpp b/datamgr_service/services/distributeddataservice/framework/metadata/meta_data_manager.cpp index 1f77a82b3bc605606698ae13a39e441365a4c273..777a8d9396902324bc32be67d130ac4c25e667d3 100644 --- a/datamgr_service/services/distributeddataservice/framework/metadata/meta_data_manager.cpp +++ b/datamgr_service/services/distributeddataservice/framework/metadata/meta_data_manager.cpp @@ -29,8 +29,8 @@ public: using DBOrigin = DistributedDB::Origin; using DBChangeData = DistributedDB::ChangedData; using Type = DistributedDB::Type; - MetaObserver(std::shared_ptr metaStore, - std::shared_ptr filter, Observer observer, bool isLocal = false); + MetaObserver(std::shared_ptr metaStore, std::shared_ptr filter, Observer observer, + bool isLocal = false); virtual ~MetaObserver(); // Database change callback @@ -38,14 +38,15 @@ public: void OnChange(DBOrigin origin, const std::string &originalId, DBChangeData &&data) override; void HandleChanges(int32_t flag, std::vector> &priData); + private: std::shared_ptr metaStore_; std::shared_ptr filter_; Observer observer_; }; -MetaObserver::MetaObserver(std::shared_ptr metaStore, - std::shared_ptr filter, Observer observer, bool isLocal) +MetaObserver::MetaObserver( + std::shared_ptr metaStore, std::shared_ptr filter, Observer observer, bool isLocal) : metaStore_(std::move(metaStore)), filter_(std::move(filter)), observer_(std::move(observer)) { if (metaStore_ != nullptr) { @@ -78,8 +79,7 @@ std::vector MetaDataManager::Filter::GetKey() const return std::vector(); } -MetaDataManager::Filter::Filter(const std::string &pattern) - : pattern_(pattern) +MetaDataManager::Filter::Filter(const std::string &pattern) : pattern_(pattern) { } @@ -191,8 +191,8 @@ bool MetaDataManager::SaveMeta(const std::string &key, const Serializable &value cloudSyncer_(); } if (status != DistributedDB::DBStatus::OK) { - ZLOGE("failed! status:%{public}d isLocal:%{public}d, key:%{public}s", - status, isLocal, Anonymous::Change(key).c_str()); + ZLOGE("failed! status:%{public}d isLocal:%{public}d, key:%{public}s", status, isLocal, + Anonymous::Change(key).c_str()); } return status == DistributedDB::DBStatus::OK; } @@ -256,8 +256,7 @@ bool MetaDataManager::Sync(const std::vector &devices, OnComplete c if (!inited_ || devices.empty()) { return false; } - auto status = metaStore_->Sync( - devices, DistributedDB::SyncMode::SYNC_MODE_PUSH_PULL, [complete](auto &dbResults) { + auto status = metaStore_->Sync(devices, DistributedDB::SyncMode::SYNC_MODE_PUSH_PULL, [complete](auto &dbResults) { std::map results; for (auto &[uuid, status] : dbResults) { results.insert_or_assign(uuid, static_cast(status)); @@ -276,10 +275,9 @@ bool MetaDataManager::Subscribe(std::shared_ptr filter, Observer observe return false; } - return metaObservers_.ComputeIfAbsent( - "", [ this, &observer, &filter ](const std::string &key) -> auto { - return std::make_shared(metaStore_, filter, observer); - }); + return metaObservers_.ComputeIfAbsent("", [this, &observer, &filter](const std::string &key) -> auto { + return std::make_shared(metaStore_, filter, observer); + }); } bool MetaDataManager::Subscribe(std::string prefix, Observer observer, bool isLocal) @@ -288,10 +286,9 @@ bool MetaDataManager::Subscribe(std::string prefix, Observer observer, bool isLo return false; } - return metaObservers_.ComputeIfAbsent( - prefix, [ this, isLocal, &observer, &prefix ](const std::string &key) -> auto { - return std::make_shared(metaStore_, std::make_shared(prefix), observer, isLocal); - }); + return metaObservers_.ComputeIfAbsent(prefix, [this, isLocal, &observer, &prefix](const std::string &key) -> auto { + return std::make_shared(metaStore_, std::make_shared(prefix), observer, isLocal); + }); } bool MetaDataManager::Unsubscribe(std::string filter) diff --git a/datamgr_service/services/distributeddataservice/framework/metadata/store_meta_data.cpp b/datamgr_service/services/distributeddataservice/framework/metadata/store_meta_data.cpp index 219780e540921a7eda0179fb97100e71b8aa31cb..2a31c3805663a804983201ab3fd58b3ab95279eb 100644 --- a/datamgr_service/services/distributeddataservice/framework/metadata/store_meta_data.cpp +++ b/datamgr_service/services/distributeddataservice/framework/metadata/store_meta_data.cpp @@ -55,14 +55,14 @@ bool StoreMetaData::Marshal(json &node) const SetValue(node[GET_NAME(dataType)], dataType); SetValue(node[GET_NAME(enableCloud)], enableCloud); SetValue(node[GET_NAME(cloudAutoSync)], cloudAutoSync); - // compatible with the versions which lower than VERSION_TAG_0000 SetValue(node[GET_NAME(kvStoreType)], storeType); SetValue(node[GET_NAME(deviceAccountID)], user); SetValue(node[GET_NAME(userId)], account); SetValue(node[GET_NAME(UID)], uid); SetValue(node[GET_NAME(customDir)], customDir); - + SetValue(node[GET_NAME(authType)], authType); + SetValue(node[GET_NAME(haMode)], haMode); return true; } @@ -95,7 +95,6 @@ bool StoreMetaData::Unmarshal(const json &node) GetValue(node, GET_NAME(dataType), dataType); GetValue(node, GET_NAME(enableCloud), enableCloud); GetValue(node, GET_NAME(cloudAutoSync), cloudAutoSync); - // compatible with the older versions if (version < FIELD_CHANGED_TAG) { GetValue(node, GET_NAME(kvStoreType), storeType); @@ -104,6 +103,8 @@ bool StoreMetaData::Unmarshal(const json &node) GetValue(node, GET_NAME(userId), account); } GetValue(node, GET_NAME(customDir), customDir); + GetValue(node, GET_NAME(authType), authType); + GetValue(node, GET_NAME(haMode), haMode); return true; } @@ -120,7 +121,7 @@ StoreMetaData::StoreMetaData(const std::string &userId, const std::string &appId { } -StoreMetaData::StoreMetaData(const StoreInfo& storeInfo) +StoreMetaData::StoreMetaData(const StoreInfo &storeInfo) : instanceId(storeInfo.instanceId), bundleName(storeInfo.bundleName), storeId(storeInfo.storeName), user(std::to_string(storeInfo.user)) { @@ -141,7 +142,7 @@ bool StoreMetaData::operator==(const StoreMetaData &metaData) const tokenId == metaData.tokenId && instanceId == metaData.instanceId && appId == metaData.appId && appType == metaData.appType && bundleName == metaData.bundleName && dataDir == metaData.dataDir && storeId == metaData.storeId && user == metaData.user && deviceId == metaData.deviceId && - account == metaData.account); + account == metaData.account && authType == metaData.authType && haMode == metaData.haMode); } bool StoreMetaData::operator!=(const StoreMetaData &metaData) const diff --git a/datamgr_service/services/distributeddataservice/framework/screen/screen_manager.cpp b/datamgr_service/services/distributeddataservice/framework/screen/screen_manager.cpp new file mode 100644 index 0000000000000000000000000000000000000000..9f7698f5bb28cfd602cd7a453a58d1c907fc2c19 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/framework/screen/screen_manager.cpp @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define LOG_TAG "ScreenManager" +#include "screen/screen_manager.h" +#include "log_print.h" + +namespace OHOS::DistributedData { +std::mutex ScreenManager::mutex_; +std::shared_ptr ScreenManager::instance_ = nullptr; +std::shared_ptr ScreenManager::GetInstance() +{ + std::lock_guard lock(mutex_); + if (instance_ != nullptr) { + return instance_; + } + instance_ = std::make_shared(); + ZLOGW("no register, new instance!"); + return instance_; +} + +bool ScreenManager::RegisterInstance(std::shared_ptr instance) +{ + std::lock_guard lock(mutex_); + instance_ = std::move(instance); + return true; +} + +bool ScreenManager::IsLocked() +{ + return false; +} + +} // namespace OHOS::DistributedData \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/framework/store/auto_cache.cpp b/datamgr_service/services/distributeddataservice/framework/store/auto_cache.cpp index 0e5420b21bebe5fc50d716843d9d0d3573f24068..fa94983b91ccbb99362ae1f4c6ef2ed72ddb87aa 100644 --- a/datamgr_service/services/distributeddataservice/framework/store/auto_cache.cpp +++ b/datamgr_service/services/distributeddataservice/framework/store/auto_cache.cpp @@ -13,13 +13,15 @@ * limitations under the License. */ #define LOG_TAG "AutoCache" +#include "store/auto_cache.h" + #include + #include "changeevent/remote_change_event.h" #include "eventcenter/event_center.h" -#include "utils/anonymous.h" -#include "store/auto_cache.h" - #include "log_print.h" +#include "screenlock/screen_lock.h" +#include "utils/anonymous.h" namespace OHOS::DistributedData { AutoCache &AutoCache::GetInstance() { @@ -41,10 +43,12 @@ void AutoCache::Bind(std::shared_ptr executor) if (executor == nullptr || taskId_ != Executor::INVALID_TASK_ID) { return; } - executor_ = executor; + executor_ = std::move(executor); } -AutoCache::AutoCache() {} +AutoCache::AutoCache() +{ +} AutoCache::~AutoCache() { @@ -57,15 +61,22 @@ AutoCache::~AutoCache() AutoCache::Store AutoCache::GetStore(const StoreMetaData &meta, const Watchers &watchers) { Store store; - if (meta.storeType >= MAX_CREATOR_NUM || meta.storeType < 0 || !creators_[meta.storeType] || - disables_.ContainIf(meta.tokenId, [&meta](const std::set& stores) -> bool { + if ((meta.area >= GeneralStore::EL4 && ScreenManager::GetInstance()->IsLocked()) || + meta.storeType >= MAX_CREATOR_NUM || meta.storeType < 0 || !creators_[meta.storeType] || + disables_.ContainIf(meta.tokenId, [&meta](const std::set &stores) -> bool { return stores.count(meta.storeId) != 0; })) { return store; } - stores_.Compute(meta.tokenId, - [this, &meta, &watchers, &store](auto &, std::map &stores) -> bool { + stores_.Compute( + meta.tokenId, [this, &meta, &watchers, &store](auto &, std::map &stores) -> bool { + if (disableStores_.count(meta.dataDir) != 0) { + ZLOGW("store is closing, tokenId:0x%{public}x user:%{public}s" + "bundleName:%{public}s storeName:%{public}s", + meta.tokenId, meta.user.c_str(), meta.bundleName.c_str(), meta.GetStoreAlias().c_str()); + return !stores.empty(); + } auto it = stores.find(meta.storeId); if (it != stores.end()) { if (!watchers.empty()) { @@ -79,6 +90,7 @@ AutoCache::Store AutoCache::GetStore(const StoreMetaData &meta, const Watchers & ZLOGE("creator failed. storeName:%{public}s", meta.GetStoreAlias().c_str()); return !stores.empty(); } + dbStore->SetExecutor(executor_); auto result = stores.emplace(std::piecewise_construct, std::forward_as_tuple(meta.storeId), std::forward_as_tuple(dbStore, watchers, atoi(meta.user.c_str()), meta)); store = result.first->second; @@ -88,22 +100,23 @@ AutoCache::Store AutoCache::GetStore(const StoreMetaData &meta, const Watchers & return store; } -AutoCache::Stores AutoCache::GetStoresIfPresent(uint32_t tokenId, const std::string& storeName) +AutoCache::Stores AutoCache::GetStoresIfPresent(uint32_t tokenId, const std::string &storeName) { Stores stores; - stores_.ComputeIfPresent(tokenId, [&stores, &storeName](auto&, std::map& delegates) -> bool { - if (storeName.empty()) { - for (auto& [_, delegate] : delegates) { - stores.push_back(delegate); - } - } else { - auto it = delegates.find(storeName); - if (it != delegates.end()) { - stores.push_back(it->second); + stores_.ComputeIfPresent( + tokenId, [&stores, &storeName](auto &, std::map &delegates) -> bool { + if (storeName.empty()) { + for (auto &[_, delegate] : delegates) { + stores.push_back(delegate); + } + } else { + auto it = delegates.find(storeName); + if (it != delegates.end()) { + stores.push_back(it->second); + } } - } - return !stores.empty(); - }); + return !stores.empty(); + }); return stores; } @@ -131,31 +144,51 @@ void AutoCache::StartTimer() void AutoCache::CloseStore(uint32_t tokenId, const std::string &storeId) { - stores_.ComputeIfPresent(tokenId, [&storeId](auto &key, std::map &delegates) { - auto it = delegates.find(storeId); - if (it != delegates.end()) { - it->second.Close(); - delegates.erase(it); + ZLOGD("close store start, store:%{public}s, token:%{public}u", Anonymous::Change(storeId).c_str(), tokenId); + std::set storeIds; + std::list closeStores; + bool isScreenLocked = ScreenManager::GetInstance()->IsLocked(); + stores_.ComputeIfPresent(tokenId, + [this, &storeId, isScreenLocked, &storeIds, &closeStores](auto &key, auto &delegates) { + auto it = delegates.begin(); + while (it != delegates.end()) { + if ((storeId == it->first || storeId.empty()) && + (!isScreenLocked || it->second.GetArea() < GeneralStore::EL4) && + disableStores_.count(it->second.GetDataDir()) == 0) { + disableStores_.insert(it->second.GetDataDir()); + storeIds.insert(it->first); + closeStores.emplace(closeStores.end(), it->second); + } else { + ++it; + } + } + return !delegates.empty(); + }); + closeStores.clear(); + stores_.ComputeIfPresent(tokenId, [this, &storeIds](auto &key, auto &delegates) { + for (auto it = delegates.begin(); it != delegates.end();) { + if (storeIds.count(it->first) != 0) { + disableStores_.erase(it->second.GetDataDir()); + it = delegates.erase(it); + } else { + ++it; + } } return !delegates.empty(); }); } -void AutoCache::CloseStore(uint32_t tokenId) -{ - stores_.Erase(tokenId); -} - void AutoCache::CloseExcept(const std::set &users) { - stores_.EraseIf([&users](const auto &tokenId, std::map &delegates) { + bool isScreenLocked = ScreenManager::GetInstance()->IsLocked(); + stores_.EraseIf([&users, isScreenLocked](const auto &tokenId, std::map &delegates) { if (delegates.empty() || users.count(delegates.begin()->second.GetUser()) != 0) { return delegates.empty(); } for (auto it = delegates.begin(); it != delegates.end();) { // if the kv store is BUSY we wait more INTERVAL minutes again - if (!it->second.Close()) { + if ((isScreenLocked && it->second.GetArea() >= GeneralStore::EL4) || !it->second.Close()) { ++it; } else { it = delegates.erase(it); @@ -168,8 +201,8 @@ void AutoCache::CloseExcept(const std::set &users) void AutoCache::SetObserver(uint32_t tokenId, const std::string &storeId, const AutoCache::Watchers &watchers) { stores_.ComputeIfPresent(tokenId, [&storeId, &watchers](auto &key, auto &stores) { - ZLOGD("tokenId:0x%{public}x storeId:%{public}s observers:%{public}zu", key, Anonymous::Change(storeId).c_str(), - watchers.size()); + ZLOGD("tokenId:0x%{public}x storeId:%{public}s observers:%{public}zu", key, + Anonymous::Change(storeId).c_str(), watchers.size()); auto it = stores.find(storeId); if (it != stores.end()) { it->second.SetObservers(watchers); @@ -181,10 +214,12 @@ void AutoCache::SetObserver(uint32_t tokenId, const std::string &storeId, const void AutoCache::GarbageCollect(bool isForce) { auto current = std::chrono::steady_clock::now(); - stores_.EraseIf([¤t, isForce](auto &key, std::map &delegates) { + bool isScreenLocked = ScreenManager::GetInstance()->IsLocked(); + stores_.EraseIf([¤t, isForce, isScreenLocked](auto &key, std::map &delegates) { for (auto it = delegates.begin(); it != delegates.end();) { // if the store is BUSY we wait more INTERVAL minutes again - if ((isForce || it->second < current) && it->second.Close()) { + if ((!isScreenLocked || it->second.GetArea() < GeneralStore::EL4) && (isForce || it->second < current) && + it->second.Close()) { it = delegates.erase(it); } else { ++it; @@ -194,25 +229,24 @@ void AutoCache::GarbageCollect(bool isForce) }); } -void AutoCache::Enable(uint32_t tokenId, const std::string& storeId) +void AutoCache::Enable(uint32_t tokenId, const std::string &storeId) { - disables_.ComputeIfPresent(tokenId, [&storeId](auto key, std::set& stores) { + disables_.ComputeIfPresent(tokenId, [&storeId](auto key, std::set &stores) { stores.erase(storeId); return !(stores.empty() || storeId.empty()); }); } -void AutoCache::Disable(uint32_t tokenId, const std::string& storeId) +void AutoCache::Disable(uint32_t tokenId, const std::string &storeId) { - disables_.Compute(tokenId, [&storeId](auto key, std::set& stores) { + disables_.Compute(tokenId, [&storeId](auto key, std::set &stores) { stores.insert(storeId); return !stores.empty(); }); CloseStore(tokenId, storeId); } -AutoCache::Delegate::Delegate(GeneralStore *delegate, const Watchers &watchers, int32_t user, - const StoreMetaData &meta) +AutoCache::Delegate::Delegate(GeneralStore *delegate, const Watchers &watchers, int32_t user, const StoreMetaData &meta) : store_(delegate), watchers_(watchers), user_(user), meta_(meta) { time_ = std::chrono::steady_clock::now() + std::chrono::minutes(INTERVAL); @@ -221,11 +255,19 @@ AutoCache::Delegate::Delegate(GeneralStore *delegate, const Watchers &watchers, } } +AutoCache::Delegate::Delegate(const Delegate& delegate) +{ + store_ = delegate.store_; + if (store_ != nullptr) { + store_->AddRef(); + } +} + AutoCache::Delegate::~Delegate() { if (store_ != nullptr) { + store_->Close(true); store_->Unwatch(Origin::ORIGIN_ALL, *this); - store_->Close(); store_->Release(); store_ = nullptr; } @@ -248,7 +290,6 @@ bool AutoCache::Delegate::operator<(const AutoCache::Time &time) const bool AutoCache::Delegate::Close() { - std::unique_lock lock(mutex_); if (store_ != nullptr) { auto status = store_->Close(); if (status == Error::E_BUSY) { @@ -270,6 +311,16 @@ int32_t AutoCache::Delegate::GetUser() const return user_; } +int32_t AutoCache::Delegate::GetArea() const +{ + return meta_.area; +} + +const std::string& AutoCache::Delegate::GetDataDir() const +{ + return meta_.dataDir; +} + int32_t AutoCache::Delegate::OnChange(const Origin &origin, const PRIFields &primaryFields, ChangeInfo &&values) { std::vector tables; @@ -327,4 +378,4 @@ void AutoCache::Delegate::PostDataChange(const StoreMetaData &meta, const std::v auto evt = std::make_unique(RemoteChangeEvent::DATA_CHANGE, std::move(info)); EventCenter::GetInstance().PostEvent(std::move(evt)); } -} // namespace OHOS::DistributedData +} // namespace OHOS::DistributedData \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/framework/test/BUILD.gn b/datamgr_service/services/distributeddataservice/framework/test/BUILD.gn index 026e7a9009caa13a2f081273c579e2f63ed23e19..2476ad7d067766da1f672cdc2d011bdc445f867f 100644 --- a/datamgr_service/services/distributeddataservice/framework/test/BUILD.gn +++ b/datamgr_service/services/distributeddataservice/framework/test/BUILD.gn @@ -127,6 +127,11 @@ ohos_unittest("ServiceUtilsTest") { configs = [ ":module_private_config" ] + cflags = [ + "-Dprivate=public", + "-Dprotected=public", + ] + external_deps = [ "access_token:libaccesstoken_sdk", "access_token:libnativetoken", diff --git a/datamgr_service/services/distributeddataservice/framework/test/checker_manager_test.cpp b/datamgr_service/services/distributeddataservice/framework/test/checker_manager_test.cpp index 8dfc80b407d1cd53e3bdfcb16d808e382b864e5b..d95a7df7dd7ea8fd5c7df2730508f36e2aedf80e 100644 --- a/datamgr_service/services/distributeddataservice/framework/test/checker_manager_test.cpp +++ b/datamgr_service/services/distributeddataservice/framework/test/checker_manager_test.cpp @@ -170,4 +170,36 @@ HWTEST_F(CheckerManagerTest, BundleChecker, TestSize.Level0) AccessTokenKit::GetHapTokenInfo(storeInfo.tokenId, tokenInfo); ASSERT_EQ(Crypto::Sha256(tokenInfo.appID), CheckerManager::GetInstance().GetAppId(storeInfo)); ASSERT_TRUE(CheckerManager::GetInstance().IsValid(storeInfo)); +} + +/** +* @tc.name: IsDynamic +* @tc.desc: checker data type. +* @tc.type: FUNC +* @tc.require: +* @tc.author: +*/ +HWTEST_F(CheckerManagerTest, IsDynamic, TestSize.Level0) +{ + CheckerManager::StoreInfo storeInfo; + storeInfo.uid = 2000000; + storeInfo.tokenId = AccessTokenKit::GetHapTokenID(100, "ohos.test.demo", 0); + storeInfo.bundleName = "ohos.test.demo"; + ASSERT_FALSE(CheckerManager::GetInstance().IsDynamic(storeInfo)); +} + +/** +* @tc.name: IsStatic +* @tc.desc: checker data type. +* @tc.type: FUNC +* @tc.require: +* @tc.author: +*/ +HWTEST_F(CheckerManagerTest, IsStatic, TestSize.Level0) +{ + CheckerManager::StoreInfo storeInfo; + storeInfo.uid = 2000000; + storeInfo.tokenId = AccessTokenKit::GetHapTokenID(100, "ohos.test.demo", 0); + storeInfo.bundleName = "ohos.test.demo"; + ASSERT_FALSE(CheckerManager::GetInstance().IsStatic(storeInfo)); } \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/framework/test/cloud_test.cpp b/datamgr_service/services/distributeddataservice/framework/test/cloud_test.cpp index 15a83e104235b731a0521583754b6bfa4c21f29e..90232b1848192abf5a4b3256489172c0a59a247b 100644 --- a/datamgr_service/services/distributeddataservice/framework/test/cloud_test.cpp +++ b/datamgr_service/services/distributeddataservice/framework/test/cloud_test.cpp @@ -18,11 +18,13 @@ #include "serializable/serializable.h" #include "cloud/cloud_db.h" +#include "cloud/cloud_event.h" #include "cloud/cloud_info.h" #include "cloud/cloud_server.h" #include "cloud/schema_meta.h" #include "nlohmann/json.hpp" #include "utils/crypto.h" +#include "screen/screen_manager.h" #include "store/general_store.h" #include "store/general_value.h" #include "store/general_watcher.h" @@ -54,6 +56,22 @@ public: void TearDown(){}; }; +class CloudEventTest : public testing::Test { +public: + static void SetUpTestCase(void){}; + static void TearDownTestCase(void){}; + void SetUp(){}; + void TearDown(){}; +}; + +class ScreenManagerTest : public testing::Test { +public: + static void SetUpTestCase(void){}; + static void TearDownTestCase(void){}; + void SetUp(){}; + void TearDown(){}; +}; + class MockGeneralWatcher : public DistributedData::GeneralWatcher { public: int32_t OnChange(const Origin &origin, const PRIFields &primaryFields, @@ -207,13 +225,13 @@ HWTEST_F(CloudInfoTest, GetPrefix, TestSize.Level0) } /** -* @tc.name: CloudInfoTest +* @tc.name: CloudInfoTest001 * @tc.desc: Marshal and Unmarshal of CloudInfo. * @tc.type: FUNC * @tc.require: * @tc.author: Anvette */ -HWTEST_F(CloudInfoTest, CloudInfoTest, TestSize.Level0) +HWTEST_F(CloudInfoTest, CloudInfoTest001, TestSize.Level0) { CloudInfo cloudInfo1; cloudInfo1.user = 111; @@ -231,6 +249,33 @@ HWTEST_F(CloudInfoTest, CloudInfoTest, TestSize.Level0) EXPECT_EQ(Serializable::Marshall(cloudInfo1), Serializable::Marshall(cloudInfo1)); } +/** +* @tc.name: CloudInfoTest002 +* @tc.desc: Marshal and Unmarshal of CloudInfo. +* @tc.type: FUNC +* @tc.require: +* @tc.author: SQL +*/ +HWTEST_F(CloudInfoTest, CloudInfoTest002, TestSize.Level0) +{ + CloudInfo cloudInfo1; + cloudInfo1.user = 111; + cloudInfo1.id = "test1_id"; + cloudInfo1.totalSpace = 0; + cloudInfo1.remainSpace = 0; + cloudInfo1.enableCloud = false; + cloudInfo1.maxNumber = CloudInfo::DEFAULT_BATCH_NUMBER; + cloudInfo1.maxSize = CloudInfo::DEFAULT_BATCH_SIZE; + + Serializable::json node1; + cloudInfo1.Marshal(node1); + EXPECT_EQ(Serializable::Marshall(cloudInfo1), to_string(node1)); + + CloudInfo cloudInfo2; + cloudInfo2.Unmarshal(node1); + EXPECT_EQ(Serializable::Marshall(cloudInfo1), Serializable::Marshall(cloudInfo1)); +} + /** * @tc.name: AppInfoTest * @tc.desc: Marshal and Unmarshal of AppInfo. @@ -506,4 +551,32 @@ HWTEST_F(CloudInfoTest, SchemaMeta, TestSize.Level0) auto result2 = schemaMeta.GetHighVersion(); EXPECT_EQ(result2, metaVersion); } + +/** +* @tc.name: GetEventId +* @tc.desc: test GetEventId function +* @tc.type: FUNC +* @tc.require: +* @tc.author: +*/ +HWTEST_F(CloudEventTest, GetEventId, TestSize.Level0) +{ + int32_t evtId = 1; + StoreInfo info; + CloudEvent event(evtId, info); + auto ret = event.GetEventId(); + EXPECT_EQ(ret, evtId); +} + +/** +* @tc.name: IsLocked +* @tc.desc: test IsLocked function +* @tc.type: FUNC +* @tc.require: +* @tc.author: +*/ +HWTEST_F(ScreenManagerTest, IsLocked, TestSize.Level0) +{ + ASSERT_FALSE(ScreenManager::GetInstance()->IsLocked()); +} } // namespace OHOS::Test diff --git a/datamgr_service/services/distributeddataservice/framework/test/constant_test.cpp b/datamgr_service/services/distributeddataservice/framework/test/constant_test.cpp index a5147d3578d261d51426946ee8075eb51c6502ab..79e748d81f66fa64483ae72a1b63e41a5db7cda1 100644 --- a/datamgr_service/services/distributeddataservice/framework/test/constant_test.cpp +++ b/datamgr_service/services/distributeddataservice/framework/test/constant_test.cpp @@ -31,14 +31,10 @@ class ConstantTest : public testing::Test { */ HWTEST_F(ConstantTest, EqualTest, TestSize.Level1) { - bool result = Constant::Equal(true, true); - ASSERT_TRUE(result); - - result = Constant::Equal(true, false); - ASSERT_FALSE(result); - - result = OHOS::DistributedData::Constant::Equal(false, false); - ASSERT_TRUE(result); + ASSERT_TRUE(Constant::Equal(true, true)); + ASSERT_TRUE(Constant::Equal(false, false)); + ASSERT_FALSE(Constant::Equal(true, false)); + ASSERT_FALSE(Constant::Equal(false, true)); } /** @@ -50,12 +46,127 @@ HWTEST_F(ConstantTest, EqualTest, TestSize.Level1) */ HWTEST_F(ConstantTest, NotEqualTest, TestSize.Level1) { - bool result = Constant::NotEqual(true, true); - ASSERT_FALSE(result); + ASSERT_TRUE(Constant::NotEqual(true, false)); + ASSERT_TRUE(Constant::NotEqual(false, true)); + ASSERT_FALSE(Constant::NotEqual(true, true)); + ASSERT_FALSE(Constant::NotEqual(false, false)); +} + +/** +* @tc.name: SplitTest +* @tc.desc: SplitEmptyStringTest. +* @tc.type: FUNC +* @tc.require: +* @tc.author: ht +*/ +HWTEST_F(ConstantTest, SplitEmptyStringTest, TestSize.Level1) +{ + auto tokens = Constant::Split("", ","); + ASSERT_EQ(tokens.size(), 1); + EXPECT_EQ(tokens[0], ""); +} + +/** +* @tc.name: SplitTest +* @tc.desc: SplitStringOneDelimTest. +* @tc.type: FUNC +* @tc.require: +* @tc.author: ht +*/ +HWTEST_F(ConstantTest, SplitStringOneDelimTest, TestSize.Level1) +{ + auto tokens = Constant::Split("abc_123", "_"); + ASSERT_EQ(tokens.size(), 2); + EXPECT_EQ(tokens[0], "abc"); + EXPECT_EQ(tokens[1], "123"); +} + +/** +* @tc.name: SplitTest +* @tc.desc: SplitStringOneDelimAtBeginTest. +* @tc.type: FUNC +* @tc.require: +* @tc.author: ht +*/ +HWTEST_F(ConstantTest, SplitStringOneDelimAtBeginTest, TestSize.Level1) +{ + auto tokens = Constant::Split("#abc123", "#"); + ASSERT_EQ(tokens.size(), 2); + EXPECT_EQ(tokens[0], ""); + EXPECT_EQ(tokens[1], "abc123"); +} + +/** +* @tc.name: SplitTest +* @tc.desc: SplitStringOneDelimAtEndTest. +* @tc.type: FUNC +* @tc.require: +* @tc.author: ht +*/ +HWTEST_F(ConstantTest, SplitStringOneDelimAtEndTest, TestSize.Level1) +{ + auto tokens = Constant::Split("abc123!", "!"); + ASSERT_EQ(tokens.size(), 1); + EXPECT_EQ(tokens[0], "abc123"); +} + +/** +* @tc.name: SplitTest +* @tc.desc: SplitStringMutipleDelimTest. +* @tc.type: FUNC +* @tc.require: +* @tc.author: ht +*/ +HWTEST_F(ConstantTest, SplitStringMutipleDelimTest, TestSize.Level1) +{ + auto tokens = Constant::Split("abc!123!", "!"); + ASSERT_EQ(tokens.size(), 2); + EXPECT_EQ(tokens[0], "abc"); + EXPECT_EQ(tokens[1], "123"); +} + +/** +* @tc.name: SplitTest +* @tc.desc: SplitStringNoDelimTest. +* @tc.type: FUNC +* @tc.require: +* @tc.author: ht +*/ +HWTEST_F(ConstantTest, SplitStringNoDelimTest, TestSize.Level1) +{ + auto tokens = Constant::Split("abc123", "^"); + ASSERT_EQ(tokens.size(), 1); + EXPECT_EQ(tokens[0], "abc123"); +} - result = Constant::NotEqual(true, false); - ASSERT_TRUE(result); +/** +* @tc.name: SplitTest +* @tc.desc: SplitStringContinuousDelimTest. +* @tc.type: FUNC +* @tc.require: +* @tc.author: ht +*/ +HWTEST_F(ConstantTest, SplitStringContinuousDelimTest, TestSize.Level1) +{ + auto tokens = Constant::Split("abc$$$123", "$"); + ASSERT_EQ(tokens.size(), 4); + EXPECT_EQ(tokens[0], "abc"); + EXPECT_EQ(tokens[1], ""); + EXPECT_EQ(tokens[2], ""); + EXPECT_EQ(tokens[3], "123"); +} - result = Constant::NotEqual(false, false); - ASSERT_FALSE(result); +/** +* @tc.name: SplitTest +* @tc.desc: SplitStringLongDelimTest. +* @tc.type: FUNC +* @tc.require: +* @tc.author: ht +*/ +HWTEST_F(ConstantTest, SplitStringLongDelimTest, TestSize.Level1) +{ + auto tokens = Constant::Split("abc&&&123", "&&"); + ASSERT_EQ(tokens.size(), 2); + EXPECT_EQ(tokens[0], "abc"); + EXPECT_EQ(tokens[1], "&123"); } diff --git a/datamgr_service/services/distributeddataservice/framework/test/feature_test.cpp b/datamgr_service/services/distributeddataservice/framework/test/feature_test.cpp index 5490d0436f868921619b51a521769dab7ff7049b..befe45f828df7836d86bf798225986e104802132 100644 --- a/datamgr_service/services/distributeddataservice/framework/test/feature_test.cpp +++ b/datamgr_service/services/distributeddataservice/framework/test/feature_test.cpp @@ -257,4 +257,19 @@ HWTEST_F(FeatureSystemTest, FeatureTest002, TestSize.Level1) ret = mockFeature.OnSessionReady(device); EXPECT_EQ(ret, E_OK); } + +/** +* @tc.name: OnScreenUnlockedTest +* @tc.desc: test OnScreenUnlocked +* @tc.type: FUNC +* @tc.require: +* @tc.author: +*/ +HWTEST_F(FeatureSystemTest, OnScreenUnlockedTest, TestSize.Level1) +{ + MockFeature mockFeature; + int32_t user = 0; + int32_t ret = mockFeature.OnScreenUnlocked(user); + EXPECT_EQ(ret, E_OK); +} } // namespace OHOS::Test \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/framework/test/meta_data_test.cpp b/datamgr_service/services/distributeddataservice/framework/test/meta_data_test.cpp index 992b78a6100e93ca6abc7e89f308d8e2e4114380..1e99a72101f0c175eb990d9c3c23950a581952f4 100644 --- a/datamgr_service/services/distributeddataservice/framework/test/meta_data_test.cpp +++ b/datamgr_service/services/distributeddataservice/framework/test/meta_data_test.cpp @@ -45,7 +45,6 @@ public: static void SetUpTestCase() { std::shared_ptr executors = std::make_shared(NUM_MAX, NUM_MIN); - Bootstrap::GetInstance().LoadComponents(); Bootstrap::GetInstance().LoadDirectory(); Bootstrap::GetInstance().LoadCheckers(); KvStoreMetaManager::GetInstance().BindExecutor(executors); @@ -462,6 +461,16 @@ HWTEST_F(ServiceMetaDataTest, StoreMetaData006, TestSize.Level1) EXPECT_FALSE(storemetaData1 == storemetaData2); storemetaData2.isNeedCompress = true; EXPECT_TRUE(storemetaData1 == storemetaData2); + + storemetaData1.enableCloud = true; + EXPECT_FALSE(storemetaData1 == storemetaData2); + storemetaData2.enableCloud = true; + EXPECT_TRUE(storemetaData1 == storemetaData2); + + storemetaData1.cloudAutoSync = true; + EXPECT_FALSE(storemetaData1 == storemetaData2); + storemetaData2.cloudAutoSync = true; + EXPECT_TRUE(storemetaData1 == storemetaData2); } /** @@ -508,6 +517,16 @@ HWTEST_F(ServiceMetaDataTest, StoreMetaData007, TestSize.Level1) EXPECT_TRUE(storemetaData1 != storemetaData2); storemetaData2.isNeedCompress = true; EXPECT_FALSE(storemetaData1 != storemetaData2); + + storemetaData1.enableCloud = true; + EXPECT_TRUE(storemetaData1 != storemetaData2); + storemetaData2.enableCloud = true; + EXPECT_FALSE(storemetaData1 != storemetaData2); + + storemetaData1.cloudAutoSync = true; + EXPECT_TRUE(storemetaData1 != storemetaData2); + storemetaData2.cloudAutoSync = true; + EXPECT_FALSE(storemetaData1 != storemetaData2); } /** @@ -771,5 +790,8 @@ HWTEST_F(ServiceMetaDataTest, MatrixMetaData, TestSize.Level1) matrixMetaData3.deviceId = "DEVICE_ID"; EXPECT_TRUE(matrixMetaData1 != matrixMetaData3); EXPECT_FALSE(matrixMetaData1 != matrixMetaData2); + + std::string key = matrixMetaData3.GetConsistentKey(); + EXPECT_EQ(key, "MatrixMeta###DEVICE_ID###Consistent"); } } // namespace OHOS::Test \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/framework/test/store_meta_data_local_test.cpp b/datamgr_service/services/distributeddataservice/framework/test/store_meta_data_local_test.cpp index fa78ec5d180c78149209518b3a6888d0d26200fb..5527998edb49df72293b3a66f449c18b04b80b4f 100644 --- a/datamgr_service/services/distributeddataservice/framework/test/store_meta_data_local_test.cpp +++ b/datamgr_service/services/distributeddataservice/framework/test/store_meta_data_local_test.cpp @@ -37,22 +37,45 @@ public: HWTEST_F(StoreMetaDataLocalTest, EqualityOperatorTest, TestSize.Level1) { StoreMetaDataLocal metaData1; - metaData1.isAutoSync = true; - metaData1.isBackup = true; StoreMetaDataLocal metaData2; - metaData2.isAutoSync = true; - metaData2.isBackup = false; StoreMetaDataLocal metaData3; + + ASSERT_TRUE(metaData1 == metaData2); metaData3.isAutoSync = true; + ASSERT_FALSE(metaData1 == metaData3); metaData3.isBackup = true; + ASSERT_FALSE(metaData1 == metaData3); + ASSERT_TRUE(metaData1 != metaData3); + ASSERT_FALSE(metaData1 != metaData2); + metaData3.isDirty = true; + ASSERT_FALSE(metaData1 == metaData3); + metaData3.isEncrypt = true; + ASSERT_FALSE(metaData1 == metaData3); + metaData3.isPublic = true; + ASSERT_FALSE(metaData1 == metaData3); - ASSERT_FALSE(metaData1 == metaData2); - ASSERT_TRUE(metaData1 == metaData3); + metaData2.isAutoSync = true; + ASSERT_FALSE(metaData2 == metaData3); + metaData2.isBackup = true; + ASSERT_FALSE(metaData2 == metaData3); + metaData2.isDirty = true; + ASSERT_FALSE(metaData2 == metaData3); + metaData2.isEncrypt = true; ASSERT_FALSE(metaData2 == metaData3); + metaData2.isPublic = true; + ASSERT_TRUE(metaData2 == metaData3); - ASSERT_TRUE(metaData1 != metaData2); - ASSERT_FALSE(metaData1 != metaData3); - ASSERT_TRUE(metaData2 != metaData3); + metaData2.isBackup = false; + ASSERT_FALSE(metaData2 == metaData3); + metaData2.isBackup = true; + metaData2.isDirty = false; + ASSERT_FALSE(metaData2 == metaData3); + metaData2.isBackup = true; + metaData2.isEncrypt = false; + ASSERT_FALSE(metaData2 == metaData3); + metaData2.isBackup = true; + metaData2.isPublic = false; + ASSERT_FALSE(metaData2 == metaData3); } /** @@ -95,5 +118,8 @@ HWTEST_F(StoreMetaDataLocalTest, GetPolicy, TestSize.Level1) policy.index = 1; EXPECT_FALSE(metaData.HasPolicy(type)); EXPECT_TRUE(policy.IsValueEffect()); + type = UINT32_MAX; + policy = metaData.GetPolicy(type); + EXPECT_EQ(policy.type, type); } } // namespace OHOS::Test \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/framework/test/store_test.cpp b/datamgr_service/services/distributeddataservice/framework/test/store_test.cpp index 322b494a16783e5cd9b9cebe50b2af37f8e24e07..18db822c9d25d685d6ba43b3e7eda0c54cadb682 100644 --- a/datamgr_service/services/distributeddataservice/framework/test/store_test.cpp +++ b/datamgr_service/services/distributeddataservice/framework/test/store_test.cpp @@ -21,7 +21,6 @@ #include "metadata/store_meta_data.h" #include "rdb_query.h" #include "rdb_types.h" -#define private public #include "store/auto_cache.h" #include "store/general_store.h" #include "store/general_value.h" diff --git a/datamgr_service/services/distributeddataservice/framework/test/utils_test.cpp b/datamgr_service/services/distributeddataservice/framework/test/utils_test.cpp index e81c8602929c6005e33f62cc0f5c22d4bfff834c..7f5da600c25cbc89b3ea3b8fe54dd45b94acc4ed 100644 --- a/datamgr_service/services/distributeddataservice/framework/test/utils_test.cpp +++ b/datamgr_service/services/distributeddataservice/framework/test/utils_test.cpp @@ -21,6 +21,7 @@ #include "ipc_skeleton.h" #include "log_print.h" #include "utils/block_integer.h" +#include "utils/constant.h" #include "utils/converter.h" #include "utils/ref_count.h" #include "utils/endian_converter.h" @@ -130,6 +131,10 @@ HWTEST_F(RefCountTest, Constructortest, TestSize.Level2) std::function action = []() { }; RefCount refCountWithAction(action); EXPECT_TRUE(refCountWithAction); + + std::function actions; + RefCount refCountWithActions(actions); + EXPECT_TRUE(refCountWithActions); int num = 0; { RefCount refCount([&num]() { @@ -158,6 +163,8 @@ HWTEST_F(RefCountTest, Constructortest, TestSize.Level2) RefCount refCount6 = std::move(refCount2); refCount6 = std::move(refCount4); ASSERT_TRUE(refCount6); + + EXPECT_TRUE(refCount5 = refCount5); } ASSERT_EQ(num, 10); } @@ -189,4 +196,34 @@ HWTEST_F(ServiceUtilsTest, HostToNet, TestSize.Level1) uint64_t hostValue64 = NetToHost(NET_VALUE64); EXPECT_EQ(hostValue64, le64toh(NET_VALUE64)); } + +/** +* @tc.name: DCopy +* @tc.desc: test Constant::DCopy function. +* @tc.type: FUNC +* @tc.require: +* @tc.author: SQL +*/ +HWTEST_F(ServiceUtilsTest, DCopy, TestSize.Level1) +{ + Constant constant; + uint8_t *tag = nullptr; + size_t tagLen = 1; + uint8_t *src = nullptr; + size_t srcLen = 0; + + uint8_t tags[10]; + size_t tagsLen = 10; + uint8_t srcs[10]; + size_t srcsLen = 10; + + EXPECT_FALSE(constant.DCopy(tag, tagLen, src, srcLen)); + EXPECT_FALSE(constant.DCopy(tag, tagsLen, src, srcsLen)); + EXPECT_FALSE(constant.DCopy(tags, tagLen, src, srcLen)); + EXPECT_FALSE(constant.DCopy(tag, tagLen, srcs, srcLen)); + EXPECT_FALSE(constant.DCopy(tags, tagsLen, src, srcsLen)); + EXPECT_FALSE(constant.DCopy(tag, tagsLen, srcs, srcsLen)); + EXPECT_FALSE(constant.DCopy(tags, tagLen, srcs, srcLen)); + EXPECT_TRUE(constant.DCopy(tags, tagsLen, srcs, srcsLen)); +} } // namespace OHOS::Test \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/framework/utils/constant.cpp b/datamgr_service/services/distributeddataservice/framework/utils/constant.cpp index 2b834643cbe59d5dd4f04c0682daa77aee662560..6fedf3f619ba5780cdf8efc664fd0909a11082a9 100644 --- a/datamgr_service/services/distributeddataservice/framework/utils/constant.cpp +++ b/datamgr_service/services/distributeddataservice/framework/utils/constant.cpp @@ -51,6 +51,25 @@ std::string Constant::Join(const std::string &prefix, const std::string &separat return result; } +std::vector Constant::Split(const std::string &str, const std::string &delim) +{ + if (str.empty()) { + return { str }; + } + std::vector res; + size_t pos = 0; + while (pos < str.size()) { + size_t found = str.find(delim, pos); + if (found == std::string::npos) { + res.push_back(str.substr(pos)); + break; + } + res.push_back(str.substr(pos, found - pos)); + pos = found + delim.size(); + } + return res; +} + bool Constant::Equal(bool first, bool second) { return (first && second) || (!first && !second); diff --git a/datamgr_service/services/distributeddataservice/rust/extension/BUILD.gn b/datamgr_service/services/distributeddataservice/rust/extension/BUILD.gn index 302f89d6ae8a134e72da04fbb5b4b8f51cb83e98..cffbfca971c9d6f8ab4a3021e261c34cb8c9294b 100644 --- a/datamgr_service/services/distributeddataservice/rust/extension/BUILD.gn +++ b/datamgr_service/services/distributeddataservice/rust/extension/BUILD.gn @@ -56,6 +56,7 @@ ohos_shared_library("opencloudextension") { external_deps = [ "access_token:libaccesstoken_sdk", "hilog:libhilog", + "json:nlohmann_json_static", "kv_store:distributeddata_inner", ] subsystem_name = "distributeddatamgr" diff --git a/datamgr_service/services/distributeddataservice/rust/extension/cloud_cursor_impl.cpp b/datamgr_service/services/distributeddataservice/rust/extension/cloud_cursor_impl.cpp index fc42049721363bd52ea456965e617dc3683deeef..9d62cc7e10d5df567ca411db806f432f6b00760d 100644 --- a/datamgr_service/services/distributeddataservice/rust/extension/cloud_cursor_impl.cpp +++ b/datamgr_service/services/distributeddataservice/rust/extension/cloud_cursor_impl.cpp @@ -271,6 +271,7 @@ int32_t CloudCursorImpl::Get(const std::string &col, DBValue &value) auto it = std::find(names_.begin(), names_.end(), col); if (it == names_.end()) { value = GetExtend(vBucket, EXTEND_TO_KEYS[col]); + OhCloudExtValueBucketFree(vBucket); return DBErr::E_OK; } auto pair = GetData(vBucket); diff --git a/datamgr_service/services/distributeddataservice/rust/extension/cloud_db_impl.cpp b/datamgr_service/services/distributeddataservice/rust/extension/cloud_db_impl.cpp index 8cac03c467e183fbd785ff17dfb69b35b9cc7e56..da137619bfc423220f73d0095506c8fc6b57fc59 100644 --- a/datamgr_service/services/distributeddataservice/rust/extension/cloud_db_impl.cpp +++ b/datamgr_service/services/distributeddataservice/rust/extension/cloud_db_impl.cpp @@ -57,6 +57,8 @@ int32_t CloudDbImpl::BatchInsert(const std::string &table, DBVBuckets &&values, auto valIn = ExtensionUtil::Convert(std::move(inValues)); auto exdIn = ExtensionUtil::Convert(std::move(extends)); if (valIn.first == nullptr || exdIn.first == nullptr) { + OhCloudExtVectorFree(valIn.first); + OhCloudExtVectorFree(exdIn.first); return DBErr::E_ERROR; } auto status = OhCloudExtCloudDbBatchInsert(database_, reinterpret_cast(table.c_str()), @@ -74,6 +76,8 @@ int32_t CloudDbImpl::BatchUpdate(const std::string &table, DBVBuckets &&values, auto exdIn = ExtensionUtil::Convert(std::move(extends)); auto valIn = ExtensionUtil::Convert(std::move(values)); if (valIn.first == nullptr || exdIn.first == nullptr) { + OhCloudExtVectorFree(valIn.first); + OhCloudExtVectorFree(exdIn.first); return DBErr::E_ERROR; } auto status = OhCloudExtCloudDbBatchUpdate(database_, reinterpret_cast(table.c_str()), @@ -91,6 +95,8 @@ int32_t CloudDbImpl::BatchUpdate(const std::string &table, DBVBuckets &&values, auto exdIn = ExtensionUtil::Convert(std::move(const_cast(extends))); auto valIn = ExtensionUtil::Convert(std::move(values)); if (valIn.first == nullptr || exdIn.first == nullptr) { + OhCloudExtVectorFree(valIn.first); + OhCloudExtVectorFree(exdIn.first); return DBErr::E_ERROR; } auto status = OhCloudExtCloudDbBatchUpdate(database_, reinterpret_cast(table.c_str()), @@ -100,14 +106,15 @@ int32_t CloudDbImpl::BatchUpdate(const std::string &table, DBVBuckets &&values, return ExtensionUtil::ConvertStatus(status); } -int32_t CloudDbImpl::BatchDelete(const std::string &table, const DBVBuckets &extends) +int32_t CloudDbImpl::BatchDelete(const std::string &table, DBVBuckets &extends) { - auto data = ExtensionUtil::Convert(std::move(const_cast(extends))); + auto data = ExtensionUtil::Convert(std::move(extends)); if (data.first == nullptr) { return DBErr::E_ERROR; } auto status = OhCloudExtCloudDbBatchDelete(database_, reinterpret_cast(table.c_str()), table.size(), data.first); + extends = ExtensionUtil::ConvertBuckets(data.first); OhCloudExtVectorFree(data.first); return ExtensionUtil::ConvertStatus(status); } diff --git a/datamgr_service/services/distributeddataservice/rust/extension/cloud_db_impl.h b/datamgr_service/services/distributeddataservice/rust/extension/cloud_db_impl.h index dee05c431e2a4e8c4f9929373ec9c0f9f2a0b82e..099bfaad0ddf004cbdee4b887f02f6a62eaafb12 100644 --- a/datamgr_service/services/distributeddataservice/rust/extension/cloud_db_impl.h +++ b/datamgr_service/services/distributeddataservice/rust/extension/cloud_db_impl.h @@ -35,7 +35,7 @@ public: int32_t BatchInsert(const std::string &table, DBVBuckets &&values, DBVBuckets &extends) override; int32_t BatchUpdate(const std::string &table, DBVBuckets &&values, DBVBuckets &extends) override; int32_t BatchUpdate(const std::string &table, DBVBuckets &&values, const DBVBuckets &extends) override; - int32_t BatchDelete(const std::string &table, const DBVBuckets &extends) override; + int32_t BatchDelete(const std::string &table, DBVBuckets &extends) override; std::shared_ptr Query(const std::string &table, const DBVBucket &extend) override; int32_t Lock() override; int32_t Heartbeat() override; diff --git a/datamgr_service/services/distributeddataservice/rust/ylong_cloud_extension/BUILD.gn b/datamgr_service/services/distributeddataservice/rust/ylong_cloud_extension/BUILD.gn index dd7526a6b1c81305cb9313cfa8861167032debe8..4ac4309e2d1eaddbf0913f5d67b31a297be5cb77 100644 --- a/datamgr_service/services/distributeddataservice/rust/ylong_cloud_extension/BUILD.gn +++ b/datamgr_service/services/distributeddataservice/rust/ylong_cloud_extension/BUILD.gn @@ -22,7 +22,6 @@ ohos_rust_shared_ffi("ylong_cloud_extension") { subsystem_name = "distributeddatamgr" part_name = "datamgr_service" - branch_protector_ret = "pac_ret" sanitize = { cfi = true cfi_cross_dso = true @@ -39,18 +38,23 @@ ohos_rust_shared_ffi("ylong_cloud_extension") { ] } -ohos_rust_unittest("rust_ylong_cloud_ext_unit_test") { - module_out_path = - "distributeddatamgr/datamgr_service/services/rust/ylong_cloud_extension" - sources = [ "src/lib.rs" ] - - external_deps = [ - "hilog:hilog_rust", - "ipc:ipc_rust", - ] - deps = [ - ":ylong_cloud_extension", - "../connect_adapter:conn_adapter", - ] - rustflags = [ "--cfg=feature=\"test_server_ready\"" ] +if (use_clang_coverage) { + group("rust_ylong_cloud_ext_unit_test") { + } +} else { + ohos_rust_unittest("rust_ylong_cloud_ext_unit_test") { + module_out_path = + "distributeddatamgr/datamgr_service/services/rust/ylong_cloud_extension" + sources = [ "src/lib.rs" ] + + external_deps = [ + "hilog:hilog_rust", + "ipc:ipc_rust", + ] + deps = [ + ":ylong_cloud_extension", + "../connect_adapter:conn_adapter", + ] + rustflags = [ "--cfg=feature=\"test_server_ready\"" ] + } } diff --git a/datamgr_service/services/distributeddataservice/rust/ylong_cloud_extension/src/ipc_conn/function.rs b/datamgr_service/services/distributeddataservice/rust/ylong_cloud_extension/src/ipc_conn/function.rs index f68387e7e1c69043a866e947a46cc7e2045a7bc7..522b80e1449494ac40e466068e6893364d2b468e 100644 --- a/datamgr_service/services/distributeddataservice/rust/ylong_cloud_extension/src/ipc_conn/function.rs +++ b/datamgr_service/services/distributeddataservice/rust/ylong_cloud_extension/src/ipc_conn/function.rs @@ -31,7 +31,7 @@ pub(crate) enum AssetLoaderFunc { } pub(crate) enum CloudServiceFunc { - ConnectAssetLoader = 1, + ConnectAssetLoader, ConnectDatabase, GetAppBriefInfo, GetServiceInfo, diff --git a/datamgr_service/services/distributeddataservice/service/BUILD.gn b/datamgr_service/services/distributeddataservice/service/BUILD.gn index f2b756ecbf2b4a1290b0b5dc05c36400e70744cc..df0103f75aba67c183d2af4e8c77b3dbb4869258 100644 --- a/datamgr_service/services/distributeddataservice/service/BUILD.gn +++ b/datamgr_service/services/distributeddataservice/service/BUILD.gn @@ -68,6 +68,7 @@ ohos_shared_library("distributeddatasvc") { "${kv_store_distributeddb_path}", ] sources = [ + "${dataobject_path}/frameworks/innerkitsimpl/src/object_radar_reporter.cpp", "backup/src/backup_manager.cpp", "bootstrap/src/bootstrap.cpp", "cloud/cloud_service_impl.cpp", @@ -80,6 +81,7 @@ ohos_shared_library("distributeddatasvc") { "common/value_proxy.cpp", "common/xcollie.cpp", "config/src/config_factory.cpp", + "config/src/model/app_id_mapping_config.cpp", "config/src/model/backup_config.cpp", "config/src/model/checker_config.cpp", "config/src/model/cloud_config.cpp", @@ -101,7 +103,6 @@ ohos_shared_library("distributeddatasvc") { "kvdb/query_helper.cpp", "kvdb/upgrade.cpp", "kvdb/user_delegate.cpp", - "matrix/src/auto_sync_matrix.cpp", "matrix/src/device_matrix.cpp", "matrix/src/matrix_event.cpp", "object/object_asset_loader.cpp", diff --git a/datamgr_service/services/distributeddataservice/service/CMakeLists.txt b/datamgr_service/services/distributeddataservice/service/CMakeLists.txt index 0781c718e82367a1c100dd1495015a3b0261ebdc..31fe3b6a040a28a2aa8098f36ebe4be95dcb2f18 100644 --- a/datamgr_service/services/distributeddataservice/service/CMakeLists.txt +++ b/datamgr_service/services/distributeddataservice/service/CMakeLists.txt @@ -5,7 +5,7 @@ set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++1y -fno-rtti -fvisibility=hidden -D_GNU_SOURCE") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fdata-sections -fPIC -fpic -ffunction-sections -D_GLIBC_MOCK") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wl,--no-as-needed -ldl") -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wa,-mbig-obj") +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wa,-mbig-obj -Wenum-compare") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wformat=0 -fpermissive -Wattributes") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fprofile-arcs -ftest-coverage") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-error=deprecated-declarations -Wno-deprecated-declarations") diff --git a/datamgr_service/services/distributeddataservice/service/backup/src/backup_manager.cpp b/datamgr_service/services/distributeddataservice/service/backup/src/backup_manager.cpp index 1de16accbae411b7b9134adcc900a0a6a4b0090f..be05b0be00f1340427ff2c7ff2f2ad4343641dd9 100644 --- a/datamgr_service/services/distributeddataservice/service/backup/src/backup_manager.cpp +++ b/datamgr_service/services/distributeddataservice/service/backup/src/backup_manager.cpp @@ -15,9 +15,10 @@ #define LOG_TAG "BackupManager" #include "backup_manager.h" +#include + #include #include -#include #include "backuprule/backup_rule_manager.h" #include "crypto_manager.h" @@ -53,13 +54,12 @@ void BackupManager::Init() { std::vector metas; MetaDataManager::GetInstance().LoadMeta( - StoreMetaData::GetPrefix({DeviceManagerAdapter::GetInstance().GetLocalDevice().uuid}), metas, true); + StoreMetaData::GetPrefix({ DeviceManagerAdapter::GetInstance().GetLocalDevice().uuid }), metas, true); for (auto &meta : metas) { if (!meta.isBackup || meta.isDirty) { - continue; + continue; } - auto backupPath = - DirectoryManager::GetInstance().GetStoreBackupPath(meta) + "/" + AUTO_BACKUP_NAME; + auto backupPath = DirectoryManager::GetInstance().GetStoreBackupPath(meta) + "/" + AUTO_BACKUP_NAME; switch (GetClearType(meta)) { case ROLLBACK: RollBackData(backupPath); @@ -171,8 +171,7 @@ void BackupManager::KeepData(const std::string &path) CopyFile(path, backupPath, true); } -void BackupManager::SaveData( - const std::string &path, const std::string &key, const SecretKeyMetaData &secretKey) +void BackupManager::SaveData(const std::string &path, const std::string &key, const SecretKeyMetaData &secretKey) { auto tmpPath = path + BACKUP_TMP_POSTFIX; auto backupPath = path + BACKUP_BK_POSTFIX; @@ -249,8 +248,7 @@ void BackupManager::CleanData(const std::string &path) * */ BackupManager::ClearType BackupManager::GetClearType(const StoreMetaData &meta) { - auto backupFile = - DirectoryManager::GetInstance().GetStoreBackupPath(meta) + "/" + AUTO_BACKUP_NAME; + auto backupFile = DirectoryManager::GetInstance().GetStoreBackupPath(meta) + "/" + AUTO_BACKUP_NAME; auto dbKey = meta.GetSecretKey(); auto backupKey = meta.GetBackupSecretKey(); auto bkFile = backupFile + BACKUP_BK_POSTFIX; @@ -289,7 +287,7 @@ void BackupManager::CopyFile(const std::string &oldPath, const std::string &newP } else { fout.open(newPath, std::ios_base::out | std::ios_base::trunc); } - char buf[COPY_SIZE] = {0}; + char buf[COPY_SIZE] = { 0 }; while (fin.good()) { fin.read(buf, COPY_SIZE); fout.write(buf, fin.gcount()); diff --git a/datamgr_service/services/distributeddataservice/service/bootstrap/include/bootstrap.h b/datamgr_service/services/distributeddataservice/service/bootstrap/include/bootstrap.h index 967ad0976e3fe9da45b7ace4171c6b30ba0a084d..50b86fd88dfa0ae9221c5c6fbf0c0f56b9e25c22 100644 --- a/datamgr_service/services/distributeddataservice/service/bootstrap/include/bootstrap.h +++ b/datamgr_service/services/distributeddataservice/service/bootstrap/include/bootstrap.h @@ -31,6 +31,7 @@ public: API_EXPORT void LoadDirectory(); API_EXPORT void LoadCloud(); API_EXPORT void LoadBackup(std::shared_ptr executors); + API_EXPORT void LoadAppIdMappings(); private: static constexpr const char *DEFAULT_LABEL = "distributeddata"; static constexpr const char *DEFAULT_META = "service_meta"; diff --git a/datamgr_service/services/distributeddataservice/service/bootstrap/src/bootstrap.cpp b/datamgr_service/services/distributeddataservice/service/bootstrap/src/bootstrap.cpp index 8ef60d480e2152bf81dc0bcaafbf7e7fee2a1616..3dda8f457ec897ed05ae5b399b181cd8c1f3542a 100644 --- a/datamgr_service/services/distributeddataservice/service/bootstrap/src/bootstrap.cpp +++ b/datamgr_service/services/distributeddataservice/service/bootstrap/src/bootstrap.cpp @@ -24,6 +24,7 @@ #include "config_factory.h" #include "directory/directory_manager.h" #include "log_print.h" +#include "app_id_mapping/app_id_mapping_config_manager.h" namespace OHOS { namespace DistributedData { Bootstrap &Bootstrap::GetInstance() @@ -167,5 +168,18 @@ void Bootstrap::LoadCloud() } CloudConfigManager::GetInstance().Initialize(infos); } + +void Bootstrap::LoadAppIdMappings() +{ + auto *appIdMapping = ConfigFactory::GetInstance().GetAppIdMappingConfig(); + if (appIdMapping == nullptr) { + return; + } + std::vector infos; + for (auto &info : *appIdMapping) { + infos.push_back({ info.srcAppId, info.dstAppId }); + } + AppIdMappingConfigManager::GetInstance().Initialize(infos); +} } // namespace DistributedData } // namespace OHOS diff --git a/datamgr_service/services/distributeddataservice/service/cloud/cloud_service_impl.cpp b/datamgr_service/services/distributeddataservice/service/cloud/cloud_service_impl.cpp index 76237bc9fd9bc1079a79bb5d86fea8a3f757711b..f48a1f651bed90c8240bb491bbab541190cb62d8 100644 --- a/datamgr_service/services/distributeddataservice/service/cloud/cloud_service_impl.cpp +++ b/datamgr_service/services/distributeddataservice/service/cloud/cloud_service_impl.cpp @@ -19,6 +19,7 @@ #include #include + #include "accesstoken_kit.h" #include "account/account_delegate.h" #include "checker/checker_manager.h" @@ -28,6 +29,7 @@ #include "cloud/sharing_center.h" #include "cloud_value_util.h" #include "communicator/device_manager_adapter.h" +#include "device_matrix.h" #include "dfx/radar_reporter.h" #include "eventcenter/event_center.h" #include "hap_token_info.h" @@ -112,11 +114,13 @@ int32_t CloudServiceImpl::EnableCloud(const std::string &id, const std::map(CloudEvent::CLEAN_DATA, storeInfo)); auto status = store->Clean({}, action, ""); if (status != E_OK) { ZLOGW("remove device data status:%{public}d, user:%{public}d, bundleName:%{public}s, " "storeId:%{public}s", status, static_cast(user), meta.bundleName.c_str(), meta.GetStoreAlias().c_str()); + } else { + ZLOGD("clean success, user:%{public}d, bundleName:%{public}s, storeId:%{public}s", + static_cast(user), meta.bundleName.c_str(), meta.GetStoreAlias().c_str()); } } } @@ -262,6 +281,7 @@ int32_t CloudServiceImpl::CheckNotifyConditions(const std::string &id, const std return INVALID_ARGUMENT; } if (!cloudInfo.enableCloud) { + ZLOGD("cloud is disabled, id:%{public}s, app:%{public}s ", Anonymous::Change(id).c_str(), bundleName.c_str()); return CLOUD_DISABLE; } if (!cloudInfo.Exist(bundleName)) { @@ -269,6 +289,8 @@ int32_t CloudServiceImpl::CheckNotifyConditions(const std::string &id, const std return INVALID_ARGUMENT; } if (!cloudInfo.apps[bundleName].cloudSwitch) { + ZLOGD("cloud switch is disabled, id:%{public}s, app:%{public}s ", Anonymous::Change(id).c_str(), + bundleName.c_str()); return CLOUD_DISABLE_SWITCH; } return SUCCESS; @@ -317,18 +339,14 @@ std::map> CloudServiceImpl::GetDbInfoFromE return dbInfos; } -bool CloudServiceImpl::DoKvCloudSync(int32_t userId, const std::string &bundleName) +bool CloudServiceImpl::DoKvCloudSync(int32_t userId, const std::string &bundleName, int32_t triggerMode) { auto stores = CheckerManager::GetInstance().GetDynamicStores(); auto staticStores = CheckerManager::GetInstance().GetStaticStores(); stores.insert(stores.end(), staticStores.begin(), staticStores.end()); - bool found = false; - for (auto &store : stores) { - if (store.bundleName == bundleName || bundleName.empty()) { - found = true; - break; - } - } + bool found = std::any_of(stores.begin(), stores.end(), [&bundleName](const CheckerManager::StoreInfo &storeInfo) { + return bundleName.empty() || storeInfo.bundleName == bundleName; + }); if (!found) { return found; } @@ -339,8 +357,10 @@ bool CloudServiceImpl::DoKvCloudSync(int32_t userId, const std::string &bundleNa Account::GetInstance()->QueryForegroundUsers(users); } for (auto user : users) { - for (auto &store : stores) { - syncManager_.DoCloudSync(SyncManager::SyncInfo(user, store.bundleName, store.storeId)); + for (const auto &store : stores) { + int32_t mode = (store.bundleName != bundleName && triggerMode == MODE_PUSH) ? MODE_CONSISTENCY + : triggerMode; + syncManager_.DoCloudSync(SyncManager::SyncInfo(user, store.bundleName, store.storeId, {}, mode)); } } return found; @@ -381,9 +401,6 @@ int32_t CloudServiceImpl::NotifyDataChange(const std::string &eventId, const std ZLOGD("invalid user:%{public}d", user); return INVALID_ARGUMENT; } - if (DoKvCloudSync(cloudInfo.user, exData.info.bundleName)) { - continue; - } auto schemaKey = CloudInfo::GetSchemaKey(user, exData.info.bundleName); SchemaMeta schemaMeta; if (!MetaDataManager::GetInstance().LoadMeta(schemaKey, schemaMeta, true)) { @@ -395,9 +412,9 @@ int32_t CloudServiceImpl::NotifyDataChange(const std::string &eventId, const std ZLOGE("GetDbInfoFromExtraData failed, empty database info."); return INVALID_ARGUMENT; } - for (auto &dbInfo : dbInfos) { + for (const auto &dbInfo : dbInfos) { syncManager_.DoCloudSync( - SyncManager::SyncInfo(cloudInfo.user, exData.info.bundleName, dbInfo.first, dbInfo.second)); + SyncManager::SyncInfo(cloudInfo.user, exData.info.bundleName, dbInfo.first, dbInfo.second, MODE_PUSH)); } } return SUCCESS; @@ -407,7 +424,7 @@ std::map CloudServiceImpl::ExecuteStatistics(const const CloudInfo &cloudInfo, const SchemaMeta &schemaMeta) { std::map result; - for (auto& database : schemaMeta.databases) { + for (auto &database : schemaMeta.databases) { if (storeId.empty() || database.alias == storeId) { StoreMetaData meta; meta.bundleName = schemaMeta.bundleName; @@ -438,7 +455,7 @@ StatisticInfos CloudServiceImpl::QueryStatistics(const StoreMetaData &storeMetaD return infos; } infos.reserve(database.tables.size()); - for (auto& table : database.tables) { + for (const auto &table : database.tables) { auto [success, info] = QueryTableStatistic(table.name, store); if (success) { info.table = table.alias; @@ -453,8 +470,8 @@ std::pair CloudServiceImpl::QueryTableStatistic(const std:: { StatisticInfo info; auto sql = BuildStatisticSql(tableName); - auto cursor = store->Query(tableName, sql, {}); - if (cursor == nullptr || cursor->GetCount() != 1 || cursor->MoveToFirst() != E_OK) { + auto [errCode, cursor] = store->Query(tableName, sql, {}); + if (errCode != E_OK || cursor == nullptr || cursor->GetCount() != 1 || cursor->MoveToFirst() != E_OK) { ZLOGE("query failed, cursor is nullptr or move to first failed,tableName:%{public}s", Anonymous::Change(tableName).c_str()); return { false, info }; @@ -519,7 +536,7 @@ std::pair> CloudServiceImpl::Quer int32_t CloudServiceImpl::SetGlobalCloudStrategy(Strategy strategy, const std::vector &values) { - if (strategy < 0 || strategy >= Strategy::STRATEGY_BUTT) { + if (strategy >= Strategy::STRATEGY_BUTT) { ZLOGE("invalid strategy:%{public}d, size:%{public}zu", strategy, values.size()); return INVALID_ARGUMENT; } @@ -644,13 +661,7 @@ int32_t CloudServiceImpl::OnUserChange(uint32_t code, const std::string &user, c return E_OK; } -int32_t CloudServiceImpl::OnScreenUnlocked(int32_t user) -{ - DoKvCloudSync(user); - return E_OK; -} - -int32_t CloudServiceImpl::OnReady(const std::string& device) +int32_t CloudServiceImpl::OnReady(const std::string &device) { if (device != DeviceManagerAdapter::CLOUD_DEVICE_UUID) { return SUCCESS; @@ -661,7 +672,7 @@ int32_t CloudServiceImpl::OnReady(const std::string& device) return SUCCESS; } for (auto user : users) { - DoKvCloudSync(user); + DoKvCloudSync(user, "", MODE_ONLINE); Execute(GenTask(0, user, { WORK_CLOUD_INFO_UPDATE, WORK_SCHEMA_UPDATE, WORK_DO_CLOUD_SYNC, WORK_SUB })); } return SUCCESS; @@ -700,15 +711,17 @@ std::pair CloudServiceImpl::GetCloudInfoFromServer(int32_t u CloudInfo cloudInfo; cloudInfo.user = userId; if (!DmAdapter::GetInstance().IsNetworkAvailable()) { + ZLOGD("network is not available"); return { NETWORK_ERROR, cloudInfo }; } auto instance = CloudServer::GetInstance(); if (instance == nullptr) { + ZLOGD("cloud server is nullptr, user:%{public}d", userId); return { SERVER_UNAVAILABLE, cloudInfo }; } cloudInfo = instance->GetServerInfo(cloudInfo.user); if (!cloudInfo.IsValid()) { - ZLOGE("cloud is empty, user%{public}d", cloudInfo.user); + ZLOGE("cloud is empty, user:%{public}d", cloudInfo.user); return { CLOUD_INFO_INVALID, cloudInfo }; } return { SUCCESS, cloudInfo }; @@ -731,7 +744,7 @@ bool CloudServiceImpl::UpdateCloudInfo(int32_t user) ZLOGE("user:%{public}d, status:%{public}d", user, status); return false; } - ZLOGI("[server] id:%{public}s, enableCloud:%{pubic}d, user:%{public}d, app size:%{public}zu", + ZLOGI("[server] id:%{public}s, enableCloud:%{public}d, user:%{public}d, app size:%{public}zu", Anonymous::Change(cloudInfo.id).c_str(), cloudInfo.enableCloud, cloudInfo.user, cloudInfo.apps.size()); CloudInfo oldInfo; if (!MetaDataManager::GetInstance().LoadMeta(cloudInfo.GetKey(), oldInfo, true)) { @@ -758,7 +771,6 @@ bool CloudServiceImpl::UpdateSchema(int32_t user) { auto [status, cloudInfo] = GetCloudInfo(user); if (status != SUCCESS) { - ZLOGE("user:%{public}d, status:%{public}d", user, status); return false; } auto keys = cloudInfo.GetSchemaKey(); @@ -786,6 +798,7 @@ std::pair CloudServiceImpl::GetAppSchemaFromServer(int32_t { SchemaMeta schemaMeta; if (!DmAdapter::GetInstance().IsNetworkAvailable()) { + ZLOGD("network is not available"); return { NETWORK_ERROR, schemaMeta }; } auto instance = CloudServer::GetInstance(); @@ -823,13 +836,14 @@ ExecutorPool::Task CloudServiceImpl::GenTask(int32_t retry, int32_t user, Handle return; } if (!DmAdapter::GetInstance().IsNetworkAvailable()) { + ZLOGD("network is not available"); return; } bool finished = true; std::vector users; if (user == 0) { auto account = Account::GetInstance(); - finished = !(account == nullptr) && account->QueryUsers(users); + finished = (account != nullptr) && account->QueryUsers(users); } else { users.push_back(user); } @@ -968,7 +982,7 @@ void CloudServiceImpl::CloudShare(const Event &event) } std::pair> CloudServiceImpl::PreShare( - const StoreInfo& storeInfo, GenQuery& query) + const StoreInfo &storeInfo, GenQuery &query) { StoreMetaData meta(storeInfo); meta.deviceId = DmAdapter::GetInstance().GetLocalDevice().uuid; @@ -982,7 +996,7 @@ std::pair> CloudServiceImpl::P ZLOGE("store null, storeId:%{public}s", meta.GetStoreAlias().c_str()); return { GeneralError::E_ERROR, nullptr }; } - return { GeneralError::E_OK, store->PreSharing(query) }; + return store->PreSharing(query); } bool CloudServiceImpl::ReleaseUserInfo(int32_t user) @@ -997,7 +1011,8 @@ bool CloudServiceImpl::ReleaseUserInfo(int32_t user) bool CloudServiceImpl::DoCloudSync(int32_t user) { - syncManager_.DoCloudSync(user); + SyncManager::SyncInfo info(user); + syncManager_.DoCloudSync(info); return true; } @@ -1101,8 +1116,8 @@ std::map CloudServiceImpl::ConvertAction(const std::map> CloudServiceImpl::AllocResourceAndShare( - const std::string& storeId, const DistributedRdb::PredicatesMemo& predicates, - const std::vector& columns, const Participants& participants) + const std::string &storeId, const DistributedRdb::PredicatesMemo &predicates, + const std::vector &columns, const Participants &participants) { auto tokenId = IPCSkeleton::GetCallingTokenID(); auto hapInfo = GetHapInfo(tokenId); @@ -1390,7 +1405,7 @@ void CloudServiceImpl::InitSubTask(const Subscription &sub, uint64_t minInterval if (executor == nullptr) { return; } - ZLOGI("Subscription Info, subTask:%{public}" PRIu64", user:%{public}d", subTask_, sub.userId); + ZLOGI("Subscription Info, subTask:%{public}" PRIu64 ", user:%{public}d", subTask_, sub.userId); expire = expire - TIME_BEFORE_SUB; // before 12 hours auto now = static_cast(duration_cast(system_clock::now().time_since_epoch()).count()); Duration delay = milliseconds(std::max(expire > now ? expire - now : 0, minInterval)); @@ -1408,7 +1423,7 @@ void CloudServiceImpl::InitSubTask(const Subscription &sub, uint64_t minInterval int32_t CloudServiceImpl::SetCloudStrategy(Strategy strategy, const std::vector &values) { - if (strategy < 0 || strategy >= Strategy::STRATEGY_BUTT) { + if (strategy >= Strategy::STRATEGY_BUTT) { ZLOGE("invalid strategy:%{public}d, size:%{public}zu", strategy, values.size()); return INVALID_ARGUMENT; } diff --git a/datamgr_service/services/distributeddataservice/service/cloud/cloud_service_impl.h b/datamgr_service/services/distributeddataservice/service/cloud/cloud_service_impl.h index 76476c25305e91d5981d65f3d29ea9b261f64b7f..212b7780d55104c42e564bde3d37af56f54ed0f5 100644 --- a/datamgr_service/services/distributeddataservice/service/cloud/cloud_service_impl.h +++ b/datamgr_service/services/distributeddataservice/service/cloud/cloud_service_impl.h @@ -18,12 +18,13 @@ #include #include + #include "cloud/cloud_event.h" #include "cloud/cloud_extra_data.h" #include "cloud/cloud_info.h" #include "cloud/schema_meta.h" -#include "cloud/subscription.h" #include "cloud/sharing_center.h" +#include "cloud/subscription.h" #include "cloud_service_stub.h" #include "feature/static_acts.h" #include "sync_manager.h" @@ -67,7 +68,6 @@ public: int32_t OnInitialize() override; int32_t OnBind(const BindInfo &info) override; int32_t OnUserChange(uint32_t code, const std::string &user, const std::string &account) override; - int32_t OnScreenUnlocked(int32_t user) override; int32_t OnReady(const std::string &device) override; int32_t Offline(const std::string &device) override; @@ -158,7 +158,7 @@ private: const DistributedData::ExtraData &extraData, const SchemaMeta &schemaMeta); std::shared_ptr GetSharingHandle(const HapInfo& hapInfo); bool GetStoreMetaData(StoreMetaData &meta); - bool DoKvCloudSync(int32_t userId, const std::string &bundleName = ""); + bool DoKvCloudSync(int32_t userId, const std::string &bundleName = "", int32_t triggerMode = 0); using SaveStrategy = int32_t (*)(const std::vector &values, const HapInfo &hapInfo); static const SaveStrategy STRATEGY_SAVERS[Strategy::STRATEGY_BUTT]; diff --git a/datamgr_service/services/distributeddataservice/service/cloud/cloud_service_stub.cpp b/datamgr_service/services/distributeddataservice/service/cloud/cloud_service_stub.cpp index 3fc501882a929211bd9ee09381295247a51a0115..ef5c357e711f63778537a15a1744aacf50294072 100644 --- a/datamgr_service/services/distributeddataservice/service/cloud/cloud_service_stub.cpp +++ b/datamgr_service/services/distributeddataservice/service/cloud/cloud_service_stub.cpp @@ -15,14 +15,14 @@ #define LOG_TAG "CloudServiceStub" #include "cloud_service_stub.h" -#include "ipc_skeleton.h" -#include "cloud_types_util.h" #include "cloud/cloud_config_manager.h" +#include "cloud_types_util.h" +#include "ipc_skeleton.h" #include "log_print.h" #include "permission/permission_validator.h" #include "rdb_types.h" -#include "utils/anonymous.h" #include "tokenid_kit.h" +#include "utils/anonymous.h" namespace OHOS::CloudData { using namespace DistributedData; using namespace OHOS::Security::AccessToken; @@ -89,7 +89,7 @@ int32_t CloudServiceStub::OnEnableCloud(MessageParcel &data, MessageParcel &repl return IPC_STUB_INVALID_DATA_ERR; } std::map localSwitches; - for (auto &[bundle, status] : switches) { + for (const auto &[bundle, status] : switches) { localSwitches.insert_or_assign(CloudConfigManager::GetInstance().ToLocal(bundle), status); } auto result = EnableCloud(id, localSwitches); @@ -129,7 +129,7 @@ int32_t CloudServiceStub::OnClean(MessageParcel &data, MessageParcel &reply) return IPC_STUB_INVALID_DATA_ERR; } std::map localActions; - for (auto &[bundle, action] : actions) { + for (const auto &[bundle, action] : actions) { localActions.insert_or_assign(CloudConfigManager::GetInstance().ToLocal(bundle), action); } auto result = Clean(id, localActions); diff --git a/datamgr_service/services/distributeddataservice/service/cloud/cloud_types_util.h b/datamgr_service/services/distributeddataservice/service/cloud/cloud_types_util.h index 4e151fa9eedc757dcd99554740f6f67f525e3fdc..afb74b6cba7fab57226c791f35e205c389a03d87 100644 --- a/datamgr_service/services/distributeddataservice/service/cloud/cloud_types_util.h +++ b/datamgr_service/services/distributeddataservice/service/cloud/cloud_types_util.h @@ -17,7 +17,6 @@ #define OHOS_DISTRIBUTED_DATA_SERVICES_CLOUD_CLOUD_TYPES_UTIL_H #include "cloud_types.h" #include "itypes_util.h" -#include "cloud_types.h" #include "values_bucket.h" namespace OHOS::ITypesUtil { @@ -69,4 +68,4 @@ bool Marshalling(const CloudSyncInfo &input, MessageParcel &data); template<> bool Unmarshalling(CloudSyncInfo &output, MessageParcel &data); } // namespace OHOS::ITypesUtil -#endif // OHOS_DISTRIBUTED_DATA_SERVICES_CLOUD_CLOUD_TYPES_UTIL_H +#endif // OHOS_DISTRIBUTED_DATA_SERVICES_CLOUD_CLOUD_TYPES_UTIL_H \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/cloud/cloud_value_util.h b/datamgr_service/services/distributeddataservice/service/cloud/cloud_value_util.h index 4b3e9cdcdd2f2d3fccce78a3f34ebfbe80233ca5..b9d66441ced0525f97d76d6937963569d4ed4c80 100644 --- a/datamgr_service/services/distributeddataservice/service/cloud/cloud_value_util.h +++ b/datamgr_service/services/distributeddataservice/service/cloud/cloud_value_util.h @@ -16,9 +16,9 @@ #ifndef OHOS_DISTRIBUTED_DATA_SERVICES_CLOUD_CLOUD_VALUE_UTIL_H #define OHOS_DISTRIBUTED_DATA_SERVICES_CLOUD_CLOUD_VALUE_UTIL_H +#include "cloud/sharing_center.h" #include "cloud_service.h" #include "cloud_types.h" -#include "cloud/sharing_center.h" #include "error/general_error.h" namespace OHOS::CloudData { @@ -53,4 +53,4 @@ Status Convert(CenterCode code); Status Convert(GenErr code); } // namespace SharingUtil } // namespace OHOS::CloudData -#endif // OHOS_DISTRIBUTED_DATA_SERVICES_CLOUD_CLOUD_VALUE_UTIL_H +#endif // OHOS_DISTRIBUTED_DATA_SERVICES_CLOUD_CLOUD_VALUE_UTIL_H \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/cloud/sync_manager.cpp b/datamgr_service/services/distributeddataservice/service/cloud/sync_manager.cpp index c52040fa2adaa60ccb2f59510ef536dec96f2b6e..40f41784feb55fe88e45be94bf84cf0c22910270 100644 --- a/datamgr_service/services/distributeddataservice/service/cloud/sync_manager.cpp +++ b/datamgr_service/services/distributeddataservice/service/cloud/sync_manager.cpp @@ -18,10 +18,13 @@ #include #include "account/account_delegate.h" +#include "bootstrap.h" +#include "checker/checker_manager.h" #include "cloud/cloud_server.h" #include "cloud/schema_meta.h" #include "cloud/sync_event.h" #include "cloud_value_util.h" +#include "cloud/cloud_lock_event.h" #include "device_manager_adapter.h" #include "dfx/radar_reporter.h" #include "eventcenter/event_center.h" @@ -40,8 +43,9 @@ using Account = OHOS::DistributedKv::AccountDelegate; using DmAdapter = OHOS::DistributedData::DeviceManagerAdapter; using Defer = EventCenter::Defer; std::atomic SyncManager::genId_ = 0; -SyncManager::SyncInfo::SyncInfo(int32_t user, const std::string &bundleName, const Store &store, const Tables &tables) - : user_(user), bundleName_(bundleName) +SyncManager::SyncInfo::SyncInfo( + int32_t user, const std::string &bundleName, const Store &store, const Tables &tables, int32_t triggerMode) + : user_(user), bundleName_(bundleName), triggerMode_(triggerMode) { if (!store.empty()) { tables_[store] = tables; @@ -90,6 +94,11 @@ void SyncManager::SyncInfo::SetCompensation(bool isCompensation) isCompensation_ = isCompensation; } +void SyncManager::SyncInfo::SetTriggerMode(int32_t triggerMode) +{ + triggerMode_ = triggerMode; +} + void SyncManager::SyncInfo::SetError(int32_t code) const { if (async_) { @@ -132,10 +141,56 @@ bool SyncManager::SyncInfo::Contains(const std::string &storeName) return tables_.empty() || tables_.find(storeName) != tables_.end(); } +std::function SyncManager::GetLockChangeHandler() +{ + return [](const Event &event) { + auto &evt = static_cast(event); + auto storeInfo = evt.GetStoreInfo(); + auto callback = evt.GetCallback(); + if (callback == nullptr) { + ZLOGE("callback is nullptr. bundleName: %{public}s, storeName: %{public}s, user: %{public}d.", + storeInfo.bundleName.c_str(), Anonymous::Change(storeInfo.storeName).c_str(), storeInfo.user); + return; + } + StoreMetaData meta(storeInfo); + meta.deviceId = DmAdapter::GetInstance().GetLocalDevice().uuid; + if (!MetaDataManager::GetInstance().LoadMeta(meta.GetKey(), meta, true)) { + ZLOGE("not found meta. bundleName: %{public}s, storeName: %{public}s, user: %{public}d.", + storeInfo.bundleName.c_str(), Anonymous::Change(storeInfo.storeName).c_str(), storeInfo.user); + return; + } + auto store = GetStore(meta, storeInfo.user); + if (store == nullptr) { + ZLOGE("failed to get store. bundleName: %{public}s, storeName: %{public}s, user: %{public}d.", + storeInfo.bundleName.c_str(), Anonymous::Change(storeInfo.storeName).c_str(), storeInfo.user); + return; + } + if (evt.GetEventId() == CloudEvent::LOCK_CLOUD_CONTAINER) { + auto [result, expiredTime] = store->LockCloudDB(); + callback(result, expiredTime); + } else { + auto result = store->UnLockCloudDB(); + callback(result, 0); + } + }; +} + SyncManager::SyncManager() { + EventCenter::GetInstance().Subscribe(CloudEvent::LOCK_CLOUD_CONTAINER, GetLockChangeHandler()); + EventCenter::GetInstance().Subscribe(CloudEvent::UNLOCK_CLOUD_CONTAINER, GetLockChangeHandler()); EventCenter::GetInstance().Subscribe(CloudEvent::LOCAL_CHANGE, GetClientChangeHandler()); syncStrategy_ = std::make_shared(); + auto metaName = Bootstrap::GetInstance().GetProcessLabel(); + kvApps_.insert(std::move(metaName)); + auto stores = CheckerManager::GetInstance().GetStaticStores(); + for (auto &store : stores) { + kvApps_.insert(std::move(store.bundleName)); + } + stores = CheckerManager::GetInstance().GetDynamicStores(); + for (auto &store : stores) { + kvApps_.insert(std::move(store.bundleName)); + } } SyncManager::~SyncManager() @@ -210,10 +265,11 @@ GeneralError SyncManager::IsValid(SyncInfo &info, CloudInfo &cloud) return E_OK; } -std::function SyncManager::GetPostEventTask(const std::vector &schemas, CloudInfo &cloud, +std::function SyncManager::GetPostEventTask(const std::vector &schemas, CloudInfo &cloud, SyncInfo &info, bool retry) { return [this, &cloud, &info, &schemas, retry]() { + bool isPostEvent = false; for (auto &schema : schemas) { if (!cloud.IsOn(schema.bundleName)) { continue; @@ -234,12 +290,18 @@ std::function SyncManager::GetPostEventTask(const std::vector(std::move(storeInfo), SyncEvent::EventInfo{ syncParam, retry, std::move(query), info.async_ }); EventCenter::GetInstance().PostEvent(std::move(evt)); + isPostEvent = true; } } + if (!isPostEvent) { + ZLOGE("schema is invalid, user: %{public}d", cloud.user); + info.SetError(E_ERROR); + } + return isPostEvent; }; } @@ -261,9 +323,7 @@ ExecutorPool::Task SyncManager::GetSyncTask(int32_t times, bool retry, RefCount UpdateStartSyncInfo(cloudSyncInfos); auto code = IsValid(info, cloud); if (code != E_OK) { - for (const auto &[queryKey, syncId] : cloudSyncInfos) { - UpdateFinishSyncInfo(queryKey, syncId, code); - } + BatchUpdateFinishState(cloudSyncInfos, code); return; } @@ -273,7 +333,8 @@ ExecutorPool::Task SyncManager::GetSyncTask(int32_t times, bool retry, RefCount UpdateSchema(info); schemas = GetSchemaMeta(cloud, info.bundleName_); if (schemas.empty()) { - retryer(RETRY_INTERVAL, E_RETRY_TIMEOUT, Status::SCHEMA_INVALID); + retryer(RETRY_INTERVAL, E_RETRY_TIMEOUT, E_CLOUD_DISABLED); + BatchUpdateFinishState(cloudSyncInfos, E_CLOUD_DISABLED); return; } } @@ -282,9 +343,10 @@ ExecutorPool::Task SyncManager::GetSyncTask(int32_t times, bool retry, RefCount info.user_ = 0; } auto task = GetPostEventTask(schemas, cloud, info, retry); - if (task != nullptr) { - task(); + if (task != nullptr && task()) { + return; } + BatchUpdateFinishState(cloudSyncInfos, E_ERROR); }; } @@ -312,25 +374,30 @@ std::function SyncManager::GetSyncHandler(Retryer retryer) auto store = GetStore(meta, storeInfo.user); if (store == nullptr) { ZLOGE("store null, storeId:%{public}s", meta.GetStoreAlias().c_str()); - DoExceptionalCallback(async, details, storeInfo); - return; + return DoExceptionalCallback(async, details, storeInfo); } ZLOGD("database:<%{public}d:%{public}s:%{public}s> sync start", storeInfo.user, storeInfo.bundleName.c_str(), meta.GetStoreAlias().c_str()); RadarReporter::Report( - { storeInfo.bundleName.c_str(), CLOUD_SYNC, TRIGGER_SYNC, storeInfo.syncId }, "GetSyncHandler", BEGIN); + { storeInfo.bundleName.c_str(), CLOUD_SYNC, TRIGGER_SYNC, storeInfo.syncId, evt.GetTriggerMode() }, + "GetSyncHandler", BEGIN); SyncParam syncParam = { evt.GetMode(), evt.GetWait(), evt.IsCompensation() }; auto status = store->Sync({ SyncInfo::DEFAULT_ID }, *(evt.GetQuery()), - evt.AutoRetry() ? RetryCallback(storeInfo, retryer) : GetCallback(evt.GetAsyncDetail(), storeInfo), + evt.AutoRetry() ? RetryCallback(storeInfo, retryer, evt.GetTriggerMode()) + : GetCallback(evt.GetAsyncDetail(), storeInfo, evt.GetTriggerMode()), syncParam); if (status != E_OK) { - int32_t errCode = status + GenStore::DB_ERR_OFFSET; - RadarReporter::Report({ storeInfo.bundleName.c_str(), CLOUD_SYNC, FINISH_SYNC, storeInfo.syncId, errCode }, - "GetSyncHandler", END); if (async) { detail.code = status; async(std::move(details)); } + UpdateFinishSyncInfo({ GetAccountId(storeInfo.user), storeInfo.bundleName, "" }, storeInfo.syncId, E_ERROR); + if (status == GeneralError::E_NOT_SUPPORT) { + return; + } + int32_t errCode = status + GenStore::DB_ERR_OFFSET; + RadarReporter::Report({ storeInfo.bundleName.c_str(), CLOUD_SYNC, FINISH_SYNC, storeInfo.syncId, + evt.GetTriggerMode(), false, errCode }, "GetSyncHandler", END); } }; } @@ -346,6 +413,7 @@ std::function SyncManager::GetClientChangeHandler() syncInfo.SetAsyncDetail(evt.GetAsyncDetail()); syncInfo.SetQuery(evt.GetQuery()); syncInfo.SetCompensation(evt.IsCompensation()); + syncInfo.SetTriggerMode(evt.GetTriggerMode()); auto times = evt.AutoRetry() ? RETRY_TIMES - CLIENT_RETRY_TIMES : RETRY_TIMES; executor_->Execute(GetSyncTask(times, evt.AutoRetry(), RefCount(), std::move(syncInfo))); }; @@ -360,7 +428,8 @@ SyncManager::Retryer SyncManager::GetRetryer(int32_t times, const SyncInfo &sync } info.SetError(code); RadarReporter::Report( - { info.bundleName_.c_str(), CLOUD_SYNC, FINISH_SYNC, info.syncId_, dbCode }, "GetRetryer", END); + { info.bundleName_.c_str(), CLOUD_SYNC, FINISH_SYNC, info.syncId_, info.triggerMode_, false, dbCode }, + "GetRetryer", END); return true; }; } @@ -371,7 +440,8 @@ SyncManager::Retryer SyncManager::GetRetryer(int32_t times, const SyncInfo &sync if (code == E_NO_SPACE_FOR_ASSET || code == E_RECODE_LIMIT_EXCEEDED) { info.SetError(code); RadarReporter::Report( - { info.bundleName_.c_str(), CLOUD_SYNC, FINISH_SYNC, info.syncId_, dbCode }, "GetRetryer", END); + { info.bundleName_.c_str(), CLOUD_SYNC, FINISH_SYNC, info.syncId_, info.triggerMode_, false, dbCode }, + "GetRetryer", END); return true; } @@ -479,7 +549,7 @@ AutoCache::Store SyncManager::GetStore(const StoreMetaData &meta, int32_t user, } SchemaMeta schemaMeta; std::string schemaKey = info.GetSchemaKey(meta.bundleName, meta.instanceId); - if (!MetaDataManager::GetInstance().LoadMeta(std::move(schemaKey), schemaMeta, true)) { + if (!MetaDataManager::GetInstance().LoadMeta(schemaKey, schemaMeta, true)) { ZLOGE("failed, no schema bundleName:%{public}s, storeId:%{public}s", meta.bundleName.c_str(), meta.GetStoreAlias().c_str()); return nullptr; @@ -523,7 +593,6 @@ std::vector> SyncManager::GetCloudSyncInfo(const ZLOGW("save cloud info fail, user: %{public}d", cloud.user); } } - if (info.bundleName_.empty()) { for (const auto &it : cloud.apps) { QueryKey queryKey{ .accountId = cloud.id, .bundleName = it.first, .storeId = "" }; @@ -546,9 +615,20 @@ void SyncManager::GetLastResults( } } +bool SyncManager::NeedSaveSyncInfo(const QueryKey &queryKey) +{ + if (queryKey.accountId.empty()) { + return false; + } + if (std::find(kvApps_.begin(), kvApps_.end(), queryKey.bundleName) != kvApps_.end()) { + return false; + } + return true; +} + int32_t SyncManager::QueryLastSyncInfo(const std::vector &queryKeys, QueryLastResults &results) { - for (auto &queryKey : queryKeys) { + for (const auto &queryKey : queryKeys) { std::string storeId = queryKey.storeId; QueryKey key{ .accountId = queryKey.accountId, .bundleName = queryKey.bundleName, .storeId = "" }; lastSyncInfos_.ComputeIfPresent( @@ -564,6 +644,9 @@ void SyncManager::UpdateStartSyncInfo(const std::vector(system_clock::now().time_since_epoch()).count(); for (const auto &[queryKey, syncId] : cloudSyncInfos) { + if (!NeedSaveSyncInfo(queryKey)) { + continue; + } lastSyncInfos_.Compute(queryKey, [id = syncId, startTime](auto &, std::map &val) { val[id] = { .startTime = startTime }; return !val.empty(); @@ -573,14 +656,21 @@ void SyncManager::UpdateStartSyncInfo(const std::vector &val) { + auto now = duration_cast(system_clock::now().time_since_epoch()).count(); for (auto iter = val.begin(); iter != val.end();) { - if (iter->first != syncId && iter->second.code != -1) { + bool isExpired = ((now - iter->second.startTime) >= EXPIRATION_TIME) && iter->second.code == -1; + if ((iter->first != syncId && ((iter->second.code != -1) || isExpired))) { iter = val.erase(iter); - } else { + } else if (iter->first == syncId) { iter->second.finishTime = duration_cast(system_clock::now().time_since_epoch()).count(); iter->second.code = code; iter++; + } else { + iter++; } } return true; @@ -588,9 +678,9 @@ void SyncManager::UpdateFinishSyncInfo(const QueryKey &queryKey, uint64_t syncId } std::function SyncManager::GetCallback(const GenAsync &async, - const StoreInfo &storeInfo) + const StoreInfo &storeInfo, int32_t triggerMode) { - return [this, async, storeInfo](const GenDetails &result) { + return [this, async, storeInfo, triggerMode](const GenDetails &result) { if (async != nullptr) { async(result); } @@ -606,6 +696,7 @@ std::function SyncManager::GetCallback(const Gen auto id = GetAccountId(storeInfo.user); if (id.empty()) { + ZLOGD("account id is empty"); return; } QueryKey queryKey{ @@ -617,8 +708,9 @@ std::function SyncManager::GetCallback(const Gen int32_t code = result.begin()->second.code; int32_t dbCode = (result.begin()->second.dbCode == GenStore::DB_ERR_OFFSET) ? 0 : result.begin()->second.dbCode; UpdateFinishSyncInfo(queryKey, storeInfo.syncId, code); - RadarReporter::Report( - { storeInfo.bundleName.c_str(), CLOUD_SYNC, FINISH_SYNC, storeInfo.syncId, dbCode }, "GetCallback", END); + RadarReporter::Report({ storeInfo.bundleName.c_str(), CLOUD_SYNC, FINISH_SYNC, storeInfo.syncId, triggerMode, + result.begin()->second.changeCount, dbCode }, + "GetCallback", END); }; } @@ -677,9 +769,9 @@ bool SyncManager::InitDefaultUser(int32_t &user) } std::function SyncManager::RetryCallback( - const StoreInfo &storeInfo, Retryer retryer) + const StoreInfo &storeInfo, Retryer retryer, int32_t triggerMode) { - return [this, retryer, storeInfo](const GenDetails &details) { + return [this, retryer, storeInfo, triggerMode](const GenDetails &details) { if (details.empty()) { ZLOGE("retry, details empty"); return; @@ -690,11 +782,21 @@ std::function SyncManager::Retr QueryKey queryKey{ GetAccountId(storeInfo.user), storeInfo.bundleName, "" }; UpdateFinishSyncInfo(queryKey, storeInfo.syncId, code); if (code == E_OK) { - RadarReporter::Report( - { storeInfo.bundleName.c_str(), CLOUD_SYNC, FINISH_SYNC, storeInfo.syncId }, "RetryCallback", END); + RadarReporter::Report({ storeInfo.bundleName.c_str(), CLOUD_SYNC, FINISH_SYNC, storeInfo.syncId, + triggerMode, details.begin()->second.changeCount }, + "RetryCallback", END); } } retryer(GetInterval(code), code, dbCode); }; } + +void SyncManager::BatchUpdateFinishState(const std::vector> &cloudSyncInfos, + int32_t code) +{ + for (const auto &[queryKey, syncId] : cloudSyncInfos) { + UpdateFinishSyncInfo(queryKey, syncId, code); + } +} + } // namespace OHOS::CloudData \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/cloud/sync_manager.h b/datamgr_service/services/distributeddataservice/service/cloud/sync_manager.h index e4d7b0e428569a5a4a595d7a209a0906bf823948..2aed28defc06b6dec157b01af17ffc9e6c6d575a 100644 --- a/datamgr_service/services/distributeddataservice/service/cloud/sync_manager.h +++ b/datamgr_service/services/distributeddataservice/service/cloud/sync_manager.h @@ -46,7 +46,8 @@ public: using Stores = std::vector; using Tables = std::vector; using MutliStoreTables = std::map; - SyncInfo(int32_t user, const std::string &bundleName = "", const Store &store = "", const Tables &tables = {}); + explicit SyncInfo(int32_t user, const std::string &bundleName = "", const Store &store = "", + const Tables &tables = {}, int32_t triggerMode = 0); SyncInfo(int32_t user, const std::string &bundleName, const Stores &stores); SyncInfo(int32_t user, const std::string &bundleName, const MutliStoreTables &tables); void SetMode(int32_t mode); @@ -55,6 +56,7 @@ public: void SetQuery(std::shared_ptr query); void SetError(int32_t code) const; void SetCompensation(bool isCompensation); + void SetTriggerMode(int32_t triggerMode); std::shared_ptr GenerateQuery(const std::string &store, const Tables &tables); bool Contains(const std::string &storeName); inline static constexpr const char *DEFAULT_ID = "default"; @@ -71,6 +73,7 @@ public: GenAsync async_; std::shared_ptr query_; bool isCompensation_ = false; + int32_t triggerMode_ = 0; }; SyncManager(); ~SyncManager(); @@ -93,13 +96,14 @@ private: using GenProgress = DistributedData::GenProgress; using GenDetails = DistributedData::GenDetails; - static constexpr ExecutorPool::Duration RETRY_INTERVAL = std::chrono::seconds(10); // second + static constexpr ExecutorPool::Duration RETRY_INTERVAL = std::chrono::seconds(10); // second static constexpr ExecutorPool::Duration LOCKED_INTERVAL = std::chrono::seconds(30); // second - static constexpr ExecutorPool::Duration BUSY_INTERVAL = std::chrono::seconds(180); // second - static constexpr int32_t RETRY_TIMES = 6; // normal retry - static constexpr int32_t CLIENT_RETRY_TIMES = 3; // normal retry - static constexpr uint64_t USER_MARK = 0xFFFFFFFF00000000; // high 32 bit + static constexpr ExecutorPool::Duration BUSY_INTERVAL = std::chrono::seconds(180); // second + static constexpr int32_t RETRY_TIMES = 6; // normal retry + static constexpr int32_t CLIENT_RETRY_TIMES = 3; // normal retry + static constexpr uint64_t USER_MARK = 0xFFFFFFFF00000000; // high 32 bit static constexpr int32_t MV_BIT = 32; + static constexpr int32_t EXPIRATION_TIME = 6 * 60 * 60 * 1000; // 6 hours static uint64_t GenerateId(int32_t user); static ExecutorPool::Duration GetInterval(int32_t code); @@ -120,15 +124,18 @@ private: void UpdateStartSyncInfo(const std::vector> &cloudSyncInfos); void UpdateFinishSyncInfo(const QueryKey &queryKey, uint64_t syncId, int32_t code); std::function GetCallback(const GenAsync &async, - const StoreInfo &storeInfo); - std::function GetPostEventTask(const std::vector &schemas, CloudInfo &cloud, SyncInfo &info, + const StoreInfo &storeInfo, int32_t triggerMode); + std::function GetPostEventTask(const std::vector &schemas, CloudInfo &cloud, SyncInfo &info, bool retry); void DoExceptionalCallback(const GenAsync &async, GenDetails &details, const StoreInfo &storeInfo); bool InitDefaultUser(int32_t &user); std::function RetryCallback( - const StoreInfo &storeInfo, Retryer retryer); + const StoreInfo &storeInfo, Retryer retryer, int32_t triggerMode); static void GetLastResults( const std::string &storeId, std::map &infos, QueryLastResults &results); + void BatchUpdateFinishState(const std::vector> &cloudSyncInfos, int32_t code); + bool NeedSaveSyncInfo(const QueryKey &queryKey); + std::function GetLockChangeHandler(); static std::atomic genId_; std::shared_ptr executor_; @@ -136,6 +143,7 @@ private: ConcurrentMap activeInfos_; std::shared_ptr syncStrategy_; ConcurrentMap> lastSyncInfos_; + std::set kvApps_; }; } // namespace OHOS::CloudData #endif // OHOS_DISTRIBUTED_DATA_SERVICES_CLOUD_SYNC_MANAGER_H \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/cloud/sync_strategies/network_sync_strategy.cpp b/datamgr_service/services/distributeddataservice/service/cloud/sync_strategies/network_sync_strategy.cpp index 043cb5e781247617300924db0ee67bbb3cfe82a4..827bf6289b4be7d47fa519e9e95c39ecafb5178e 100644 --- a/datamgr_service/services/distributeddataservice/service/cloud/sync_strategies/network_sync_strategy.cpp +++ b/datamgr_service/services/distributeddataservice/service/cloud/sync_strategies/network_sync_strategy.cpp @@ -16,17 +16,19 @@ #define LOG_TAG "NetworkSyncStrategy" #include "network_sync_strategy.h" -#include "metadata/meta_data_manager.h" + #include "device_manager_adapter.h" #include "error/general_error.h" -#include "utils/constant.h" #include "log_print.h" +#include "metadata/meta_data_manager.h" +#include "utils/constant.h" namespace OHOS::CloudData { using namespace OHOS::DistributedData; NetworkSyncStrategy::NetworkSyncStrategy() { MetaDataManager::GetInstance().Subscribe( - StrategyInfo::PREFIX, [this](const std::string &key, const std::string &value, int32_t flag) -> auto { + StrategyInfo::PREFIX, + [this](const std::string &key, const std::string &value, int32_t flag) -> auto { StrategyInfo info; StrategyInfo::Unmarshall(value, info); ZLOGI("flag:%{public}d, value:%{public}s", flag, value.c_str()); @@ -41,14 +43,20 @@ NetworkSyncStrategy::NetworkSyncStrategy() ZLOGE("ignored operation"); } return true; - }, true); + }, + true); } + NetworkSyncStrategy::~NetworkSyncStrategy() { MetaDataManager::GetInstance().Unsubscribe(StrategyInfo::PREFIX); } + int32_t NetworkSyncStrategy::CheckSyncAction(const StoreInfo &storeInfo) { + if (storeInfo.user == StrategyInfo::ROOT_USER) { + return E_OK; + } if (!DeviceManagerAdapter::GetInstance().IsNetworkAvailable()) { return E_NETWORK_ERROR; } @@ -125,4 +133,4 @@ NetworkSyncStrategy::StrategyInfo NetworkSyncStrategy::GetStrategy(int32_t user, strategies_.Insert(info.bundleName, info); return info; } -} +} // namespace OHOS::CloudData \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/cloud/sync_strategies/network_sync_strategy.h b/datamgr_service/services/distributeddataservice/service/cloud/sync_strategies/network_sync_strategy.h index 2d19ece4aa7fc9a441f7246d8401b155f4ea22a7..af2680a194b31cb6d184cb36bd8e9d5a66d258d1 100644 --- a/datamgr_service/services/distributeddataservice/service/cloud/sync_strategies/network_sync_strategy.h +++ b/datamgr_service/services/distributeddataservice/service/cloud/sync_strategies/network_sync_strategy.h @@ -36,16 +36,18 @@ public: bool Unmarshal(const json &node) override; std::string GetKey(); static constexpr int32_t INVALID_USER = -1; + static constexpr int32_t ROOT_USER = 0; static constexpr const char *PREFIX = "NETWORK_SYNC_STRATEGY"; }; NetworkSyncStrategy(); ~NetworkSyncStrategy(); - int32_t CheckSyncAction(const StoreInfo& storeInfo) override; + int32_t CheckSyncAction(const StoreInfo &storeInfo) override; static std::string GetKey(int32_t user); - static std::string GetKey(int32_t user, const std::string& bundleName); + static std::string GetKey(int32_t user, const std::string &bundleName); + private: - StrategyInfo GetStrategy(int32_t user, const std::string& bundleName); + StrategyInfo GetStrategy(int32_t user, const std::string &bundleName); static bool Check(uint32_t strategy); static constexpr uint32_t DEFAULT_STRATEGY = WIFI | CELLULAR; @@ -53,5 +55,5 @@ private: int32_t user_ = -1; ConcurrentMap strategies_; }; -} -#endif //OHOS_DISTRIBUTED_DATA_SERVICES_CLOUD_NETWORK_SYNC_STRATEGY_H +} // namespace OHOS::CloudData +#endif //OHOS_DISTRIBUTED_DATA_SERVICES_CLOUD_NETWORK_SYNC_STRATEGY_H \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/config/include/config_factory.h b/datamgr_service/services/distributeddataservice/service/config/include/config_factory.h index e6e4025c67e930ead2e48498875bb0aeb4d677ac..6ebb1e0db025495eb261667e8bbb23d845dc8466 100644 --- a/datamgr_service/services/distributeddataservice/service/config/include/config_factory.h +++ b/datamgr_service/services/distributeddataservice/service/config/include/config_factory.h @@ -31,6 +31,7 @@ public: API_EXPORT DirectoryConfig *GetDirectoryConfig(); API_EXPORT BackupConfig *GetBackupConfig(); API_EXPORT CloudConfig *GetCloudConfig(); + API_EXPORT std::vector *GetAppIdMappingConfig(); private: static constexpr const char *CONF_PATH = "/system/etc/distributeddata/conf"; ConfigFactory(); diff --git a/datamgr_service/services/distributeddataservice/service/config/include/model/app_id_mapping_config.h b/datamgr_service/services/distributeddataservice/service/config/include/model/app_id_mapping_config.h new file mode 100644 index 0000000000000000000000000000000000000000..a0ff96a34640a66077dc4b268ec1359c860ca7bb --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/config/include/model/app_id_mapping_config.h @@ -0,0 +1,30 @@ +/* +* Copyright (c) 2024 Huawei Device Co., Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +#ifndef OHOS_DISTRIBUTED_DATA_SERVICES_CONFIG_MODEL_APP_ID_MAPPING_CONFIG_H +#define OHOS_DISTRIBUTED_DATA_SERVICES_CONFIG_MODEL_APP_ID_MAPPING_CONFIG_H + +#include "serializable/serializable.h" +namespace OHOS { +namespace DistributedData { +class AppIdMappingConfig final : public Serializable { +public: + std::string srcAppId = ""; + std::string dstAppId = ""; + bool Marshal(json &node) const override; + bool Unmarshal(const json &node) override; +}; +} // namespace DistributedData +} // namespace OHOS +#endif //OHOS_DISTRIBUTED_DATA_SERVICES_CONFIG_MODEL_APP_ID_MAPPING_CONFIG_H diff --git a/datamgr_service/services/distributeddataservice/service/config/include/model/global_config.h b/datamgr_service/services/distributeddataservice/service/config/include/model/global_config.h index c96926e4f5e7d458e058ccf6ef5e73f794743bda..0d974d5bec9b6930904aaa3bbd1a2f962593fa5c 100644 --- a/datamgr_service/services/distributeddataservice/service/config/include/model/global_config.h +++ b/datamgr_service/services/distributeddataservice/service/config/include/model/global_config.h @@ -22,6 +22,7 @@ #include "model/network_config.h" #include "model/directory_config.h" #include "model/backup_config.h" +#include "model/app_id_mapping_config.h" namespace OHOS { namespace DistributedData { class GlobalConfig final : public Serializable { @@ -36,6 +37,7 @@ public: DirectoryConfig *directory = nullptr; BackupConfig *backup = nullptr; CloudConfig *cloud = nullptr; + std::vector *appIdMapping = nullptr; ~GlobalConfig(); bool Marshal(json &node) const override; bool Unmarshal(const json &node) override; diff --git a/datamgr_service/services/distributeddataservice/service/config/src/config_factory.cpp b/datamgr_service/services/distributeddataservice/service/config/src/config_factory.cpp index 733ab0ea95a4eb88e4933481456035b40595c4fa..996f6e585bde9141a1a0e956860a1cb16ad0d99a 100644 --- a/datamgr_service/services/distributeddataservice/service/config/src/config_factory.cpp +++ b/datamgr_service/services/distributeddataservice/service/config/src/config_factory.cpp @@ -82,5 +82,10 @@ CloudConfig *ConfigFactory::GetCloudConfig() { return config_.cloud; } + +std::vector *ConfigFactory::GetAppIdMappingConfig() +{ + return config_.appIdMapping; +} } // namespace DistributedData } // namespace OHOS diff --git a/datamgr_service/services/distributeddataservice/service/config/src/model/app_id_mapping_config.cpp b/datamgr_service/services/distributeddataservice/service/config/src/model/app_id_mapping_config.cpp new file mode 100644 index 0000000000000000000000000000000000000000..001336e61e656c721499af1ce77c3bd6839882d9 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/config/src/model/app_id_mapping_config.cpp @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "model/app_id_mapping_config.h" +namespace OHOS { +namespace DistributedData { +bool AppIdMappingConfig::Marshal(Serializable::json &node) const +{ + SetValue(node[GET_NAME(srcAppId)], srcAppId); + SetValue(node[GET_NAME(dstAppId)], dstAppId); + return true; +} +bool AppIdMappingConfig::Unmarshal(const Serializable::json &node) +{ + GetValue(node, GET_NAME(srcAppId), srcAppId); + GetValue(node, GET_NAME(dstAppId), dstAppId); + return true; +} +} // namespace DistributedData +} // namespace OHOS diff --git a/datamgr_service/services/distributeddataservice/service/config/src/model/global_config.cpp b/datamgr_service/services/distributeddataservice/service/config/src/model/global_config.cpp index b3078891e9d5fb031ac1ba036e560ad8ec2722b8..d4ee79710b9cedcc9f8581b168b2d3301693c135 100644 --- a/datamgr_service/services/distributeddataservice/service/config/src/model/global_config.cpp +++ b/datamgr_service/services/distributeddataservice/service/config/src/model/global_config.cpp @@ -28,6 +28,7 @@ bool GlobalConfig::Marshal(json &node) const SetValue(node[GET_NAME(directory)], directory); SetValue(node[GET_NAME(backup)], backup); SetValue(node[GET_NAME(cloud)], cloud); + SetValue(node[GET_NAME(appIdMapping)], appIdMapping); return true; } @@ -43,6 +44,7 @@ bool GlobalConfig::Unmarshal(const json &node) GetValue(node, GET_NAME(directory), directory); GetValue(node, GET_NAME(backup), backup); GetValue(node, GET_NAME(cloud), cloud); + GetValue(node, GET_NAME(appIdMapping), appIdMapping); return true; } @@ -54,6 +56,7 @@ GlobalConfig::~GlobalConfig() delete directory; delete backup; delete cloud; + delete appIdMapping; } } // namespace DistributedData } // namespace OHOS diff --git a/datamgr_service/services/distributeddataservice/service/data_share/common/bundle_mgr_proxy.cpp b/datamgr_service/services/distributeddataservice/service/data_share/common/bundle_mgr_proxy.cpp index a54df9368b081e4aea4edbd611d330dc4b30d0e4..dec8551caa0b349d709dd9a97ff697e9fdc60dc4 100644 --- a/datamgr_service/services/distributeddataservice/service/data_share/common/bundle_mgr_proxy.cpp +++ b/datamgr_service/services/distributeddataservice/service/data_share/common/bundle_mgr_proxy.cpp @@ -16,11 +16,13 @@ #include "bundle_mgr_proxy.h" #include "account/account_delegate.h" +#include "datashare_errno.h" #include "datashare_radar_reporter.h" #include "if_system_ability_manager.h" #include "iservice_registry.h" #include "log_print.h" #include "system_ability_definition.h" +#include "uri_utils.h" namespace OHOS::DataShare { sptr BundleMgrProxy::GetBundleMgrProxy() @@ -59,32 +61,39 @@ sptr BundleMgrProxy::CheckBMS() return systemAbilityManager->CheckSystemAbility(BUNDLE_MGR_SERVICE_SYS_ABILITY_ID); } -bool BundleMgrProxy::GetBundleInfoFromBMS( - const std::string &bundleName, int32_t userId, AppExecFwk::BundleInfo &bundleInfo) +int BundleMgrProxy::GetBundleInfoFromBMS( + const std::string &bundleName, int32_t userId, BundleConfig &bundleConfig) { auto bundleKey = bundleName + std::to_string(userId); auto it = bundleCache_.Find(bundleKey); if (it.first) { - bundleInfo = it.second; - return true; + bundleConfig = it.second; + return E_OK; } auto bmsClient = GetBundleMgrProxy(); if (bmsClient == nullptr) { RADAR_REPORT(__FUNCTION__, RadarReporter::SILENT_ACCESS, RadarReporter::GET_BMS, RadarReporter::FAILED, RadarReporter::ERROR_CODE, RadarReporter::GET_BMS_FAILED); ZLOGE("GetBundleMgrProxy is nullptr!"); - return false; + return E_BMS_NOT_READY; } + AppExecFwk::BundleInfo bundleInfo; bool ret = bmsClient->GetBundleInfo( bundleName, AppExecFwk::BundleFlag::GET_BUNDLE_WITH_EXTENSION_INFO, bundleInfo, userId); if (!ret) { RADAR_REPORT(__FUNCTION__, RadarReporter::SILENT_ACCESS, RadarReporter::GET_BMS, RadarReporter::FAILED, RadarReporter::ERROR_CODE, RadarReporter::GET_BUNDLE_INFP_FAILED); ZLOGE("GetBundleInfo failed!bundleName is %{public}s, userId is %{public}d", bundleName.c_str(), userId); - return false; + return E_BUNDLE_NAME_NOT_EXIST; } - bundleCache_.Insert(bundleKey, bundleInfo); - return true; + auto [errCode, bundle] = ConvertToDataShareBundle(bundleInfo); + if (errCode != E_OK) { + ZLOGE("Profile Unmarshall failed! bundleName:%{public}s", URIUtils::Anonymous(bundle.name).c_str()); + return errCode; + } + bundleConfig = bundle; + bundleCache_.Insert(bundleKey, bundle); + return E_OK; } void BundleMgrProxy::OnProxyDied() @@ -117,4 +126,92 @@ std::shared_ptr BundleMgrProxy::GetInstance() static std::shared_ptr proxy(new BundleMgrProxy()); return proxy; } + +std::pair BundleMgrProxy::ConvertToDataShareBundle(AppExecFwk::BundleInfo &bundleInfo) +{ + BundleConfig bundleConfig; + bundleConfig.name = std::move(bundleInfo.name); + bundleConfig.singleton = std::move(bundleInfo.singleton); + auto [errCode, hapModuleInfos] = ConvertHapModuleInfo(bundleInfo); + if (errCode != E_OK) { + return std::make_pair(errCode, bundleConfig); + } + bundleConfig.hapModuleInfos = hapModuleInfos; + + auto [err, extensionInfos] = ConvertExtensionAbility(bundleInfo); + if (err != E_OK) { + return std::make_pair(err, bundleConfig); + } + bundleConfig.extensionInfos = extensionInfos; + return std::make_pair(E_OK, bundleConfig); +} + +std::pair> BundleMgrProxy::ConvertExtensionAbility( + AppExecFwk::BundleInfo &bundleInfo) +{ + std::vector extensionInfos; + for (auto &item : bundleInfo.extensionInfos) { + if (item.type != AppExecFwk::ExtensionAbilityType::DATASHARE) { + continue; + } + ExtensionAbilityInfo extensionInfo; + extensionInfo.type = std::move(item.type); + extensionInfo.readPermission = std::move(item.readPermission); + extensionInfo.writePermission = std::move(item.writePermission); + extensionInfo.uri = std::move(item.uri); + extensionInfo.resourcePath = std::move(item.resourcePath); + extensionInfo.hapPath = std::move(item.hapPath); + ProfileConfig profileConfig; + auto [ret, profileInfo] = DataShareProfileConfig::GetDataProperties( + item.metadata, extensionInfo.resourcePath, extensionInfo.hapPath, DATA_SHARE_EXTENSION_META); + if (ret == NOT_FOUND) { + profileConfig.resultCode = NOT_FOUND; + } + if (ret == ERROR) { + profileConfig.resultCode = ERROR; + ZLOGE("Profile unmarshall error.uri: %{public}s", URIUtils::Anonymous(extensionInfo.uri).c_str()); + return std::make_pair(E_ERROR, extensionInfos); + } + profileConfig.profile = profileInfo; + extensionInfo.profileInfo = profileConfig; + extensionInfos.emplace_back(extensionInfo); + } + return std::make_pair(E_OK, extensionInfos); +} + +std::pair> BundleMgrProxy::ConvertHapModuleInfo(AppExecFwk::BundleInfo &bundleInfo) +{ + std::vector hapModuleInfos; + for (auto &item : bundleInfo.hapModuleInfos) { + HapModuleInfo hapModuleInfo; + hapModuleInfo.resourcePath = std::move(item.resourcePath); + hapModuleInfo.hapPath = std::move(item.hapPath); + hapModuleInfo.moduleName = std::move(item.moduleName); + std::vector proxyDatas; + for (auto &proxyData : item.proxyDatas) { + ProxyData data; + data.uri = std::move(proxyData.uri); + data.requiredReadPermission = std::move(proxyData.requiredReadPermission); + data.requiredWritePermission = std::move(proxyData.requiredWritePermission); + ProfileConfig profileConfig; + auto [ret, profileInfo] = DataShareProfileConfig::GetDataProperties( + std::vector{proxyData.metadata}, hapModuleInfo.resourcePath, + hapModuleInfo.hapPath, DATA_SHARE_PROPERTIES_META); + if (ret == NOT_FOUND) { + profileConfig.resultCode = NOT_FOUND; + } + if (ret == ERROR) { + profileConfig.resultCode = ERROR; + ZLOGE("Profile unmarshall error.uri: %{public}s", URIUtils::Anonymous(data.uri).c_str()); + return std::make_pair(E_ERROR, hapModuleInfos); + } + profileConfig.profile = profileInfo; + data.profileInfo = profileConfig; + proxyDatas.emplace_back(data); + } + hapModuleInfo.proxyDatas = proxyDatas; + hapModuleInfos.emplace_back(hapModuleInfo); + } + return std::make_pair(E_OK, hapModuleInfos); +} } // namespace OHOS::DataShare \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/data_share/common/bundle_mgr_proxy.h b/datamgr_service/services/distributeddataservice/service/data_share/common/bundle_mgr_proxy.h index a41374053ddcccc3d3fd68b5de122b14f083383c..9b4b325cac565a22567387de6bb53d57d6a3b898 100644 --- a/datamgr_service/services/distributeddataservice/service/data_share/common/bundle_mgr_proxy.h +++ b/datamgr_service/services/distributeddataservice/service/data_share/common/bundle_mgr_proxy.h @@ -22,12 +22,50 @@ #include "bundle_info.h" #include "bundlemgr/bundle_mgr_proxy.h" #include "concurrent_map.h" +#include "data_share_profile_config.h" + namespace OHOS::DataShare { +struct ProfileConfig { + ProfileInfo profile; + int resultCode = 0; +}; + +struct ProxyData { + std::string uri; + std::string requiredReadPermission; + std::string requiredWritePermission; + ProfileConfig profileInfo; +}; + +struct HapModuleInfo { + std::string resourcePath; + std::string hapPath; + std::string moduleName; + std::vector proxyDatas; +}; + +struct ExtensionAbilityInfo { + AppExecFwk::ExtensionAbilityType type = AppExecFwk::ExtensionAbilityType::UNSPECIFIED; + std::string readPermission; + std::string writePermission; + std::string uri; + std::string resourcePath; + std::string hapPath; + ProfileConfig profileInfo; +}; + +struct BundleConfig { + std::string name; + bool singleton = false; + std::vector hapModuleInfos; + std::vector extensionInfos; +}; + class BundleMgrProxy final : public std::enable_shared_from_this { public: ~BundleMgrProxy(); static std::shared_ptr GetInstance(); - bool GetBundleInfoFromBMS(const std::string &bundleName, int32_t userId, AppExecFwk::BundleInfo &bundleInfo); + int GetBundleInfoFromBMS(const std::string &bundleName, int32_t userId, BundleConfig &bundleConfig); void Delete(const std::string &bundleName, int32_t userId); sptr CheckBMS(); @@ -49,10 +87,15 @@ private: }; sptr GetBundleMgrProxy(); void OnProxyDied(); + std::pair ConvertToDataShareBundle(AppExecFwk::BundleInfo &bundleInfo); + std::pair> ConvertExtensionAbility(AppExecFwk::BundleInfo &bundleInfo); + std::pair> ConvertHapModuleInfo(AppExecFwk::BundleInfo &bundleInfo); std::mutex mutex_; sptr proxy_; sptr deathRecipient_; - ConcurrentMap bundleCache_; + ConcurrentMap bundleCache_; + static constexpr const char *DATA_SHARE_EXTENSION_META = "ohos.extension.dataShare"; + static constexpr const char *DATA_SHARE_PROPERTIES_META = "dataProperties"; }; } // namespace OHOS::DataShare #endif // DATASHARESERVICE_BUNDLEMGR_PROXY_H diff --git a/datamgr_service/services/distributeddataservice/service/data_share/common/context.h b/datamgr_service/services/distributeddataservice/service/data_share/common/context.h index e347eb03aef9f87265a9279214c5c6b35aa2e47f..25995eaa064c8741f80251cfc2e80874f6fa15d8 100644 --- a/datamgr_service/services/distributeddataservice/service/data_share/common/context.h +++ b/datamgr_service/services/distributeddataservice/service/data_share/common/context.h @@ -21,7 +21,7 @@ #include #include -#include "bundle_info.h" +#include "bundle_mgr_proxy.h" namespace OHOS::DataShare { enum AccessSystemMode : uint8_t { @@ -53,7 +53,7 @@ public: bool needAutoLoadCallerBundleName = false; bool isEncryptDb = false; AccessSystemMode accessSystemMode = AccessSystemMode::UNDEFINED; - OHOS::AppExecFwk::BundleInfo bundleInfo; + BundleConfig bundleInfo; std::string type = "rdb"; }; } // namespace OHOS::DataShare diff --git a/datamgr_service/services/distributeddataservice/service/data_share/common/db_delegate.cpp b/datamgr_service/services/distributeddataservice/service/data_share/common/db_delegate.cpp index 84b9b54437f33dec0edcd422f3407bf06e7341b1..f9ba94f047fb3fd9eef242af3d1c578f67f7d681 100644 --- a/datamgr_service/services/distributeddataservice/service/data_share/common/db_delegate.cpp +++ b/datamgr_service/services/distributeddataservice/service/data_share/common/db_delegate.cpp @@ -20,9 +20,89 @@ #include "log_print.h" #include "rdb_delegate.h" namespace OHOS::DataShare { -std::shared_ptr DBDelegate::Create(DistributedData::StoreMetaData &metaData) +ExecutorPool::TaskId DBDelegate::taskId_ = ExecutorPool::INVALID_TASK_ID; +ConcurrentMap>> DBDelegate::stores_ = {}; +std::shared_ptr DBDelegate::executor_ = nullptr; +std::shared_ptr DBDelegate::Create(DistributedData::StoreMetaData &metaData, + const std::string &extUri, const std::string &backup) { - return std::make_shared(metaData, NO_CHANGE_VERSION, true); + if (metaData.tokenId == 0) { + return std::make_shared(metaData, NO_CHANGE_VERSION, true, extUri, backup); + } + std::shared_ptr store; + stores_.Compute(metaData.tokenId, + [&metaData, &store, extUri, &backup](auto &, std::map> &stores) -> bool { + auto it = stores.find(metaData.storeId); + if (it != stores.end()) { + store = it->second->store_; + it->second->time_ = std::chrono::steady_clock::now() + std::chrono::seconds(INTERVAL); + return !stores.empty(); + } + store = std::make_shared(metaData, NO_CHANGE_VERSION, true, extUri, backup); + if (store->IsInvalid()) { + store = nullptr; + ZLOGE("creator failed, storeName: %{public}s", metaData.GetStoreAlias().c_str()); + return false; + } + auto entity = std::make_shared(store); + stores.emplace(metaData.storeId, entity); + StartTimer(); + return !stores.empty(); + }); + return store; +} + +void DBDelegate::SetExecutorPool(std::shared_ptr executor) +{ + executor_ = std::move(executor); +} + +void DBDelegate::GarbageCollect() +{ + stores_.EraseIf([](auto &, std::map> &stores) { + auto current = std::chrono::steady_clock::now(); + for (auto it = stores.begin(); it != stores.end();) { + // if the store is BUSY we wait more INTERVAL minutes again + if (it->second->time_ < current) { + it = stores.erase(it); + } else { + ++it; + } + } + return stores.empty(); + }); +} + +void DBDelegate::StartTimer() +{ + if (executor_ == nullptr || taskId_ != Executor::INVALID_TASK_ID) { + return; + } + taskId_ = executor_->Schedule( + []() { + GarbageCollect(); + stores_.DoActionIfEmpty([]() { + if (executor_ == nullptr || taskId_ == Executor::INVALID_TASK_ID) { + return; + } + executor_->Remove(taskId_); + ZLOGD("remove timer, taskId: %{public}" PRIu64, taskId_); + taskId_ = Executor::INVALID_TASK_ID; + }); + }, + std::chrono::seconds(INTERVAL), std::chrono::seconds(INTERVAL)); + ZLOGD("start timer, taskId: %{public}" PRIu64, taskId_); +} + +DBDelegate::Entity::Entity(std::shared_ptr store) +{ + store_ = std::move(store); + time_ = std::chrono::steady_clock::now() + std::chrono::seconds(INTERVAL); +} + +void DBDelegate::EraseStoreCache(const int32_t tokenId) +{ + stores_.Erase(tokenId); } std::shared_ptr KvDBDelegate::GetInstance( diff --git a/datamgr_service/services/distributeddataservice/service/data_share/common/db_delegate.h b/datamgr_service/services/distributeddataservice/service/data_share/common/db_delegate.h index 99f13253ce97be11c1526eead9f60ba1a4f59155..18e4052373940a080830a7a98c574bf72dc35a6a 100644 --- a/datamgr_service/services/distributeddataservice/service/data_share/common/db_delegate.h +++ b/datamgr_service/services/distributeddataservice/service/data_share/common/db_delegate.h @@ -31,19 +31,37 @@ namespace OHOS::DataShare { class DBDelegate { public: - static std::shared_ptr Create(DistributedData::StoreMetaData &metaData); - virtual int64_t Insert(const std::string &tableName, const DataShareValuesBucket &valuesBucket) = 0; - virtual int64_t Update(const std::string &tableName, const DataSharePredicates &predicate, - const DataShareValuesBucket &valuesBucket) = 0; - virtual int64_t Delete(const std::string &tableName, const DataSharePredicates &predicate) = 0; + using Time = std::chrono::steady_clock::time_point; + static std::shared_ptr Create(DistributedData::StoreMetaData &metaData, + const std::string &extUri = "", const std::string &backup = ""); virtual std::pair> Query(const std::string &tableName, const DataSharePredicates &predicates, const std::vector &columns, const int32_t callingPid) = 0; virtual std::string Query( const std::string &sql, const std::vector &selectionArgs = std::vector()) = 0; virtual std::shared_ptr QuerySql(const std::string &sql) = 0; + virtual bool IsInvalid() = 0; + static void SetExecutorPool(std::shared_ptr executor); + static void EraseStoreCache(const int32_t tokenId); + virtual std::pair InsertEx(const std::string &tableName, + const DataShareValuesBucket &valuesBucket) = 0; + virtual std::pair UpdateEx(const std::string &tableName, + const DataSharePredicates &predicate, const DataShareValuesBucket &valuesBucket) = 0; + virtual std::pair DeleteEx(const std::string &tableName, + const DataSharePredicates &predicate) = 0; private: + static void GarbageCollect(); + static void StartTimer(); + struct Entity { + explicit Entity(std::shared_ptr store); + std::shared_ptr store_; + Time time_; + }; static constexpr int NO_CHANGE_VERSION = -1; + static constexpr int64_t INTERVAL = 20; //seconds + static ConcurrentMap>> stores_; + static std::shared_ptr executor_; + static ExecutorPool::TaskId taskId_; }; class Id : public DistributedData::Serializable { @@ -107,6 +125,7 @@ public: std::string &result) = 0; virtual int32_t GetBatch(const std::string &collectionName, const std::string &filter, const std::string &projection, std::vector &result) = 0; + virtual void NotifyBackup() = 0; }; } // namespace OHOS::DataShare #endif // DATASHARESERVICE_DB_DELEGATE_H diff --git a/datamgr_service/services/distributeddataservice/service/data_share/common/extension_ability_manager.cpp b/datamgr_service/services/distributeddataservice/service/data_share/common/extension_ability_manager.cpp index 8a7c7f388c33d92c22ff14c4e8235419fd4e6c4f..2328285df370c1f67f2b2bcc51788ba1d3e28416 100644 --- a/datamgr_service/services/distributeddataservice/service/data_share/common/extension_ability_manager.cpp +++ b/datamgr_service/services/distributeddataservice/service/data_share/common/extension_ability_manager.cpp @@ -34,7 +34,7 @@ void ExtensionAbilityManager::SetExecutorPool(std::shared_ptr exec } int32_t ExtensionAbilityManager::ConnectExtension(const std::string &uri, const std::string &bundleName, - const sptr &callback) + const sptr &callback, AAFwk::WantParams &wantParams) { auto absent = connectCallbackCache_.ComputeIfAbsent(bundleName, [callback](const std::string &) { return std::move(callback); @@ -44,32 +44,38 @@ int32_t ExtensionAbilityManager::ConnectExtension(const std::string &uri, const bundleName.c_str(), URIUtils::Anonymous(uri).c_str()); return E_ERROR; } - ErrCode ret = ExtensionMgrProxy::GetInstance()->Connect(uri, callback, nullptr); + ErrCode ret = ExtensionMgrProxy::GetInstance()->Connect(uri, callback, nullptr, wantParams); if (ret != E_OK) { ZLOGE("Connect ability failed, ret:%{public}d, uri:%{public}s, bundleName:%{public}s", ret, URIUtils::Anonymous(uri).c_str(), bundleName.c_str()); connectCallbackCache_.Erase(bundleName); return E_ERROR; } + Disconnect(bundleName, MAX_WAIT_DISCONNECT_TIME); return E_OK; } void ExtensionAbilityManager::DelayDisconnect(const std::string &bundleName) { - executor_->Schedule(std::chrono::seconds(WAIT_DISCONNECT_TIME), [bundleName, this]() { + Disconnect(bundleName, WAIT_DISCONNECT_TIME); +} + +void ExtensionAbilityManager::Disconnect(const std::string &bundleName, int time) +{ + executor_->Schedule(std::chrono::seconds(time), [bundleName, this]() { ZLOGI("Delay disconnect %{public}s", bundleName.c_str()); - connectCallbackCache_.ComputeIfPresent(bundleName, [bundleName](const std::string &, - sptr &disconnect) { - if (disconnect == nullptr) { - ZLOGI("Delay disconnect nullptr %{public}s", bundleName.c_str()); + connectCallbackCache_.ComputeIfPresent(bundleName, + [bundleName](const std::string &, sptr &disconnect) { + if (disconnect == nullptr) { + ZLOGI("Delay disconnect nullptr %{public}s", bundleName.c_str()); + return false; + } + auto ret = ExtensionMgrProxy::GetInstance()->DisConnect(disconnect); + if (ret != E_OK) { + ZLOGE("Delay disConnect failed bundleName: %{public}s, ret: %{public}d", bundleName.c_str(), ret); + } return false; - } - auto ret = ExtensionMgrProxy::GetInstance()->DisConnect(disconnect); - if (ret != E_OK) { - ZLOGE("Delay disConnect failed bundleName: %{public}s, ret: %{public}d", bundleName.c_str(), ret); - } - return false; - }); + }); }); } } // namespace OHOS::DataShare diff --git a/datamgr_service/services/distributeddataservice/service/data_share/common/extension_ability_manager.h b/datamgr_service/services/distributeddataservice/service/data_share/common/extension_ability_manager.h index 0640fa6e823c683d0aaea94efcbd767131ae0873..a78e4e20cac0d275089080e5fe3f088161cede3d 100644 --- a/datamgr_service/services/distributeddataservice/service/data_share/common/extension_ability_manager.h +++ b/datamgr_service/services/distributeddataservice/service/data_share/common/extension_ability_manager.h @@ -19,6 +19,7 @@ #include "concurrent_map.h" #include "executor_pool.h" #include "iremote_object.h" +#include "want.h" namespace OHOS::DataShare { class ExtensionAbilityManager { @@ -26,13 +27,15 @@ public: static ExtensionAbilityManager &GetInstance(); void SetExecutorPool(std::shared_ptr executor); int32_t ConnectExtension(const std::string &uri, const std::string &bundleName, - const sptr &callback); + const sptr &callback, AAFwk::WantParams &wantParams); void DelayDisconnect(const std::string &bundleName); private: + void Disconnect(const std::string &bundleName, int time); std::shared_ptr executor_ = nullptr; ConcurrentMap> connectCallbackCache_; static constexpr int WAIT_DISCONNECT_TIME = 5; + static constexpr int MAX_WAIT_DISCONNECT_TIME = 30; }; } // namespace OHOS::DataShare #endif // DATASHARESERVICE_EXTENSION_ABILITY_MANAGER_H diff --git a/datamgr_service/services/distributeddataservice/service/data_share/common/extension_connect_adaptor.cpp b/datamgr_service/services/distributeddataservice/service/data_share/common/extension_connect_adaptor.cpp index 9256abd3defb0b6d761e2992f93707538d078954..6a48232a4598c1175220a89d5797bccdf2429b38 100644 --- a/datamgr_service/services/distributeddataservice/service/data_share/common/extension_connect_adaptor.cpp +++ b/datamgr_service/services/distributeddataservice/service/data_share/common/extension_connect_adaptor.cpp @@ -32,13 +32,15 @@ ExtensionConnectAdaptor::ExtensionConnectAdaptor() : data_(std::make_sharedClear(); if (callback_ == nullptr) { return false; } - ErrCode ret = ExtensionAbilityManager::GetInstance().ConnectExtension(uri, bundleName, callback_->AsObject()); + ErrCode ret = ExtensionAbilityManager::GetInstance().ConnectExtension(uri, bundleName, + callback_->AsObject(), wantParams); if (ret != ERR_OK) { ZLOGE("connect ability failed, ret = %{public}d, uri: %{public}s", ret, URIUtils::Anonymous(uri).c_str()); @@ -51,13 +53,13 @@ bool ExtensionConnectAdaptor::DoConnect(const std::string &uri, const std::strin } bool ExtensionConnectAdaptor::TryAndWait(const std::string &uri, const std::string &bundleName, - int maxWaitTime) + AAFwk::WantParams &wantParams, int maxWaitTime) { ExtensionConnectAdaptor strategy; return AppConnectManager::Wait( bundleName, maxWaitTime, - [&uri, &bundleName, &strategy]() { - return strategy.DoConnect(uri, bundleName); + [&uri, &bundleName, &strategy, &wantParams]() { + return strategy.DoConnect(uri, bundleName, wantParams); }, [&strategy]() { strategy.Disconnect(); diff --git a/datamgr_service/services/distributeddataservice/service/data_share/common/extension_connect_adaptor.h b/datamgr_service/services/distributeddataservice/service/data_share/common/extension_connect_adaptor.h index e36d61ed694c170175b0770716cd726229aaa82c..ad585d10a1b3f9b03977b628b86ccb7e12a39d0b 100644 --- a/datamgr_service/services/distributeddataservice/service/data_share/common/extension_connect_adaptor.h +++ b/datamgr_service/services/distributeddataservice/service/data_share/common/extension_connect_adaptor.h @@ -19,15 +19,16 @@ #include "ability_connect_callback_interface.h" #include "block_data.h" #include "context.h" +#include "want.h" namespace OHOS::DataShare { class ExtensionConnectAdaptor { public: - static bool TryAndWait(const std::string &uri, const std::string &bundleName, + static bool TryAndWait(const std::string &uri, const std::string &bundleName, AAFwk::WantParams &wantParams, int maxWaitTime = 2); ExtensionConnectAdaptor(); private: void Disconnect(); - bool DoConnect(const std::string &uri, const std::string &bundleName); + bool DoConnect(const std::string &uri, const std::string &bundleName, AAFwk::WantParams &wantParams); std::shared_ptr> data_; sptr callback_ = nullptr; }; diff --git a/datamgr_service/services/distributeddataservice/service/data_share/common/extension_mgr_proxy.cpp b/datamgr_service/services/distributeddataservice/service/data_share/common/extension_mgr_proxy.cpp index 3303346e9a23b2e79349a56551d811950e7938d9..1d7f44d10edfe8e256e7b60eab7e9d995254ea43 100644 --- a/datamgr_service/services/distributeddataservice/service/data_share/common/extension_mgr_proxy.cpp +++ b/datamgr_service/services/distributeddataservice/service/data_share/common/extension_mgr_proxy.cpp @@ -49,10 +49,12 @@ std::shared_ptr ExtensionMgrProxy::GetInstance() } int ExtensionMgrProxy::Connect( - const std::string &uri, const sptr &connect, const sptr &callerToken) + const std::string &uri, const sptr &connect, const sptr &callerToken, + AAFwk::WantParams &wantParams) { AAFwk::Want want; want.SetUri(uri); + want.SetParams(wantParams); std::lock_guard lock(mutex_); if (ConnectSA()) { int ret = proxy_->ConnectAbilityCommon(want, connect, callerToken, AppExecFwk::ExtensionAbilityType::DATASHARE); diff --git a/datamgr_service/services/distributeddataservice/service/data_share/common/extension_mgr_proxy.h b/datamgr_service/services/distributeddataservice/service/data_share/common/extension_mgr_proxy.h index a93a4c903b98086b7cc028f0770c495708d40217..21bda2ddb44049777f2843c05e6edc56e25f2309 100644 --- a/datamgr_service/services/distributeddataservice/service/data_share/common/extension_mgr_proxy.h +++ b/datamgr_service/services/distributeddataservice/service/data_share/common/extension_mgr_proxy.h @@ -20,6 +20,7 @@ #include #include "extension_manager_proxy.h" +#include "want.h" namespace OHOS::DataShare { class ExtensionMgrProxy final : public std::enable_shared_from_this { public: @@ -27,7 +28,8 @@ public: ExtensionMgrProxy() = default; ~ExtensionMgrProxy(); static std::shared_ptr GetInstance(); - int Connect(const std::string &uri, const sptr &connect, const sptr &callerToken); + int Connect(const std::string &uri, const sptr &connect, + const sptr &callerToken, AAFwk::WantParams &wantParams); int DisConnect(sptr connect); private: using Proxy = AAFwk::ExtensionManagerProxy; diff --git a/datamgr_service/services/distributeddataservice/service/data_share/common/kv_delegate.cpp b/datamgr_service/services/distributeddataservice/service/data_share/common/kv_delegate.cpp index 9e36164adaed8b19c14a2ccf6743d041f5f5cc3a..23aa6a6119c406daf5700de16df913598af56b33 100644 --- a/datamgr_service/services/distributeddataservice/service/data_share/common/kv_delegate.cpp +++ b/datamgr_service/services/distributeddataservice/service/data_share/common/kv_delegate.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023 Huawei Device Co., Ltd. + * Copyright (c) 2023-2024 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -13,6 +13,12 @@ * limitations under the License. */ #define LOG_TAG "KvAdaptor" + +#include +#include +#include +#include + #include "kv_delegate.h" #include "datashare_errno.h" @@ -24,6 +30,103 @@ namespace OHOS::DataShare { constexpr int WAIT_TIME = 30; + +// If using multi-process access, back up dataShare.db.map as well. Check config file to see whether +// using multi-process maccess +const char* g_backupFiles[] = { + "dataShare.db", + "dataShare.db.redo", + "dataShare.db.safe", + "dataShare.db.undo", +}; +const char* BACKUP_SUFFIX = ".backup"; + +// If isBackUp is true, remove db backup files. Otherwise remove source db files. +void KvDelegate::RemoveDbFile(bool isBackUp) +{ + for (auto &fileName: g_backupFiles) { + std::string dbPath = path_ + "/" + fileName; + if (isBackUp) { + dbPath += BACKUP_SUFFIX; + } + if (std::filesystem::exists(dbPath)) { + std::error_code ec; + bool success = std::filesystem::remove(dbPath, ec); + if (!success) { + ZLOGE("failed to remove file %{public}s, err: %{public}s", fileName, ec.message().c_str()); + } + } + } +} + +bool KvDelegate::CopyFile(bool isBackup) +{ + std::filesystem::copy_options options = std::filesystem::copy_options::overwrite_existing; + std::error_code code; + bool ret = true; + for (auto &fileName : g_backupFiles) { + std::string src = path_ + "/" + fileName; + std::string dst = src; + isBackup ? dst.append(BACKUP_SUFFIX) : src.append(BACKUP_SUFFIX); + // If src doesn't exist, error will be returned through `std::error_code` + bool copyRet = std::filesystem::copy_file(src, dst, options, code); + if (!copyRet) { + ZLOGE("failed to copy file %{public}s, isBackup %{public}d, err: %{public}s", + fileName, isBackup, code.message().c_str()); + ret = false; + RemoveDbFile(isBackup); + break; + } + } + return ret; +} + +// Restore database data when it is broken somehow. Some failure of insertion / deletion / updates will be considered +// as database files damage, and therefore trigger the process of restoration. +void KvDelegate::Restore() +{ + // No need to lock because this inner method will only be called when upper methods lock up + CopyFile(false); + ZLOGD("finish restoring kv"); +} + +// Backup database data by copying its key files. This mechanism might be costly, but acceptable when updating +// contents of KV database happens not so frequently now. +void KvDelegate::Backup() +{ + // No need to lock because this inner method will only be called when upper methods lock up + ZLOGD("backup kv"); + if (hasChange_) { + CopyFile(true); + hasChange_ = false; + } + ZLOGD("finish backing up kv"); +} + +// Set hasChange_ to true. Caller can use this to control when to back up db. +void OHOS::DataShare::KvDelegate::NotifyBackup() +{ + std::lock_guard lock(mutex_); + hasChange_ = true; +} + +// The return val indicates whether the database has been restored +bool KvDelegate::RestoreIfNeed(int32_t dbStatus) +{ + // No need to lock because this inner method will only be called when upper methods lock up + if (dbStatus == GRD_INVALID_FILE_FORMAT || dbStatus == GRD_REBUILD_DATABASE) { + if (db_ != NULL) { + GRD_DBClose(db_, GRD_DB_CLOSE); + db_ = nullptr; + isInitDone_ = false; + } + // If db is NULL, it has been closed. + Restore(); + return true; + } + return false; +} + int64_t KvDelegate::Upsert(const std::string &collectionName, const std::string &filter, const std::string &value) { std::lock_guard lock(mutex_); @@ -33,7 +136,8 @@ int64_t KvDelegate::Upsert(const std::string &collectionName, const std::string } int count = GRD_UpsertDoc(db_, collectionName.c_str(), filter.c_str(), value.c_str(), 0); if (count <= 0) { - ZLOGE("GRD_UpSertDoc failed,status %{public}d", count); + ZLOGE("GRD_UpSertDoc failed,status %{public}d", count); + RestoreIfNeed(count); return count; } Flush(); @@ -52,12 +156,16 @@ int32_t KvDelegate::Delete(const std::string &collectionName, const std::string int32_t status = GetBatch(collectionName, filter, "{\"id_\": true}", queryResults); if (status != E_OK) { ZLOGE("db GetBatch failed, %{public}s %{public}d", filter.c_str(), status); + // `GetBatch` should decide whether to restore before errors are returned, so skip restoration here. return status; } for (auto &result : queryResults) { auto count = GRD_DeleteDoc(db_, collectionName.c_str(), result.c_str(), 0); if (count < 0) { - ZLOGE("GRD_UpSertDoc failed,status %{public}d %{public}s", count, result.c_str()); + ZLOGE("GRD_DeleteDoc failed,status %{public}d %{public}s", count, result.c_str()); + if (RestoreIfNeed(count)) { + return count; + } continue; } } @@ -79,7 +187,8 @@ bool KvDelegate::Init() int status = GRD_DBOpen( (path_ + "/dataShare.db").c_str(), nullptr, GRD_DB_OPEN_CREATE | GRD_DB_OPEN_CHECK_FOR_ABNORMAL, &db_); if (status != GRD_OK || db_ == nullptr) { - ZLOGE("GRD_DBOpen failed,status %{public}d", status); + ZLOGE("GRD_DBOpen failed,status %{public}d", status); + RestoreIfNeed(status); return false; } if (executors_ != nullptr) { @@ -89,17 +198,22 @@ bool KvDelegate::Init() db_ = nullptr; isInitDone_ = false; taskId_ = ExecutorPool::INVALID_TASK_ID; + Backup(); }); } status = GRD_CreateCollection(db_, TEMPLATE_TABLE, nullptr, 0); if (status != GRD_OK) { - ZLOGE("GRD_CreateCollection template table failed,status %{public}d", status); + // If opeaning db succeeds, it is rare to fail to create tables + ZLOGE("GRD_CreateCollection template table failed,status %{public}d", status); + RestoreIfNeed(status); return false; } status = GRD_CreateCollection(db_, DATA_TABLE, nullptr, 0); if (status != GRD_OK) { - ZLOGE("GRD_CreateCollection data table failed,status %{public}d", status); + // If opeaning db succeeds, it is rare to fail to create tables + ZLOGE("GRD_CreateCollection data table failed,status %{public}d", status); + RestoreIfNeed(status); return false; } isInitDone_ = true; @@ -112,7 +226,7 @@ KvDelegate::~KvDelegate() if (isInitDone_) { int status = GRD_DBClose(db_, 0); if (status != GRD_OK) { - ZLOGE("GRD_DBClose failed,status %{public}d", status); + ZLOGE("GRD_DBClose failed,status %{public}d", status); } } } @@ -124,7 +238,7 @@ int32_t KvDelegate::Upsert(const std::string &collectionName, const KvData &valu int version = -1; if (GetVersion(collectionName, id, version)) { if (value.GetVersion() <= version) { - ZLOGE("GetVersion failed,%{public}s id %{private}s %{public}d %{public}d", collectionName.c_str(), + ZLOGE("GetVersion failed,%{public}s id %{private}s %{public}d %{public}d", collectionName.c_str(), id.c_str(), value.GetVersion(), version); return E_VERSION_NOT_NEWER; } @@ -152,7 +266,7 @@ bool KvDelegate::GetVersion(const std::string &collectionName, const std::string } VersionData data(-1); if (!DistributedData::Serializable::Unmarshall(value, data)) { - ZLOGE("Unmarshall failed,data %{public}s", value.c_str()); + ZLOGE("Unmarshall failed,data %{public}s", value.c_str()); return false; } version = data.GetVersion(); @@ -173,20 +287,23 @@ int32_t KvDelegate::Get( GRD_ResultSet *resultSet = nullptr; int status = GRD_FindDoc(db_, collectionName.c_str(), query, 0, &resultSet); if (status != GRD_OK || resultSet == nullptr) { - ZLOGE("GRD_FindDoc failed,status %{public}d", status); + ZLOGE("GRD_FindDoc failed,status %{public}d", status); + RestoreIfNeed(status); return status; } status = GRD_Next(resultSet); if (status != GRD_OK) { GRD_FreeResultSet(resultSet); - ZLOGE("GRD_Next failed,status %{public}d", status); + ZLOGE("GRD_Next failed,status %{public}d", status); + RestoreIfNeed(status); return status; } char *value = nullptr; status = GRD_GetValue(resultSet, &value); if (status != GRD_OK || value == nullptr) { GRD_FreeResultSet(resultSet); - ZLOGE("GRD_GetValue failed,status %{public}d", status); + ZLOGE("GRD_GetValue failed,status %{public}d", status); + RestoreIfNeed(status); return status; } result = value; @@ -199,7 +316,8 @@ void KvDelegate::Flush() { int status = GRD_Flush(db_, GRD_DB_FLUSH_ASYNC); if (status != GRD_OK) { - ZLOGE("GRD_Flush failed,status %{public}d", status); + ZLOGE("GRD_Flush failed,status %{public}d", status); + RestoreIfNeed(status); } } @@ -217,7 +335,8 @@ int32_t KvDelegate::GetBatch(const std::string &collectionName, const std::strin GRD_ResultSet *resultSet; int status = GRD_FindDoc(db_, collectionName.c_str(), query, GRD_DOC_ID_DISPLAY, &resultSet); if (status != GRD_OK || resultSet == nullptr) { - ZLOGE("GRD_UpSertDoc failed,status %{public}d", status); + ZLOGE("GRD_FindDoc failed,status %{public}d", status); + RestoreIfNeed(status); return status; } char *value = nullptr; @@ -225,7 +344,8 @@ int32_t KvDelegate::GetBatch(const std::string &collectionName, const std::strin status = GRD_GetValue(resultSet, &value); if (status != GRD_OK || value == nullptr) { GRD_FreeResultSet(resultSet); - ZLOGE("GRD_GetValue failed,status %{public}d", status); + ZLOGE("GRD_GetValue failed,status %{public}d", status); + RestoreIfNeed(status); return status; } result.emplace_back(value); diff --git a/datamgr_service/services/distributeddataservice/service/data_share/common/kv_delegate.h b/datamgr_service/services/distributeddataservice/service/data_share/common/kv_delegate.h index e3d19e08c05494f4b95f8f69798145115a15cc95..13499f70d9e24d15e50c2016a9a86361a3a98f0c 100644 --- a/datamgr_service/services/distributeddataservice/service/data_share/common/kv_delegate.h +++ b/datamgr_service/services/distributeddataservice/service/data_share/common/kv_delegate.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023 Huawei Device Co., Ltd. + * Copyright (c) 2023-2024 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -36,18 +36,25 @@ public: std::string &result) override; int32_t GetBatch(const std::string &collectionName, const std::string &filter, const std::string &projection, std::vector &result) override; + void NotifyBackup() override; private: bool Init(); bool GetVersion(const std::string &collectionName, const std::string &filter, int &version); int64_t Upsert(const std::string &collectionName, const std::string &filter, const std::string &value); void Flush(); + bool RestoreIfNeed(int32_t dbStatus); + void Backup(); + void Restore(); + void RemoveDbFile(bool isBackUp); + bool CopyFile(bool isBackup); std::recursive_mutex mutex_; std::string path_; GRD_DB *db_ = nullptr; bool isInitDone_ = false; std::shared_ptr executors_ = nullptr; ExecutorPool::TaskId taskId_ = ExecutorPool::INVALID_TASK_ID; + bool hasChange_ = false; }; } // namespace OHOS::DataShare #endif // DATASHARESERVICE_KV_DELEGATE_H diff --git a/datamgr_service/services/distributeddataservice/service/data_share/common/rdb_delegate.cpp b/datamgr_service/services/distributeddataservice/service/data_share/common/rdb_delegate.cpp index 603c9fcfc90dda8729b8e00849f1a1f9c3b76aab..013ce8b05cd1971d7f9994d3ef3a0201ec52d6ea 100644 --- a/datamgr_service/services/distributeddataservice/service/data_share/common/rdb_delegate.cpp +++ b/datamgr_service/services/distributeddataservice/service/data_share/common/rdb_delegate.cpp @@ -16,21 +16,28 @@ #include "rdb_delegate.h" #include "crypto_manager.h" +#include "datashare_errno.h" #include "datashare_radar_reporter.h" #include "device_manager_adapter.h" +#include "extension_connect_adaptor.h" +#include "int_wrapper.h" #include "metadata/meta_data_manager.h" #include "metadata/store_meta_data.h" #include "metadata/secret_key_meta_data.h" #include "resultset_json_formatter.h" #include "log_print.h" +#include "rdb_errno.h" #include "rdb_utils.h" #include "scheduler_manager.h" +#include "string_wrapper.h" #include "utils/anonymous.h" +#include "want_params.h" namespace OHOS::DataShare { -constexpr static int32_t MAX_RESULTSET_COUNT = 16; +constexpr static int32_t MAX_RESULTSET_COUNT = 32; constexpr static int64_t TIMEOUT_TIME = 500; std::atomic RdbDelegate::resultSetCount = 0; +ConcurrentMap RdbDelegate::resultSetCallingPids; enum REMIND_TIMER_ARGS : int32_t { ARG_DB_PATH = 0, ARG_VERSION, @@ -61,6 +68,7 @@ RdbStoreConfig RdbDelegate::GetConfig(const DistributedData::StoreMetaData &meta { RdbStoreConfig config(meta.dataDir); config.SetCreateNecessary(false); + config.SetHaMode(meta.haMode); config.SetBundleName(meta.bundleName); if (meta.isEncrypt) { DistributedData::SecretKeyMetaData secretKeyMeta; @@ -76,22 +84,46 @@ RdbStoreConfig RdbDelegate::GetConfig(const DistributedData::StoreMetaData &meta return config; } -RdbDelegate::RdbDelegate(const DistributedData::StoreMetaData &meta, int version, bool registerFunction) +RdbDelegate::RdbDelegate(const DistributedData::StoreMetaData &meta, int version, + bool registerFunction, const std::string &extUriData, const std::string &backup) { + tokenId_ = meta.tokenId; + bundleName_ = meta.bundleName; + storeName_ = meta.storeId; + extUri_ = extUriData; + haMode_ = meta.haMode; + backup_ = backup; + RdbStoreConfig config = GetConfig(meta, registerFunction); DefaultOpenCallback callback; store_ = RdbHelper::GetRdbStore(config, version, callback, errCode_); if (errCode_ != E_OK) { ZLOGW("GetRdbStore failed, errCode is %{public}d, dir is %{public}s", errCode_, DistributedData::Anonymous::Change(meta.dataDir).c_str()); + RdbDelegate::TryAndSend(errCode_); } } -int64_t RdbDelegate::Insert(const std::string &tableName, const DataShareValuesBucket &valuesBucket) +void RdbDelegate::TryAndSend(int errCode) +{ + if (errCode != E_SQLITE_CORRUPT || (haMode_ == HAMode::SINGLE && (backup_ != DUAL_WRITE && backup_ != PERIODIC))) { + return; + } + ZLOGE("Database corruption. BundleName: %{public}s. StoreName: %{public}s. ExtUri: %{public}s", + bundleName_.c_str(), storeName_.c_str(), DistributedData::Anonymous::Change(extUri_).c_str()); + AAFwk::WantParams params; + params.SetParam("BundleName", AAFwk::String::Box(bundleName_)); + params.SetParam("StoreName", AAFwk::String::Box(storeName_)); + params.SetParam("StoreStatus", AAFwk::Integer::Box(1)); + ExtensionConnectAdaptor::TryAndWait(extUri_, bundleName_, params); +} + +std::pair RdbDelegate::InsertEx(const std::string &tableName, + const DataShareValuesBucket &valuesBucket) { if (store_ == nullptr) { ZLOGE("store is null"); - return 0; + return std::make_pair(E_DB_ERROR, 0); } int64_t rowId = 0; ValuesBucket bucket = RdbDataShareAdapter::RdbUtils::ToValuesBucket(valuesBucket); @@ -100,15 +132,21 @@ int64_t RdbDelegate::Insert(const std::string &tableName, const DataShareValuesB ZLOGE("Insert failed %{public}s %{public}d", tableName.c_str(), ret); RADAR_REPORT(__FUNCTION__, RadarReporter::SILENT_ACCESS, RadarReporter::PROXY_CALL_RDB, RadarReporter::FAILED, RadarReporter::ERROR_CODE, RadarReporter::INSERT_RDB_ERROR); + if (ret == E_SQLITE_ERROR) { + EraseStoreCache(tokenId_); + } + RdbDelegate::TryAndSend(ret); + return std::make_pair(E_DB_ERROR, rowId); } - return rowId; + return std::make_pair(E_OK, rowId); } -int64_t RdbDelegate::Update( + +std::pair RdbDelegate::UpdateEx( const std::string &tableName, const DataSharePredicates &predicate, const DataShareValuesBucket &valuesBucket) { if (store_ == nullptr) { ZLOGE("store is null"); - return 0; + return std::make_pair(E_DB_ERROR, 0); } int changeCount = 0; ValuesBucket bucket = RdbDataShareAdapter::RdbUtils::ToValuesBucket(valuesBucket); @@ -118,14 +156,20 @@ int64_t RdbDelegate::Update( ZLOGE("Update failed %{public}s %{public}d", tableName.c_str(), ret); RADAR_REPORT(__FUNCTION__, RadarReporter::SILENT_ACCESS, RadarReporter::PROXY_CALL_RDB, RadarReporter::FAILED, RadarReporter::ERROR_CODE, RadarReporter::UPDATE_RDB_ERROR); + if (ret == E_SQLITE_ERROR) { + EraseStoreCache(tokenId_); + } + RdbDelegate::TryAndSend(ret); + return std::make_pair(E_DB_ERROR, changeCount); } - return changeCount; + return std::make_pair(E_OK, changeCount); } -int64_t RdbDelegate::Delete(const std::string &tableName, const DataSharePredicates &predicate) + +std::pair RdbDelegate::DeleteEx(const std::string &tableName, const DataSharePredicates &predicate) { if (store_ == nullptr) { ZLOGE("store is null"); - return 0; + return std::make_pair(E_DB_ERROR, 0); } int changeCount = 0; RdbPredicates predicates = RdbDataShareAdapter::RdbUtils::ToPredicates(predicate, tableName); @@ -134,9 +178,15 @@ int64_t RdbDelegate::Delete(const std::string &tableName, const DataSharePredica ZLOGE("Delete failed %{public}s %{public}d", tableName.c_str(), ret); RADAR_REPORT(__FUNCTION__, RadarReporter::SILENT_ACCESS, RadarReporter::PROXY_CALL_RDB, RadarReporter::FAILED, RadarReporter::ERROR_CODE, RadarReporter::DELETE_RDB_ERROR); + if (ret == E_SQLITE_ERROR) { + EraseStoreCache(tokenId_); + } + RdbDelegate::TryAndSend(ret); + return std::make_pair(E_DB_ERROR, changeCount); } - return changeCount; + return std::make_pair(E_OK, changeCount); } + std::pair> RdbDelegate::Query(const std::string &tableName, const DataSharePredicates &predicates, const std::vector &columns, const int32_t callingPid) @@ -147,20 +197,29 @@ std::pair> RdbDelegate::Query(const std } int count = resultSetCount.fetch_add(1); ZLOGD("start query %{public}d", count); - if (count > MAX_RESULTSET_COUNT) { - ZLOGE("resultSetCount is full"); + if (count > MAX_RESULTSET_COUNT && IsLimit(count, callingPid)) { resultSetCount--; - return std::make_pair(E_ERROR, nullptr); + return std::make_pair(E_RESULTSET_BUSY, nullptr); } RdbPredicates rdbPredicates = RdbDataShareAdapter::RdbUtils::ToPredicates(predicates, tableName); std::shared_ptr resultSet = store_->QueryByStep(rdbPredicates, columns); if (resultSet == nullptr) { RADAR_REPORT(__FUNCTION__, RadarReporter::SILENT_ACCESS, RadarReporter::PROXY_CALL_RDB, RadarReporter::FAILED, RadarReporter::ERROR_CODE, RadarReporter::QUERY_RDB_ERROR); - ZLOGE("Query failed %{public}s", tableName.c_str()); + ZLOGE("Query failed %{public}s, pid: %{public}d", tableName.c_str(), callingPid); resultSetCount--; return std::make_pair(E_ERROR, nullptr); } + int err = resultSet->GetRowCount(count); + RdbDelegate::TryAndSend(err); + if (err == E_SQLITE_ERROR) { + ZLOGE("query failed, err:%{public}d, pid:%{public}d", E_SQLITE_ERROR, callingPid); + EraseStoreCache(tokenId_); + } + resultSetCallingPids.Compute(callingPid, [](const uint32_t &, int32_t &value) { + ++value; + return true; + }); int64_t beginTime = std::chrono::duration_cast( std::chrono::system_clock::now().time_since_epoch()).count(); auto bridge = RdbDataShareAdapter::RdbUtils::ToResultSetBridge(resultSet); @@ -173,6 +232,10 @@ std::pair> RdbDelegate::Query(const std ZLOGE("pid %{public}d query time is %{public}" PRId64 ", %{public}d resultSet is used.", callingPid, (endTime - beginTime), resultSetCount.load()); } + resultSetCallingPids.ComputeIfPresent(callingPid, [](const uint32_t &, int32_t &value) { + --value; + return value > 0; + }); delete p; }}; return std::make_pair(E_OK, result); @@ -189,6 +252,11 @@ std::string RdbDelegate::Query(const std::string &sql, const std::vectorGetRowCount(rowCount) == E_SQLITE_ERROR) { + ZLOGE("query failed, err:%{public}d", E_SQLITE_ERROR); + EraseStoreCache(tokenId_); + } ResultSetJsonFormatter formatter(std::move(resultSet)); return DistributedData::Serializable::Marshall(formatter); } @@ -199,6 +267,43 @@ std::shared_ptr RdbDelegate::QuerySql(const std::string &s ZLOGE("store is null"); return nullptr; } - return store_->QuerySql(sql); + auto resultSet = store_->QuerySql(sql); + if (resultSet == nullptr) { + ZLOGE("Query failed %{private}s", sql.c_str()); + return resultSet; + } + int rowCount; + if (resultSet->GetRowCount(rowCount) == E_SQLITE_ERROR) { + ZLOGE("query failed, err:%{public}d", E_SQLITE_ERROR); + EraseStoreCache(tokenId_); + } + return resultSet; +} + +bool RdbDelegate::IsInvalid() +{ + return store_ == nullptr; +} + +bool RdbDelegate::IsLimit(int count, const int32_t callingPid) +{ + bool isFull = true; + for (int32_t retryCount = 0; retryCount < RETRY; retryCount++) { + std::this_thread::sleep_for(WAIT_TIME); + if (resultSetCount.load() <= MAX_RESULTSET_COUNT) { + isFull = false; + break; + } + } + if (!isFull) { + return false; + } + std::string logStr; + resultSetCallingPids.ForEach([&logStr](const uint32_t &key, const int32_t &value) { + logStr += std::to_string(key) + ":" + std::to_string(value) + ";"; + return false; + }); + ZLOGE("resultSetCount is full, pid: %{public}d, owner is %{public}s", callingPid, logStr.c_str()); + return true; } } // namespace OHOS::DataShare \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/data_share/common/rdb_delegate.h b/datamgr_service/services/distributeddataservice/service/data_share/common/rdb_delegate.h index cef51a9cc2c16acde425d45dc09f4d84f4308d76..adb3d3b133980e7a7aa5cadab78faee3ec1831be 100644 --- a/datamgr_service/services/distributeddataservice/service/data_share/common/rdb_delegate.h +++ b/datamgr_service/services/distributeddataservice/service/data_share/common/rdb_delegate.h @@ -31,22 +31,38 @@ namespace OHOS::DataShare { using namespace OHOS::NativeRdb; class RdbDelegate final : public DBDelegate { public: - explicit RdbDelegate(const DistributedData::StoreMetaData &meta, int version, bool registerFunction); - int64_t Insert(const std::string &tableName, const DataShareValuesBucket &valuesBucket) override; - int64_t Update(const std::string &tableName, const DataSharePredicates &predicate, - const DataShareValuesBucket &valuesBucket) override; - int64_t Delete(const std::string &tableName, const DataSharePredicates &predicate) override; + explicit RdbDelegate(const DistributedData::StoreMetaData &meta, int version, + bool registerFunction, const std::string &extUri, const std::string &backup); std::pair> Query(const std::string &tableName, const DataSharePredicates &predicates, const std::vector &columns, const int32_t callingPid) override; std::string Query(const std::string &sql, const std::vector &selectionArgs) override; std::shared_ptr QuerySql(const std::string &sql) override; - + bool IsInvalid() override; + std::pair InsertEx(const std::string &tableName, + const DataShareValuesBucket &valuesBucket) override; + std::pair UpdateEx(const std::string &tableName, + const DataSharePredicates &predicate, const DataShareValuesBucket &valuesBucket) override; + std::pair DeleteEx(const std::string &tableName, + const DataSharePredicates &predicate) override; private: + void TryAndSend(int errCode); RdbStoreConfig GetConfig(const DistributedData::StoreMetaData &meta, bool registerFunction); + bool IsLimit(int count, const int32_t callingPid); static std::atomic resultSetCount; + static ConcurrentMap resultSetCallingPids; + static constexpr std::chrono::milliseconds WAIT_TIME = std::chrono::milliseconds(50); std::shared_ptr store_; int errCode_ = E_OK; + static constexpr int RETRY = 3; + static constexpr const char *DUAL_WRITE = "dualWrite"; + static constexpr const char *PERIODIC = "periodic"; + uint32_t tokenId_; + std::string bundleName_; + std::string storeName_; + int32_t haMode_; + std::string extUri_; + std::string backup_; }; class DefaultOpenCallback : public RdbOpenCallback { public: diff --git a/datamgr_service/services/distributeddataservice/service/data_share/common/uri_utils.cpp b/datamgr_service/services/distributeddataservice/service/data_share/common/uri_utils.cpp index 8fb91826922fc63b34002af3d7586fc0d6cb21a2..26447121a82615ea7304cef1f41d75bec5b845f9 100644 --- a/datamgr_service/services/distributeddataservice/service/data_share/common/uri_utils.cpp +++ b/datamgr_service/services/distributeddataservice/service/data_share/common/uri_utils.cpp @@ -72,7 +72,7 @@ void URIUtils::FormatUri(std::string &uri) uri.resize(pos); } -UriConfig URIUtils::GetUriConfig(const std::string &uri) +__attribute__((no_sanitize("cfi"))) UriConfig URIUtils::GetUriConfig(const std::string &uri) { UriConfig uriConfig; Uri uriTemp(uri); @@ -107,7 +107,7 @@ std::pair URIUtils::Strtoul(const std::string &str) char* end = nullptr; errno = 0; data = strtoul(str.c_str(), &end, 10); - if (errno == ERANGE || end == str || *end != '\0') { + if (errno == ERANGE || end == nullptr || end == str || *end != '\0') { return std::make_pair(false, data); } return std::make_pair(true, data); diff --git a/datamgr_service/services/distributeddataservice/service/data_share/data/template_data.cpp b/datamgr_service/services/distributeddataservice/service/data_share/data/template_data.cpp index 4236f4d7b370f28199c9e7f443bd267756cced00..eb63f4111728c95a87a6c3dfd8129d855af7d828 100644 --- a/datamgr_service/services/distributeddataservice/service/data_share/data/template_data.cpp +++ b/datamgr_service/services/distributeddataservice/service/data_share/data/template_data.cpp @@ -132,6 +132,7 @@ bool TemplateData::Delete(const std::string &bundleName, const int32_t userId) ZLOGE("db DeleteById failed, %{public}d", status); return false; } + delegate->NotifyBackup(); return true; } @@ -149,6 +150,7 @@ bool TemplateData::Add(const std::string &uri, const int32_t userId, const std:: ZLOGE("db Upsert failed, %{public}d", status); return false; } + delegate->NotifyBackup(); return true; } @@ -166,6 +168,7 @@ bool TemplateData::Delete( ZLOGE("db DeleteById failed, %{public}d", status); return false; } + delegate->NotifyBackup(); return true; } diff --git a/datamgr_service/services/distributeddataservice/service/data_share/data_provider_config.cpp b/datamgr_service/services/distributeddataservice/service/data_share/data_provider_config.cpp index 4d951df554fa6ec26be2389488dab78729d05234..98783ade7fe562899cf3adffe406f973356b793a 100644 --- a/datamgr_service/services/distributeddataservice/service/data_share/data_provider_config.cpp +++ b/datamgr_service/services/distributeddataservice/service/data_share/data_provider_config.cpp @@ -41,9 +41,9 @@ DataProviderConfig::DataProviderConfig(const std::string &uri, uint32_t callerTo uriConfig_ = URIUtils::GetUriConfig(providerInfo_.uri); } -std::pair DataProviderConfig::GetBundleInfo() +std::pair DataProviderConfig::GetBundleInfo() { - BundleInfo bundleInfo; + BundleConfig bundleInfo; providerInfo_.bundleName = uriConfig_.authority; if (providerInfo_.bundleName.empty()) { if (uriConfig_.pathSegments.empty()) { @@ -51,11 +51,9 @@ std::pair DataProviderConfig::GetBundleInfo() } providerInfo_.bundleName = uriConfig_.pathSegments[0]; } - if (!BundleMgrProxy::GetInstance()->GetBundleInfoFromBMS( - providerInfo_.bundleName, providerInfo_.currentUserId, bundleInfo)) { - return std::make_pair(E_BUNDLE_NAME_NOT_EXIST, bundleInfo); - } - return std::make_pair(E_OK, bundleInfo); + auto ret = BundleMgrProxy::GetInstance()->GetBundleInfoFromBMS( + providerInfo_.bundleName, providerInfo_.currentUserId, bundleInfo); + return std::make_pair(ret, bundleInfo); } int DataProviderConfig::GetFromProxyData() @@ -77,8 +75,8 @@ int DataProviderConfig::GetFromProxyData() } for (auto &hapModuleInfo : bundleInfo.hapModuleInfos) { auto &proxyDatas = hapModuleInfo.proxyDatas; - std::sort(proxyDatas.begin(), proxyDatas.end(), [](const AppExecFwk::ProxyData &curr, - const AppExecFwk::ProxyData &prev) { + std::sort(proxyDatas.begin(), proxyDatas.end(), [](const ProxyData &curr, + const ProxyData &prev) { return curr.uri.length() > prev.uri.length(); }); for (auto &data : proxyDatas) { @@ -88,17 +86,15 @@ int DataProviderConfig::GetFromProxyData() } providerInfo_.readPermission = std::move(data.requiredReadPermission); providerInfo_.writePermission = std::move(data.requiredWritePermission); - auto [ret, profileInfo] = DataShareProfileConfig::GetDataProperties( - std::vector{data.metadata}, hapModuleInfo.resourcePath, - hapModuleInfo.hapPath, DATA_SHARE_PROPERTIES_META); - if (ret == NOT_FOUND) { + auto profileInfo = data.profileInfo; + if (profileInfo.resultCode == NOT_FOUND) { return E_OK; } - if (ret == ERROR) { + if (profileInfo.resultCode == ERROR) { ZLOGE("Profile unmarshall error.uri: %{public}s", URIUtils::Anonymous(providerInfo_.uri).c_str()); return E_ERROR; } - return GetFromDataProperties(profileInfo, hapModuleInfo.moduleName); + return GetFromDataProperties(profileInfo.profile, hapModuleInfo.moduleName); } } return E_URI_NOT_EXIST; @@ -114,6 +110,8 @@ int DataProviderConfig::GetFromDataProperties(const ProfileInfo &profileInfo, providerInfo_.tableName = profileInfo.tableName; providerInfo_.type = profileInfo.type; providerInfo_.storeMetaDataFromUri = profileInfo.storeMetaDataFromUri; + providerInfo_.backup = profileInfo.backup; + providerInfo_.extensionUri = profileInfo.extUri; if (profileInfo.tableConfig.empty()) { return E_OK; } @@ -144,11 +142,12 @@ int DataProviderConfig::GetFromExtension() ZLOGE("Uri path failed! uri:%{public}s", URIUtils::Anonymous(providerInfo_.uri).c_str()); return E_URI_NOT_EXIST; } - BundleInfo bundleInfo; - if (!BundleMgrProxy::GetInstance()->GetBundleInfoFromBMS( - providerInfo_.bundleName, providerInfo_.currentUserId, bundleInfo)) { + BundleConfig bundleInfo; + auto ret = BundleMgrProxy::GetInstance()->GetBundleInfoFromBMS( + providerInfo_.bundleName, providerInfo_.currentUserId, bundleInfo); + if (ret != E_OK) { ZLOGE("BundleInfo failed! bundleName: %{public}s", providerInfo_.bundleName.c_str()); - return E_BUNDLE_NAME_NOT_EXIST; + return ret; } providerInfo_.singleton = bundleInfo.singleton; providerInfo_.allowEmptyPermission = true; @@ -159,16 +158,15 @@ int DataProviderConfig::GetFromExtension() providerInfo_.hasExtension = true; providerInfo_.readPermission = std::move(item.readPermission); providerInfo_.writePermission = std::move(item.writePermission); - auto [ret, profileInfo] = DataShareProfileConfig::GetDataProperties( - item.metadata, item.resourcePath, item.hapPath, DATA_SHARE_EXTENSION_META); - if (ret == NOT_FOUND) { + auto profileInfo = item.profileInfo; + if (profileInfo.resultCode == NOT_FOUND) { return E_OK; } - if (ret == ERROR) { + if (profileInfo.resultCode == ERROR) { ZLOGE("Profile Unmarshall failed! uri:%{public}s", URIUtils::Anonymous(providerInfo_.uri).c_str()); return E_ERROR; } - return GetFromExtensionProperties(profileInfo, providerInfo_.moduleName); + return GetFromExtensionProperties(profileInfo.profile, providerInfo_.moduleName); } return E_URI_NOT_EXIST; } diff --git a/datamgr_service/services/distributeddataservice/service/data_share/data_provider_config.h b/datamgr_service/services/distributeddataservice/service/data_share/data_provider_config.h index dd2f5966405e16dcab22dd4f44f500006796875d..794cfe0650ca6c77fed175d507520afd7ff74bf3 100644 --- a/datamgr_service/services/distributeddataservice/service/data_share/data_provider_config.h +++ b/datamgr_service/services/distributeddataservice/service/data_share/data_provider_config.h @@ -18,6 +18,7 @@ #include #include +#include "common/bundle_mgr_proxy.h" #include "account/account_delegate.h" #include "bundle_mgr_proxy.h" #include "data_share_profile_config.h" @@ -25,7 +26,6 @@ #include "uri_utils.h" namespace OHOS::DataShare { -using BundleInfo = OHOS::AppExecFwk::BundleInfo; using ExtensionAbility = OHOS::AppExecFwk::ExtensionAbilityInfo; class DataProviderConfig { public: @@ -41,6 +41,8 @@ public: std::string readPermission; std::string writePermission; std::string type = "rdb"; + std::string backup; + std::string extensionUri; bool singleton = false; bool hasExtension = false; bool allowEmptyPermission = false; @@ -56,7 +58,7 @@ private: int GetFromDataProperties(const ProfileInfo &profileInfo, const std::string &moduleName); int GetFromExtensionProperties(const ProfileInfo &profileInfo, const std::string &moduleName); void GetMetaDataFromUri(); - std::pair GetBundleInfo(); + std::pair GetBundleInfo(); enum class PATH_PARAM : int32_t { BUNDLE_NAME = 0, MODULE_NAME, diff --git a/datamgr_service/services/distributeddataservice/service/data_share/data_share_db_config.cpp b/datamgr_service/services/distributeddataservice/service/data_share/data_share_db_config.cpp index d604a832557e6f05b4d1e6fc7c53326c8aa2b076..b8c2927a025c75b811e99c5d66a3cc94668157c8 100644 --- a/datamgr_service/services/distributeddataservice/service/data_share/data_share_db_config.cpp +++ b/datamgr_service/services/distributeddataservice/service/data_share/data_share_db_config.cpp @@ -50,7 +50,8 @@ std::pair DataShareDbConfig::GetMetaData(co if (!hasExtension) { return std::pair(NativeRdb::E_DB_NOT_EXIST, metaData); } - ExtensionConnectAdaptor::TryAndWait(uri, bundleName); + AAFwk::WantParams wantParams; + ExtensionConnectAdaptor::TryAndWait(uri, bundleName, wantParams); auto [succ, meta] = QueryMetaData(bundleName, storeName, userId); if (!succ) { return std::pair(NativeRdb::E_DB_NOT_EXIST, meta); @@ -61,21 +62,22 @@ std::pair DataShareDbConfig::GetMetaData(co } std::tuple> DataShareDbConfig::GetDbConfig( - const std::string &uri, bool hasExtension, const std::string &bundleName, const std::string &storeName, - int32_t userId) + DbConfig &dbConfig) { - auto [errCode, metaData] = GetMetaData(uri, bundleName, storeName, userId, hasExtension); + auto [errCode, metaData] = GetMetaData(dbConfig.uri, dbConfig.bundleName, dbConfig.storeName, + dbConfig.userId, dbConfig.hasExtension); if (errCode != E_OK) { ZLOGE("DB not exist,bundleName:%{public}s,storeName:%{public}s,user:%{public}d,err:%{public}d,uri:%{public}s", - bundleName.c_str(), storeName.c_str(), userId, errCode, URIUtils::Anonymous(uri).c_str()); + dbConfig.bundleName.c_str(), dbConfig.storeName.c_str(), dbConfig.userId, errCode, + URIUtils::Anonymous(dbConfig.uri).c_str()); RADAR_REPORT(__FUNCTION__, RadarReporter::SILENT_ACCESS, RadarReporter::PROXY_MATEDATA_EXISTS, RadarReporter::FAILED, RadarReporter::ERROR_CODE, RadarReporter::META_DATA_NOT_EXISTS); return std::make_tuple(errCode, metaData, nullptr); } - auto dbDelegate = DBDelegate::Create(metaData); + auto dbDelegate = DBDelegate::Create(metaData, dbConfig.extUri, dbConfig.backup); if (dbDelegate == nullptr) { ZLOGE("Create delegate fail, bundleName:%{public}s, userId:%{public}d, uri:%{public}s", - bundleName.c_str(), userId, URIUtils::Anonymous(uri).c_str()); + dbConfig.bundleName.c_str(), dbConfig.userId, URIUtils::Anonymous(dbConfig.uri).c_str()); return std::make_tuple(E_ERROR, metaData, nullptr); } return std::make_tuple(E_OK, metaData, dbDelegate); diff --git a/datamgr_service/services/distributeddataservice/service/data_share/data_share_db_config.h b/datamgr_service/services/distributeddataservice/service/data_share/data_share_db_config.h index 441e9cfe20c447d4451318ca0344869a959b779b..c038a4cbd62d5148d98beb169ea335908774230e 100644 --- a/datamgr_service/services/distributeddataservice/service/data_share/data_share_db_config.h +++ b/datamgr_service/services/distributeddataservice/service/data_share/data_share_db_config.h @@ -28,9 +28,16 @@ namespace OHOS::DataShare { class DataShareDbConfig { public: - std::tuple> GetDbConfig( - const std::string &uri, bool hasExtension, const std::string &bundleName, - const std::string &storeName, int32_t userId); + struct DbConfig { + std::string uri; + std::string extUri; + std::string bundleName; + std::string storeName; + std::string backup; + int32_t userId; + bool hasExtension; + }; + std::tuple> GetDbConfig(DbConfig &dbConfig); std::pair GetMetaData(const std::string &uri, const std::string &bundleName, const std::string &storeName, int32_t userId, bool hasExtension); private: diff --git a/datamgr_service/services/distributeddataservice/service/data_share/data_share_profile_config.cpp b/datamgr_service/services/distributeddataservice/service/data_share/data_share_profile_config.cpp index f179186de6da658a74d5461f62ba0b2d915a46a2..fde20bd1128af33f4e3bb2496aac5c778fc91e38 100644 --- a/datamgr_service/services/distributeddataservice/service/data_share/data_share_profile_config.cpp +++ b/datamgr_service/services/distributeddataservice/service/data_share/data_share_profile_config.cpp @@ -24,6 +24,7 @@ #include #include "bundle_mgr_proxy.h" +#include "datashare_errno.h" #include "log_print.h" #include "uri_utils.h" #include "utils/anonymous.h" @@ -75,6 +76,9 @@ bool ProfileInfo::Marshal(json &node) const SetValue(node[GET_NAME(type)], type); SetValue(node[GET_NAME(launchInfos)], launchInfos); SetValue(node[GET_NAME(storeMetaDataFromUri)], storeMetaDataFromUri); + SetValue(node[GET_NAME(launchForCleanData)], launchForCleanData); + SetValue(node[GET_NAME(backup)], backup); + SetValue(node[GET_NAME(extUri)], extUri); return true; } @@ -86,6 +90,9 @@ bool ProfileInfo::Unmarshal(const json &node) GetValue(node, GET_NAME(type), type); GetValue(node, GET_NAME(launchInfos), launchInfos); GetValue(node, GET_NAME(storeMetaDataFromUri), storeMetaDataFromUri); + GetValue(node, GET_NAME(launchForCleanData), launchForCleanData); + GetValue(node, GET_NAME(backup), backup); + GetValue(node, GET_NAME(extUri), extUri); std::string path; auto ret = GetValue(node, GET_NAME(path), path); if (ret) { @@ -243,8 +250,9 @@ std::string DataShareProfileConfig::ReadProfile(const std::string &resPath) bool DataShareProfileConfig::GetProfileInfo(const std::string &calledBundleName, int32_t currentUserId, std::map &profileInfos) { - AppExecFwk::BundleInfo bundleInfo; - if (!BundleMgrProxy::GetInstance()->GetBundleInfoFromBMS(calledBundleName, currentUserId, bundleInfo)) { + BundleConfig bundleInfo; + if (BundleMgrProxy::GetInstance()->GetBundleInfoFromBMS(calledBundleName, + currentUserId, bundleInfo) != E_OK) { ZLOGE("data share GetBundleInfoFromBMS failed! bundleName: %{public}s, currentUserId = %{public}d", calledBundleName.c_str(), currentUserId); return false; @@ -253,12 +261,11 @@ bool DataShareProfileConfig::GetProfileInfo(const std::string &calledBundleName, if (item.type != AppExecFwk::ExtensionAbilityType::DATASHARE) { continue; } - auto [ret, profileInfo] = GetDataProperties(item.metadata, item.resourcePath, - item.hapPath, DATA_SHARE_EXTENSION_META); - if (ret == ERROR || ret == NOT_FOUND) { + auto profileInfo = item.profileInfo; + if (profileInfo.resultCode == ERROR || profileInfo.resultCode == NOT_FOUND) { continue; } - profileInfos[item.uri] = profileInfo; + profileInfos[item.uri] = profileInfo.profile; } return true; } diff --git a/datamgr_service/services/distributeddataservice/service/data_share/data_share_profile_config.h b/datamgr_service/services/distributeddataservice/service/data_share/data_share_profile_config.h index fb5e631a98819681dc5f31effb59be3d2e52f504..9fc6df898af97bb4db84fbae61b63d2e535fb641 100644 --- a/datamgr_service/services/distributeddataservice/service/data_share/data_share_profile_config.h +++ b/datamgr_service/services/distributeddataservice/service/data_share/data_share_profile_config.h @@ -50,8 +50,11 @@ struct ProfileInfo : public DistributedData::Serializable { std::string tableName; std::string scope = "module"; std::string type = "rdb"; + std::string backup; + std::string extUri; std::vector launchInfos; bool storeMetaDataFromUri = false; + bool launchForCleanData = false; bool Marshal(json &node) const override; bool Unmarshal(const json &node) override; }; @@ -63,7 +66,7 @@ enum AccessCrossMode : uint8_t { USER_MAX, }; -class API_EXPORT DataShareProfileConfig { +class DataShareProfileConfig { public: constexpr static int8_t TABLE_MATCH_PRIORITY = 3; constexpr static int8_t STORE_MATCH_PRIORITY = 2; diff --git a/datamgr_service/services/distributeddataservice/service/data_share/data_share_service_impl.cpp b/datamgr_service/services/distributeddataservice/service/data_share/data_share_service_impl.cpp index 57e063904b79e71a9156f465d9421ac22901d4ac..c57d403dcb636a09d88f13c11509feecdca1b22b 100644 --- a/datamgr_service/services/distributeddataservice/service/data_share/data_share_service_impl.cpp +++ b/datamgr_service/services/distributeddataservice/service/data_share/data_share_service_impl.cpp @@ -38,7 +38,9 @@ #include "dump/dump_manager.h" #include "extension_ability_manager.h" #include "hap_token_info.h" +#include "if_system_ability_manager.h" #include "ipc_skeleton.h" +#include "iservice_registry.h" #include "log_print.h" #include "metadata/auto_launch_meta_data.h" #include "metadata/meta_data_manager.h" @@ -48,6 +50,8 @@ #include "scheduler_manager.h" #include "subscriber_managers/published_data_subscriber_manager.h" #include "sys_event_subscriber.h" +#include "system_ability_definition.h" +#include "system_ability_status_change_stub.h" #include "template_data.h" #include "utils/anonymous.h" #include "xcollie.h" @@ -58,6 +62,29 @@ using DumpManager = OHOS::DistributedData::DumpManager; using ProviderInfo = DataProviderConfig::ProviderInfo; using namespace OHOS::DistributedData; __attribute__((used)) DataShareServiceImpl::Factory DataShareServiceImpl::factory_; +class DataShareServiceImpl::SystemAbilityStatusChangeListener + : public SystemAbilityStatusChangeStub { +public: + SystemAbilityStatusChangeListener() + { + } + ~SystemAbilityStatusChangeListener() = default; + void OnAddSystemAbility(int32_t systemAbilityId, const std::string &deviceId) override; + void OnRemoveSystemAbility(int32_t systemAbilityId, const std::string &deviceId) override + { + } +}; + +void DataShareServiceImpl::SystemAbilityStatusChangeListener::OnAddSystemAbility( + int32_t systemAbilityId, const std::string &deviceId) +{ + if (systemAbilityId != COMMON_EVENT_SERVICE_ID) { + return; + } + ZLOGI("Common event service start. saId:%{public}d", systemAbilityId); + InitSubEvent(); +} + DataShareServiceImpl::Factory::Factory() { FeatureSystem::GetInstance().RegisterCreator("data_share", []() { @@ -69,24 +96,24 @@ DataShareServiceImpl::Factory::Factory() DataShareServiceImpl::Factory::~Factory() {} -int32_t DataShareServiceImpl::Insert(const std::string &uri, const DataShareValuesBucket &valuesBucket) +std::pair DataShareServiceImpl::InsertEx(const std::string &uri, const std::string &extUri, + const DataShareValuesBucket &valuesBucket) { - ZLOGD("Insert enter."); XCollie xcollie(__FUNCTION__, HiviewDFX::XCOLLIE_FLAG_LOG | HiviewDFX::XCOLLIE_FLAG_RECOVERY); if (GetSilentProxyStatus(uri, false) != E_OK) { ZLOGW("silent proxy disable, %{public}s", URIUtils::Anonymous(uri).c_str()); - return ERROR; + return std::make_pair(ERROR, 0); } - auto callBack = [&uri, &valuesBucket, this](ProviderInfo &providerInfo, - DistributedData::StoreMetaData &metaData, std::shared_ptr dbDelegate) -> int32_t { - auto ret = dbDelegate->Insert(providerInfo.tableName, valuesBucket); - if (ret > 0) { + auto callBack = [&uri, &valuesBucket, this](ProviderInfo &providerInfo, DistributedData::StoreMetaData &metaData, + std::shared_ptr dbDelegate) -> std::pair { + auto [errCode, ret] = dbDelegate->InsertEx(providerInfo.tableName, valuesBucket); + if (errCode == E_OK && ret > 0) { NotifyChange(uri); RdbSubscriberManager::GetInstance().Emit(uri, providerInfo.currentUserId, metaData); } - return ret; + return std::make_pair(errCode, ret); }; - return Execute(uri, IPCSkeleton::GetCallingTokenID(), false, callBack); + return ExecuteEx(uri, extUri, IPCSkeleton::GetCallingTokenID(), false, callBack); } bool DataShareServiceImpl::NotifyChange(const std::string &uri) @@ -109,51 +136,52 @@ bool DataShareServiceImpl::NotifyChange(const std::string &uri) return true; } -int32_t DataShareServiceImpl::Update(const std::string &uri, const DataSharePredicates &predicate, - const DataShareValuesBucket &valuesBucket) +std::pair DataShareServiceImpl::UpdateEx(const std::string &uri, const std::string &extUri, + const DataSharePredicates &predicate, const DataShareValuesBucket &valuesBucket) { - ZLOGD("Update enter."); XCollie xcollie(__FUNCTION__, HiviewDFX::XCOLLIE_FLAG_LOG | HiviewDFX::XCOLLIE_FLAG_RECOVERY); if (GetSilentProxyStatus(uri, false) != E_OK) { ZLOGW("silent proxy disable, %{public}s", URIUtils::Anonymous(uri).c_str()); - return ERROR; + return std::make_pair(ERROR, 0); } auto callBack = [&uri, &predicate, &valuesBucket, this](ProviderInfo &providerInfo, - DistributedData::StoreMetaData &metaData, std::shared_ptr dbDelegate) -> int32_t { - auto ret = dbDelegate->Update(providerInfo.tableName, predicate, valuesBucket); - if (ret > 0) { + DistributedData::StoreMetaData &metaData, + std::shared_ptr dbDelegate) -> std::pair { + auto [errCode, ret] = dbDelegate->UpdateEx(providerInfo.tableName, predicate, valuesBucket); + if (errCode == E_OK && ret > 0) { NotifyChange(uri); RdbSubscriberManager::GetInstance().Emit(uri, providerInfo.currentUserId, metaData); } - return ret; + return std::make_pair(errCode, ret); }; - return Execute(uri, IPCSkeleton::GetCallingTokenID(), false, callBack); + return ExecuteEx(uri, extUri, IPCSkeleton::GetCallingTokenID(), false, callBack); } -int32_t DataShareServiceImpl::Delete(const std::string &uri, const DataSharePredicates &predicate) +std::pair DataShareServiceImpl::DeleteEx(const std::string &uri, const std::string &extUri, + const DataSharePredicates &predicate) { XCollie xcollie(__FUNCTION__, HiviewDFX::XCOLLIE_FLAG_LOG | HiviewDFX::XCOLLIE_FLAG_RECOVERY); if (GetSilentProxyStatus(uri, false) != E_OK) { ZLOGW("silent proxy disable, %{public}s", URIUtils::Anonymous(uri).c_str()); - return ERROR; + return std::make_pair(ERROR, 0); } - auto callBack = [&uri, &predicate, this](ProviderInfo &providerInfo, - DistributedData::StoreMetaData &metaData, std::shared_ptr dbDelegate) -> int32_t { - auto ret = dbDelegate->Delete(providerInfo.tableName, predicate); - if (ret > 0) { + auto callBack = [&uri, &predicate, this](ProviderInfo &providerInfo, DistributedData::StoreMetaData &metaData, + std::shared_ptr dbDelegate) -> std::pair { + auto [errCode, ret] = dbDelegate->DeleteEx(providerInfo.tableName, predicate); + if (errCode == E_OK && ret > 0) { NotifyChange(uri); RdbSubscriberManager::GetInstance().Emit(uri, providerInfo.currentUserId, metaData); } - return ret; + return std::make_pair(errCode, ret); }; - return Execute(uri, IPCSkeleton::GetCallingTokenID(), false, callBack); + return ExecuteEx(uri, extUri, IPCSkeleton::GetCallingTokenID(), false, callBack); } -std::shared_ptr DataShareServiceImpl::Query(const std::string &uri, +std::shared_ptr DataShareServiceImpl::Query(const std::string &uri, const std::string &extUri, const DataSharePredicates &predicates, const std::vector &columns, int &errCode) { - ZLOGD("Query enter."); - XCollie xcollie(__FUNCTION__, HiviewDFX::XCOLLIE_FLAG_LOG | HiviewDFX::XCOLLIE_FLAG_RECOVERY); + XCollie xcollie(std::string(LOG_TAG) + "::" + std::string(__FUNCTION__), + HiviewDFX::XCOLLIE_FLAG_LOG | HiviewDFX::XCOLLIE_FLAG_RECOVERY); if (GetSilentProxyStatus(uri, false) != E_OK) { ZLOGW("silent proxy disable, %{public}s", URIUtils::Anonymous(uri).c_str()); return nullptr; @@ -161,13 +189,14 @@ std::shared_ptr DataShareServiceImpl::Query(const std::strin std::shared_ptr resultSet; auto callingPid = IPCSkeleton::GetCallingPid(); auto callBack = [&uri, &predicates, &columns, &resultSet, &callingPid](ProviderInfo &providerInfo, - DistributedData::StoreMetaData &, std::shared_ptr dbDelegate) -> int32_t { + DistributedData::StoreMetaData &, std::shared_ptr dbDelegate) -> std::pair { auto [err, result] = dbDelegate->Query(providerInfo.tableName, predicates, columns, callingPid); resultSet = std::move(result); - return err; + return std::make_pair(err, E_OK); }; - errCode = Execute(uri, IPCSkeleton::GetCallingTokenID(), true, callBack); + auto [errVal, status] = ExecuteEx(uri, extUri, IPCSkeleton::GetCallingTokenID(), true, callBack); + errCode = errVal; return resultSet; } @@ -498,13 +527,25 @@ int32_t DataShareServiceImpl::OnBind(const BindInfo &binderInfo) KvDBDelegate::GetInstance(false, saveMeta.dataDir, binderInfo.executors); SchedulerManager::GetInstance().SetExecutorPool(binderInfo.executors); ExtensionAbilityManager::GetInstance().SetExecutorPool(binderInfo.executors); - InitSubEvent(); + DBDelegate::SetExecutorPool(binderInfo.executors); + SubscribeCommonEvent(); SubscribeTimeChanged(); SubscribeChange(); ZLOGI("end"); return E_OK; } +void DataShareServiceImpl::SubscribeCommonEvent() +{ + sptr systemManager = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager(); + if (systemManager == nullptr) { + ZLOGE("System mgr is nullptr"); + return; + } + sptr callback(new SystemAbilityStatusChangeListener()); + systemManager->SubscribeSystemAbility(COMMON_EVENT_SERVICE_ID, callback); +} + void DataShareServiceImpl::SubscribeChange() { EventCenter::GetInstance().Subscribe(RemoteChangeEvent::RDB_META_SAVE, [this](const Event &event) { @@ -535,16 +576,36 @@ void DataShareServiceImpl::SaveLaunchInfo(const std::string &bundleName, const s } std::string extUri = uri; extUri.insert(strlen(EXT_URI_SCHEMA), "/"); + StoreMetaData meta = MakeMetaData(bundleName, userId, deviceId); + if (value.launchInfos.empty()) { + meta.storeId = ""; + AutoLaunchMetaData autoLaunchMetaData = {}; + std::vector tempData = {}; + autoLaunchMetaData.datas.emplace(extUri, tempData); + autoLaunchMetaData.launchForCleanData = value.launchForCleanData; + MetaDataManager::GetInstance().SaveMeta(meta.GetAutoLaunchKey(), autoLaunchMetaData, true); + ZLOGI("Without launchInfos, save meta end, bundleName = %{public}s.", bundleName.c_str()); + continue; + } for (const auto &launchInfo : value.launchInfos) { - AutoLaunchMetaData &autoLaunchMetaData = maps[launchInfo.storeId]; + AutoLaunchMetaData autoLaunchMetaData = {}; autoLaunchMetaData.datas.emplace(extUri, launchInfo.tableNames); + autoLaunchMetaData.launchForCleanData = value.launchForCleanData; + meta.storeId = launchInfo.storeId; + MetaDataManager::GetInstance().SaveMeta(meta.GetAutoLaunchKey(), autoLaunchMetaData, true); } } - StoreMetaData meta = MakeMetaData(bundleName, userId, deviceId); - for (const auto &[storeId, value] : maps) { - meta.storeId = storeId; - MetaDataManager::GetInstance().SaveMeta(meta.GetAutoLaunchKey(), value, true); +} + +bool DataShareServiceImpl::AllowCleanDataLaunchApp(const Event &event, bool launchForCleanData) +{ + auto &evt = static_cast(event); + auto dataInfo = evt.GetDataInfo(); + // 1 means CLOUD_DATA_CLEAN + if (dataInfo.changeType == 1) { + return launchForCleanData; // Applications can be started by default } + return true; } void DataShareServiceImpl::AutoLaunch(const Event &event) @@ -554,21 +615,30 @@ void DataShareServiceImpl::AutoLaunch(const Event &event) StoreMetaData meta = MakeMetaData(dataInfo.bundleName, dataInfo.userId, dataInfo.deviceId, dataInfo.storeId); AutoLaunchMetaData autoLaunchMetaData; if (!MetaDataManager::GetInstance().LoadMeta(std::move(meta.GetAutoLaunchKey()), autoLaunchMetaData, true)) { - return; + meta.storeId = ""; + if (!MetaDataManager::GetInstance().LoadMeta(std::move(meta.GetAutoLaunchKey()), autoLaunchMetaData, true)) { + ZLOGE("No launch meta without storeId, bundleName = %{public}s.", dataInfo.bundleName.c_str()); + return; + } } - if (autoLaunchMetaData.datas.empty()) { + if (autoLaunchMetaData.datas.empty() || !AllowCleanDataLaunchApp(event, autoLaunchMetaData.launchForCleanData)) { return; } - std::vector uris; for (const auto &[uri, metaTables] : autoLaunchMetaData.datas) { - for (const auto &table : dataInfo.tables) - if (std::find(metaTables.begin(), metaTables.end(), table) != metaTables.end()) { - uris.emplace_back(uri); - break; + if (dataInfo.tables.empty() && dataInfo.changeType == 1) { + ZLOGI("Start to connect extension, bundlename = %{public}s.", dataInfo.bundleName.c_str()); + AAFwk::WantParams wantParams; + ExtensionConnectAdaptor::TryAndWait(uri, dataInfo.bundleName, wantParams); + return; + } + for (const auto &table : dataInfo.tables) { + if (std::find(metaTables.begin(), metaTables.end(), table) != metaTables.end()) { + ZLOGI("Find table, start to connect extension, bundlename = %{public}s.", dataInfo.bundleName.c_str()); + AAFwk::WantParams wantParams; + ExtensionConnectAdaptor::TryAndWait(uri, dataInfo.bundleName, wantParams); + break; + } } - } - for (const auto &uri : uris) { - ExtensionConnectAdaptor::TryAndWait(uri, dataInfo.bundleName); } } @@ -602,6 +672,8 @@ int32_t DataShareServiceImpl::DataShareStatic::OnAppUninstall(const std::string TemplateData::Delete(bundleName, user); NativeRdb::RdbHelper::ClearCache(); BundleMgrProxy::GetInstance()->Delete(bundleName, user); + uint32_t tokenId = Security::AccessToken::AccessTokenKit::GetHapTokenID(user, bundleName, index); + DBDelegate::EraseStoreCache(tokenId); return E_OK; } @@ -630,6 +702,15 @@ int32_t DataShareServiceImpl::DataShareStatic::OnAppUpdate(const std::string &bu return E_OK; } +int32_t DataShareServiceImpl::DataShareStatic::OnClearAppStorage(const std::string &bundleName, + int32_t user, int32_t index, int32_t tokenId) +{ + ZLOGI("ClearAppStorage user=%{public}d, index=%{public}d, token:0x%{public}x, bundleName=%{public}s", + user, index, tokenId, bundleName.c_str()); + DBDelegate::EraseStoreCache(tokenId); + return E_OK; +} + int32_t DataShareServiceImpl::OnAppUninstall(const std::string &bundleName, int32_t user, int32_t index) { ZLOGI("AppUninstall user=%{public}d, index=%{public}d, bundleName=%{public}s", @@ -745,7 +826,8 @@ int32_t DataShareServiceImpl::EnableSilentProxy(const std::string &uri, bool ena int32_t DataShareServiceImpl::GetSilentProxyStatus(const std::string &uri, bool isCreateHelper) { - XCollie xcollie(__FUNCTION__, HiviewDFX::XCOLLIE_FLAG_LOG | HiviewDFX::XCOLLIE_FLAG_RECOVERY); + XCollie xcollie(std::string(LOG_TAG) + "::" + std::string(__FUNCTION__), + HiviewDFX::XCOLLIE_FLAG_LOG | HiviewDFX::XCOLLIE_FLAG_RECOVERY); uint32_t callerTokenId = IPCSkeleton::GetCallingTokenID(); if (isCreateHelper) { auto errCode = GetBMSAndMetaDataStatus(uri, callerTokenId); @@ -776,7 +858,8 @@ int32_t DataShareServiceImpl::GetSilentProxyStatus(const std::string &uri, bool int32_t DataShareServiceImpl::RegisterObserver(const std::string &uri, const sptr &remoteObj) { - XCollie xcollie(__FUNCTION__, HiviewDFX::XCOLLIE_FLAG_LOG); + XCollie xcollie(std::string(LOG_TAG) + "::" + std::string(__FUNCTION__), + HiviewDFX::XCOLLIE_FLAG_LOG); auto callerTokenId = IPCSkeleton::GetCallingTokenID(); DataProviderConfig providerConfig(uri, callerTokenId); auto [errCode, providerInfo] = providerConfig.GetProviderInfo(); @@ -809,7 +892,8 @@ int32_t DataShareServiceImpl::RegisterObserver(const std::string &uri, int32_t DataShareServiceImpl::UnregisterObserver(const std::string &uri, const sptr &remoteObj) { - XCollie xcollie(__FUNCTION__, HiviewDFX::XCOLLIE_FLAG_LOG); + XCollie xcollie(std::string(LOG_TAG) + "::" + std::string(__FUNCTION__), + HiviewDFX::XCOLLIE_FLAG_LOG); auto callerTokenId = IPCSkeleton::GetCallingTokenID(); DataProviderConfig providerConfig(uri, callerTokenId); auto [errCode, providerInfo] = providerConfig.GetProviderInfo(); @@ -839,37 +923,42 @@ int32_t DataShareServiceImpl::UnregisterObserver(const std::string &uri, return obsMgrClient->UnregisterObserver(Uri(uri), obServer); } -int32_t DataShareServiceImpl::Execute(const std::string &uri, const int32_t tokenId, - bool isRead, ExecuteCallback callback) +std::pair DataShareServiceImpl::ExecuteEx(const std::string &uri, const std::string &extUri, + const int32_t tokenId, bool isRead, ExecuteCallbackEx callback) { DataProviderConfig providerConfig(uri, tokenId); - auto [errCode, provider] = providerConfig.GetProviderInfo(); + auto [errCode, providerInfo] = providerConfig.GetProviderInfo(); if (errCode != E_OK) { ZLOGE("Provider failed! token:0x%{public}x,ret:%{public}d,uri:%{public}s", tokenId, - errCode, URIUtils::Anonymous(provider.uri).c_str()); + errCode, URIUtils::Anonymous(providerInfo.uri).c_str()); RADAR_REPORT(__FUNCTION__, RadarReporter::SILENT_ACCESS, RadarReporter::PROXY_GET_SUPPLIER, RadarReporter::FAILED, RadarReporter::ERROR_CODE, RadarReporter::SUPPLIER_ERROR); - return errCode; + return std::make_pair(errCode, 0); } - std::string permission = isRead ? provider.readPermission : provider.writePermission; + std::string permission = isRead ? providerInfo.readPermission : providerInfo.writePermission; if (!permission.empty() && !PermitDelegate::VerifyPermission(permission, tokenId)) { ZLOGE("Permission denied! token:0x%{public}x, permission:%{public}s, uri:%{public}s", - tokenId, permission.c_str(), URIUtils::Anonymous(provider.uri).c_str()); + tokenId, permission.c_str(), URIUtils::Anonymous(providerInfo.uri).c_str()); RADAR_REPORT(__FUNCTION__, RadarReporter::SILENT_ACCESS, RadarReporter::PROXY_PERMISSION, RadarReporter::FAILED, RadarReporter::ERROR_CODE, RadarReporter::PERMISSION_DENIED_ERROR); - return ERROR_PERMISSION_DENIED; + return std::make_pair(ERROR_PERMISSION_DENIED, 0); } DataShareDbConfig dbConfig; - auto [code, metaData, dbDelegate] = dbConfig.GetDbConfig(provider.uri, - provider.hasExtension, provider.bundleName, provider.storeName, - provider.singleton ? 0 : provider.currentUserId); + std::string extensionUri = extUri; + if (extensionUri.empty()) { + extensionUri = providerInfo.extensionUri; + } + DataShareDbConfig::DbConfig config {providerInfo.uri, extensionUri, providerInfo.bundleName, + providerInfo.storeName, providerInfo.backup, + providerInfo.singleton ? 0 : providerInfo.currentUserId, providerInfo.hasExtension}; + auto [code, metaData, dbDelegate] = dbConfig.GetDbConfig(config); if (code != E_OK) { ZLOGE("Get dbConfig fail,bundleName:%{public}s,tableName:%{public}s,tokenId:0x%{public}x, uri:%{public}s", - provider.bundleName.c_str(), provider.tableName.c_str(), tokenId, - URIUtils::Anonymous(provider.uri).c_str()); - return code; + providerInfo.bundleName.c_str(), providerInfo.tableName.c_str(), tokenId, + URIUtils::Anonymous(providerInfo.uri).c_str()); + return std::make_pair(code, 0); } - return callback(provider, metaData, dbDelegate); + return callback(providerInfo, metaData, dbDelegate); } int32_t DataShareServiceImpl::GetBMSAndMetaDataStatus(const std::string &uri, const int32_t tokenId) @@ -884,7 +973,7 @@ int32_t DataShareServiceImpl::GetBMSAndMetaDataStatus(const std::string &uri, co if (errCode != E_OK) { ZLOGE("CalledInfo failed! token:0x%{public}x,ret:%{public}d,uri:%{public}s", tokenId, errCode, URIUtils::Anonymous(calledInfo.uri).c_str()); - return E_BMS_NOT_READY; + return errCode; } DataShareDbConfig dbConfig; auto [code, metaData] = dbConfig.GetMetaData(calledInfo.uri, calledInfo.bundleName, diff --git a/datamgr_service/services/distributeddataservice/service/data_share/data_share_service_impl.h b/datamgr_service/services/distributeddataservice/service/data_share/data_share_service_impl.h index 261f51c7c5052ec833dfb867d79926490c3f83be..634322ccc33dfffdce4aec9b3f9960d1892f85a1 100644 --- a/datamgr_service/services/distributeddataservice/service/data_share/data_share_service_impl.h +++ b/datamgr_service/services/distributeddataservice/service/data_share/data_share_service_impl.h @@ -42,19 +42,15 @@ #include "visibility.h" namespace OHOS::DataShare { -class API_EXPORT DataShareServiceImpl : public DataShareServiceStub { +class DataShareServiceImpl : public DataShareServiceStub { public: using Handler = std::function> &)>; - using ExecuteCallback = std::function(DataProviderConfig::ProviderInfo &, DistributedData::StoreMetaData &, std::shared_ptr)>; DataShareServiceImpl() = default; virtual ~DataShareServiceImpl(); - int32_t Insert(const std::string &uri, const DataShareValuesBucket &valuesBucket) override; - int32_t Update(const std::string &uri, const DataSharePredicates &predicate, - const DataShareValuesBucket &valuesBucket) override; - int32_t Delete(const std::string &uri, const DataSharePredicates &predicate) override; - std::shared_ptr Query(const std::string &uri, const DataSharePredicates &predicates, - const std::vector &columns, int &errCode) override; + std::shared_ptr Query(const std::string &uri, const std::string &extUri, + const DataSharePredicates &predicates, const std::vector &columns, int &errCode) override; int32_t AddTemplate(const std::string &uri, const int64_t subscriberId, const Template &tplt) override; int32_t DelTemplate(const std::string &uri, const int64_t subscriberId) override; std::vector Publish(const Data &data, const std::string &bundleNameOfProvider) override; @@ -87,14 +83,21 @@ public: int32_t GetSilentProxyStatus(const std::string &uri, bool isCreateHelper) override; int32_t RegisterObserver(const std::string &uri, const sptr &remoteObj) override; int32_t UnregisterObserver(const std::string &uri, const sptr &remoteObj) override; - + std::pair InsertEx(const std::string &uri, const std::string &extUri, + const DataShareValuesBucket &valuesBucket) override; + std::pair UpdateEx(const std::string &uri, const std::string &extUri, + const DataSharePredicates &predicate, const DataShareValuesBucket &valuesBucket) override; + std::pair DeleteEx(const std::string &uri, const std::string &extUri, + const DataSharePredicates &predicate) override; private: + class SystemAbilityStatusChangeListener; using StaticActs = DistributedData::StaticActs; class DataShareStatic : public StaticActs { public: ~DataShareStatic() override {}; int32_t OnAppUninstall(const std::string &bundleName, int32_t user, int32_t index) override; int32_t OnAppUpdate(const std::string &bundleName, int32_t user, int32_t index) override; + int32_t OnClearAppStorage(const std::string &bundleName, int32_t user, int32_t index, int32_t tokenId) override; }; class Factory { public: @@ -108,18 +111,21 @@ private: TimerReceiver() = default; explicit TimerReceiver(const EventFwk::CommonEventSubscribeInfo &subscriberInfo); virtual ~TimerReceiver() = default; - virtual void OnReceiveEvent(const EventFwk::CommonEventData &eventData) override; + void OnReceiveEvent(const EventFwk::CommonEventData &eventData) override; }; void RegisterDataShareServiceInfo(); void RegisterHandler(); bool SubscribeTimeChanged(); bool NotifyChange(const std::string &uri); bool GetCallerBundleName(std::string &bundleName); - int32_t Execute(const std::string &uri, const int32_t tokenId, bool isRead, ExecuteCallback callback); + std::pair ExecuteEx(const std::string &uri, const std::string &extUri, const int32_t tokenId, + bool isRead, ExecuteCallbackEx callback); int32_t GetBMSAndMetaDataStatus(const std::string &uri, const int32_t tokenId); - void InitSubEvent(); + void SubscribeCommonEvent(); + static void InitSubEvent(); void AutoLaunch(const DistributedData::Event &event); void SubscribeChange(); + bool AllowCleanDataLaunchApp(const DistributedData::Event &event, bool launchForCleanData); static void SaveLaunchInfo(const std::string &bundleName, const std::string &userId, const std::string &deviceId); static DistributedData::StoreMetaData MakeMetaData(const std::string &bundleName, const std::string &userId, diff --git a/datamgr_service/services/distributeddataservice/service/data_share/data_share_service_stub.cpp b/datamgr_service/services/distributeddataservice/service/data_share/data_share_service_stub.cpp index acad4229d5262bfed6a1b5f3109158be5396386b..df4b59e5218ff04fd9902f32dd85095244578f32 100644 --- a/datamgr_service/services/distributeddataservice/service/data_share/data_share_service_stub.cpp +++ b/datamgr_service/services/distributeddataservice/service/data_share/data_share_service_stub.cpp @@ -38,52 +38,55 @@ bool DataShareServiceStub::CheckInterfaceToken(MessageParcel &data) return true; } -int32_t DataShareServiceStub::OnInsert(MessageParcel &data, MessageParcel &reply) +int32_t DataShareServiceStub::OnInsertEx(MessageParcel &data, MessageParcel &reply) { std::string uri; + std::string extUri; DataShareValuesBucket bucket; - if (!ITypesUtil::Unmarshal(data, uri, bucket.valuesMap)) { + if (!ITypesUtil::Unmarshal(data, uri, extUri, bucket.valuesMap)) { ZLOGE("Unmarshal uri:%{public}s bucket size:%{public}zu", DistributedData::Anonymous::Change(uri).c_str(), bucket.valuesMap.size()); return IPC_STUB_INVALID_DATA_ERR; } - int32_t status = Insert(uri, bucket); - if (!ITypesUtil::Marshal(reply, status)) { - ZLOGE("Marshal status:0x%{public}x", status); + auto [errCode, status] = InsertEx(uri, extUri, bucket); + if (!ITypesUtil::Marshal(reply, errCode, status)) { + ZLOGE("Marshal errCode: 0x%{public}x, status: 0x%{public}x", errCode, status); return IPC_STUB_WRITE_PARCEL_ERR; } return 0; } -int32_t DataShareServiceStub::OnUpdate(MessageParcel &data, MessageParcel &reply) +int32_t DataShareServiceStub::OnUpdateEx(MessageParcel &data, MessageParcel &reply) { std::string uri; + std::string extUri; DataSharePredicates predicate; DataShareValuesBucket bucket; - if (!ITypesUtil::Unmarshal(data, uri, predicate, bucket.valuesMap)) { + if (!ITypesUtil::Unmarshal(data, uri, extUri, predicate, bucket.valuesMap)) { ZLOGE("Unmarshal uri:%{public}s bucket size:%{public}zu", DistributedData::Anonymous::Change(uri).c_str(), bucket.valuesMap.size()); return IPC_STUB_INVALID_DATA_ERR; } - int32_t status = Update(uri, predicate, bucket); - if (!ITypesUtil::Marshal(reply, status)) { - ZLOGE("Marshal status:0x%{public}x", status); + auto [errCode, status] = UpdateEx(uri, extUri, predicate, bucket); + if (!ITypesUtil::Marshal(reply, errCode, status)) { + ZLOGE("Marshal errCode: 0x%{public}x, status: 0x%{public}x", errCode, status); return IPC_STUB_WRITE_PARCEL_ERR; } return 0; } -int32_t DataShareServiceStub::OnDelete(MessageParcel &data, MessageParcel &reply) +int32_t DataShareServiceStub::OnDeleteEx(MessageParcel &data, MessageParcel &reply) { std::string uri; + std::string extUri; DataSharePredicates predicate; - if (!ITypesUtil::Unmarshal(data, uri, predicate)) { + if (!ITypesUtil::Unmarshal(data, uri, extUri, predicate)) { ZLOGE("Unmarshal uri:%{public}s", DistributedData::Anonymous::Change(uri).c_str()); return IPC_STUB_INVALID_DATA_ERR; } - int32_t status = Delete(uri, predicate); - if (!ITypesUtil::Marshal(reply, status)) { - ZLOGE("Marshal status:0x%{public}x", status); + auto [errCode, status] = DeleteEx(uri, extUri, predicate); + if (!ITypesUtil::Marshal(reply, errCode, status)) { + ZLOGE("Marshal errCode: 0x%{public}x, status: 0x%{public}x", errCode, status); return IPC_STUB_WRITE_PARCEL_ERR; } return 0; @@ -92,15 +95,16 @@ int32_t DataShareServiceStub::OnDelete(MessageParcel &data, MessageParcel &reply int32_t DataShareServiceStub::OnQuery(MessageParcel &data, MessageParcel &reply) { std::string uri; + std::string extUri; DataSharePredicates predicate; std::vector columns; - if (!ITypesUtil::Unmarshal(data, uri, predicate, columns)) { + if (!ITypesUtil::Unmarshal(data, uri, extUri, predicate, columns)) { ZLOGE("Unmarshal uri:%{public}s columns size:%{public}zu", DistributedData::Anonymous::Change(uri).c_str(), columns.size()); return IPC_STUB_INVALID_DATA_ERR; } int status = 0; - auto result = ISharedResultSet::WriteToParcel(Query(uri, predicate, columns, status), reply); + auto result = ISharedResultSet::WriteToParcel(Query(uri, extUri, predicate, columns, status), reply); if (!ITypesUtil::Marshal(reply, status)) { ZLOGE("Marshal status:0x%{public}x", status); return IPC_STUB_WRITE_PARCEL_ERR; @@ -327,7 +331,7 @@ int DataShareServiceStub::OnRemoteRequest(uint32_t code, MessageParcel &data, Me std::this_thread::sleep_for(std::chrono::milliseconds(SLEEP_TIME)); } auto callingPid = IPCSkeleton::GetCallingPid(); - if (code != DATA_SHARE_SERVICE_CMD_QUERY) { + if (code != DATA_SHARE_SERVICE_CMD_QUERY && code != DATA_SHARE_SERVICE_CMD_GET_SILENT_PROXY_STATUS) { ZLOGI("code:%{public}u, callingPid:%{public}d", code, callingPid); } if (!CheckInterfaceToken(data)) { diff --git a/datamgr_service/services/distributeddataservice/service/data_share/data_share_service_stub.h b/datamgr_service/services/distributeddataservice/service/data_share/data_share_service_stub.h index 9daede9747bfc18d822379b19c8b7a9a84c7fd2c..d13b2099344894592e4804216ed2b2ef2a231625 100644 --- a/datamgr_service/services/distributeddataservice/service/data_share/data_share_service_stub.h +++ b/datamgr_service/services/distributeddataservice/service/data_share/data_share_service_stub.h @@ -29,9 +29,6 @@ public: private: static constexpr std::chrono::milliseconds TIME_THRESHOLD = std::chrono::milliseconds(500); static bool CheckInterfaceToken(MessageParcel& data); - int32_t OnInsert(MessageParcel& data, MessageParcel& reply); - int32_t OnUpdate(MessageParcel& data, MessageParcel& reply); - int32_t OnDelete(MessageParcel& data, MessageParcel& reply); int32_t OnQuery(MessageParcel& data, MessageParcel& reply); int32_t OnAddTemplate(MessageParcel& data, MessageParcel& reply); int32_t OnDelTemplate(MessageParcel& data, MessageParcel& reply); @@ -51,11 +48,11 @@ private: int32_t OnGetSilentProxyStatus(MessageParcel& data, MessageParcel& reply); int32_t OnRegisterObserver(MessageParcel& data, MessageParcel& reply); int32_t OnUnregisterObserver(MessageParcel& data, MessageParcel& reply); + int32_t OnInsertEx(MessageParcel& data, MessageParcel& reply); + int32_t OnUpdateEx(MessageParcel& data, MessageParcel& reply); + int32_t OnDeleteEx(MessageParcel& data, MessageParcel& reply); using RequestHandle = int (DataShareServiceStub::*)(MessageParcel &, MessageParcel &); static constexpr RequestHandle HANDLERS[DATA_SHARE_SERVICE_CMD_MAX] = { - &DataShareServiceStub::OnInsert, - &DataShareServiceStub::OnDelete, - &DataShareServiceStub::OnUpdate, &DataShareServiceStub::OnQuery, &DataShareServiceStub::OnAddTemplate, &DataShareServiceStub::OnDelTemplate, @@ -74,7 +71,10 @@ private: &DataShareServiceStub::OnSetSilentSwitch, &DataShareServiceStub::OnGetSilentProxyStatus, &DataShareServiceStub::OnRegisterObserver, - &DataShareServiceStub::OnUnregisterObserver}; + &DataShareServiceStub::OnUnregisterObserver, + &DataShareServiceStub::OnInsertEx, + &DataShareServiceStub::OnDeleteEx, + &DataShareServiceStub::OnUpdateEx}; static constexpr int SLEEP_TIME = 300; static constexpr int TRY_TIMES = 5; std::atomic isReady_ = false; diff --git a/datamgr_service/services/distributeddataservice/service/data_share/idata_share_service.h b/datamgr_service/services/distributeddataservice/service/data_share/idata_share_service.h index aa2da754aa2d58a7de165d45381b069222b72295..e57489fecdeda12978ad666a1fd1518c064aacc6 100644 --- a/datamgr_service/services/distributeddataservice/service/data_share/idata_share_service.h +++ b/datamgr_service/services/distributeddataservice/service/data_share/idata_share_service.h @@ -30,9 +30,6 @@ namespace OHOS::DataShare { class IDataShareService { public: enum { - DATA_SHARE_SERVICE_CMD_INSERT, - DATA_SHARE_SERVICE_CMD_DELETE, - DATA_SHARE_SERVICE_CMD_UPDATE, DATA_SHARE_SERVICE_CMD_QUERY, DATA_SHARE_SERVICE_CMD_ADD_TEMPLATE, DATA_SHARE_SERVICE_CMD_DEL_TEMPLATE, @@ -52,18 +49,17 @@ public: DATA_SHARE_SERVICE_CMD_GET_SILENT_PROXY_STATUS, DATA_SHARE_SERVICE_CMD_REGISTER_OBSERVER, DATA_SHARE_SERVICE_CMD_UNREGISTER_OBSERVER, + DATA_SHARE_SERVICE_CMD_INSERTEX, + DATA_SHARE_SERVICE_CMD_DELETEEX, + DATA_SHARE_SERVICE_CMD_UPDATEEX, DATA_SHARE_SERVICE_CMD_MAX }; enum { DATA_SHARE_ERROR = -1, DATA_SHARE_OK = 0 }; DECLARE_INTERFACE_DESCRIPTOR(u"OHOS.DataShare.IDataShareService"); - virtual int32_t Insert(const std::string &uri, const DataShareValuesBucket &valuesBucket) = 0; - virtual int32_t Update( - const std::string &uri, const DataSharePredicates &predicate, const DataShareValuesBucket &valuesBucket) = 0; - virtual int32_t Delete(const std::string &uri, const DataSharePredicates &predicate) = 0; - virtual std::shared_ptr Query(const std::string &uri, const DataSharePredicates &predicates, - const std::vector &columns, int &errCode) = 0; + virtual std::shared_ptr Query(const std::string &uri, const std::string &extUri, + const DataSharePredicates &predicates, const std::vector &columns, int &errCode) = 0; virtual int32_t AddTemplate(const std::string &uri, const int64_t subscriberId, const Template &tplt) = 0; virtual int32_t DelTemplate(const std::string &uri, const int64_t subscriberId) = 0; virtual std::vector Publish(const Data &data, const std::string &bundleNameOfProvider) = 0; @@ -91,6 +87,12 @@ public: virtual int32_t RegisterObserver(const std::string &uri, const sptr &remoteObj) = 0; virtual int32_t UnregisterObserver(const std::string &uri, const sptr &remoteObj) = 0; + virtual std::pair InsertEx( + const std::string &uri, const std::string &extUri, const DataShareValuesBucket &valuesBucket) = 0; + virtual std::pair UpdateEx(const std::string &uri, const std::string &extUri, + const DataSharePredicates &predicate, const DataShareValuesBucket &valuesBucket) = 0; + virtual std::pair DeleteEx(const std::string &uri, const std::string &extUri, + const DataSharePredicates &predicate) = 0; }; } // namespace OHOS::DataShare #endif // DISTRIBUTEDDATAFWK_IDATA_SHARE_SERVICE_H diff --git a/datamgr_service/services/distributeddataservice/service/data_share/strategies/data_proxy/load_config_from_data_proxy_node_strategy.cpp b/datamgr_service/services/distributeddataservice/service/data_share/strategies/data_proxy/load_config_from_data_proxy_node_strategy.cpp index 17f7436699c185b32f13f09f8d53b19616f9c09d..c796152ca0fcd267f999c1d713a424cecacb7785 100644 --- a/datamgr_service/services/distributeddataservice/service/data_share/strategies/data_proxy/load_config_from_data_proxy_node_strategy.cpp +++ b/datamgr_service/services/distributeddataservice/service/data_share/strategies/data_proxy/load_config_from_data_proxy_node_strategy.cpp @@ -30,8 +30,8 @@ bool LoadConfigFromDataProxyNodeStrategy::operator()(std::shared_ptr co return false; } context->type = PUBLISHED_DATA_TYPE; - if (!BundleMgrProxy::GetInstance()->GetBundleInfoFromBMS( - context->calledBundleName, context->currentUserId, context->bundleInfo)) { + if (BundleMgrProxy::GetInstance()->GetBundleInfoFromBMS( + context->calledBundleName, context->currentUserId, context->bundleInfo) != E_OK) { ZLOGE("GetBundleInfoFromBMS failed! bundleName: %{public}s", context->calledBundleName.c_str()); context->errCode = E_BUNDLE_NAME_NOT_EXIST; return false; @@ -40,9 +40,9 @@ bool LoadConfigFromDataProxyNodeStrategy::operator()(std::shared_ptr co context->permission = "reject"; return true; } - for (auto &hapModuleInfo : context->bundleInfo.hapModuleInfos) { + for (auto const &hapModuleInfo : context->bundleInfo.hapModuleInfos) { auto proxyDatas = hapModuleInfo.proxyDatas; - for (auto &proxyData : proxyDatas) { + for (auto const &proxyData : proxyDatas) { if (proxyData.uri != context->uri) { continue; } @@ -51,13 +51,11 @@ bool LoadConfigFromDataProxyNodeStrategy::operator()(std::shared_ptr co if (context->permission.empty()) { context->permission = "reject"; } - auto [ret, properties] = DataShareProfileConfig::GetDataProperties( - std::vector{proxyData.metadata}, hapModuleInfo.resourcePath, - hapModuleInfo.hapPath, DATA_SHARE_PROPERTIES_META); - if (ret == ERROR || ret == NOT_FOUND) { + auto properties = proxyData.profileInfo; + if (properties.resultCode == ERROR || properties.resultCode == NOT_FOUND) { return true; } - GetContextInfoFromDataProperties(properties, hapModuleInfo.moduleName, context); + GetContextInfoFromDataProperties(properties.profile, hapModuleInfo.moduleName, context); return true; } } diff --git a/datamgr_service/services/distributeddataservice/service/data_share/strategies/data_share/load_config_from_data_share_bundle_info_strategy.cpp b/datamgr_service/services/distributeddataservice/service/data_share/strategies/data_share/load_config_from_data_share_bundle_info_strategy.cpp index f9b2c72d2c50773b92bc4adc7428d586ef361955..edec38acfeb2429d138807b0cb733194e73b98aa 100644 --- a/datamgr_service/services/distributeddataservice/service/data_share/strategies/data_share/load_config_from_data_share_bundle_info_strategy.cpp +++ b/datamgr_service/services/distributeddataservice/service/data_share/strategies/data_share/load_config_from_data_share_bundle_info_strategy.cpp @@ -18,6 +18,7 @@ #include "bundle_mgr_proxy.h" #include "data_share_profile_config.h" +#include "datashare_errno.h" #include "log_print.h" #include "uri_utils.h" #include "utils/anonymous.h" @@ -79,25 +80,24 @@ bool LoadConfigFromDataShareBundleInfoStrategy::operator()(std::shared_ptrcalledBundleName.c_str()); return false; } - if (!BundleMgrProxy::GetInstance()->GetBundleInfoFromBMS( - context->calledBundleName, context->currentUserId, context->bundleInfo)) { + if (BundleMgrProxy::GetInstance()->GetBundleInfoFromBMS( + context->calledBundleName, context->currentUserId, context->bundleInfo) != E_OK) { ZLOGE("GetBundleInfoFromBMS failed! bundleName: %{public}s", context->calledBundleName.c_str()); return false; } - for (auto &item : context->bundleInfo.extensionInfos) { + for (auto const &item : context->bundleInfo.extensionInfos) { if (item.type == AppExecFwk::ExtensionAbilityType::DATASHARE) { context->permission = context->isRead ? item.readPermission : item.writePermission; - auto [ret, profileInfo] = DataShareProfileConfig::GetDataProperties(item.metadata, - item.resourcePath, item.hapPath, DATA_SHARE_EXTENSION_META); - if (ret == NOT_FOUND) { + auto profileInfo = item.profileInfo; + if (profileInfo.resultCode == NOT_FOUND) { return true; // optional meta data config } - if (ret == ERROR) { + if (profileInfo.resultCode == ERROR) { ZLOGE("parse failed! %{public}s", context->calledBundleName.c_str()); return false; } - LoadConfigFromProfile(profileInfo, context); + LoadConfigFromProfile(profileInfo.profile, context); return true; } } diff --git a/datamgr_service/services/distributeddataservice/service/data_share/strategies/general/load_config_data_info_strategy.cpp b/datamgr_service/services/distributeddataservice/service/data_share/strategies/general/load_config_data_info_strategy.cpp index f47d62e3cd7a15d36f4d5b7d00c7d5d0521a4d9e..a48ad89a8b816ac787683b9bb4c7f8c4eddf3f62 100644 --- a/datamgr_service/services/distributeddataservice/service/data_share/strategies/general/load_config_data_info_strategy.cpp +++ b/datamgr_service/services/distributeddataservice/service/data_share/strategies/general/load_config_data_info_strategy.cpp @@ -54,7 +54,8 @@ bool LoadConfigNormalDataInfoStrategy::operator()(std::shared_ptr conte DistributedData::StoreMetaData metaData; if (!QueryMetaData(context->calledBundleName, context->calledStoreName, metaData, context->currentUserId)) { // connect extension and retry - ExtensionConnectAdaptor::TryAndWait(context->uri, context->calledBundleName); + AAFwk::WantParams wantParams; + ExtensionConnectAdaptor::TryAndWait(context->uri, context->calledBundleName, wantParams); if (!QueryMetaData(context->calledBundleName, context->calledStoreName, metaData, context->currentUserId)) { ZLOGE("QueryMetaData fail, %{public}s", DistributedData::Anonymous::Change(context->uri).c_str()); context->errCode = NativeRdb::E_DB_NOT_EXIST; @@ -74,7 +75,8 @@ bool LoadConfigSingleDataInfoStrategy::operator()(std::shared_ptr conte DistributedData::StoreMetaData metaData; if (!QueryMetaData(context->calledBundleName, context->calledStoreName, metaData, 0)) { // connect extension and retry - ExtensionConnectAdaptor::TryAndWait(context->uri, context->calledBundleName); + AAFwk::WantParams wantParams; + ExtensionConnectAdaptor::TryAndWait(context->uri, context->calledBundleName, wantParams); if (!QueryMetaData(context->calledBundleName, context->calledStoreName, metaData, 0)) { ZLOGE("QueryMetaData fail, %{public}s", DistributedData::Anonymous::Change(context->uri).c_str()); context->errCode = NativeRdb::E_DB_NOT_EXIST; diff --git a/datamgr_service/services/distributeddataservice/service/data_share/subscriber_managers/rdb_subscriber_manager.cpp b/datamgr_service/services/distributeddataservice/service/data_share/subscriber_managers/rdb_subscriber_manager.cpp index 1ff14c391bd30541e7bf9fb97700ca1408ac367b..3ad175de106b39a0bd6a852a84ad1fd1cb8090f6 100644 --- a/datamgr_service/services/distributeddataservice/service/data_share/subscriber_managers/rdb_subscriber_manager.cpp +++ b/datamgr_service/services/distributeddataservice/service/data_share/subscriber_managers/rdb_subscriber_manager.cpp @@ -248,14 +248,19 @@ void RdbSubscriberManager::Emit(const std::string &uri, int32_t userId, if (!URIUtils::IsDataProxyURI(uri)) { return; } - rdbCache_.ForEach([&uri, &userId, &metaData, this](const Key &key, std::vector &val) { + bool hasObserver = false; + rdbCache_.ForEach([&uri, &userId, &metaData, &hasObserver, this](const Key &key, std::vector &val) { if (key.uri != uri) { return false; } + hasObserver = true; Notify(key, userId, val, metaData.dataDir, metaData.version); SetObserverNotifyOnEnabled(val); return false; }); + if (!hasObserver) { + return; + } SchedulerManager::GetInstance().Execute( uri, userId, metaData.dataDir, metaData.version, metaData.bundleName); } @@ -321,7 +326,7 @@ int RdbSubscriberManager::Notify(const Key &key, int32_t userId, const std::vect DistributedData::StoreMetaData meta; meta.dataDir = rdbDir; meta.bundleName = key.bundleName; - auto delegate = DBDelegate::Create(meta); + auto delegate = DBDelegate::Create(meta, key.uri); if (delegate == nullptr) { ZLOGE("Create fail %{public}s %{public}s", DistributedData::Anonymous::Change(key.uri).c_str(), key.bundleName.c_str()); diff --git a/datamgr_service/services/distributeddataservice/service/data_share/sys_event_subscriber.cpp b/datamgr_service/services/distributeddataservice/service/data_share/sys_event_subscriber.cpp index e802950ae503f0cb4b2b71ef4e649eb6adcf40d1..b0fe15ee2318ac49b302c0b461f0fdd80de88cd6 100644 --- a/datamgr_service/services/distributeddataservice/service/data_share/sys_event_subscriber.cpp +++ b/datamgr_service/services/distributeddataservice/service/data_share/sys_event_subscriber.cpp @@ -47,7 +47,9 @@ void SysEventSubscriber::NotifyDataShareReady() AAFwk::Want want; want.SetAction("usual.event.DATA_SHARE_READY"); EventFwk::CommonEventData CommonEventData { want }; - if (!EventFwk::CommonEventManager::PublishCommonEvent(CommonEventData)) { + EventFwk::CommonEventPublishInfo publishInfo; + publishInfo.SetSticky(true); + if (!EventFwk::CommonEventManager::PublishCommonEvent(CommonEventData, publishInfo)) { ZLOGE("Notify dataShare ready failed."); return; } diff --git a/datamgr_service/services/distributeddataservice/service/kvdb/auth_delegate.cpp b/datamgr_service/services/distributeddataservice/service/kvdb/auth_delegate.cpp index c50f1236e7fcc67a7406fdc3a0c26aef0efe1e67..fc72e1cfc6c4bcd37d5d8c26c80ab6a9124fc93d 100644 --- a/datamgr_service/services/distributeddataservice/service/kvdb/auth_delegate.cpp +++ b/datamgr_service/services/distributeddataservice/service/kvdb/auth_delegate.cpp @@ -23,132 +23,24 @@ #include "log_print.h" #include "user_delegate.h" #include "utils/anonymous.h" - +#include "metadata/store_meta_data.h" +#include "metadata/meta_data_manager.h" namespace OHOS::DistributedData { +using DmAdapter = OHOS::DistributedData::DeviceManagerAdapter; class AuthHandlerStub : public AuthHandler { public: // override for mock auth in current version, need remove in the future bool CheckAccess( - int localUserId, int peerUserId, const std::string &peerDeviceId, const std::string &appId) override; - + int localUserId, int peerUserId, const std::string &peerDeviceId, + int32_t authType, bool isSend = true) override; private: bool IsUserActive(const std::vector &users, int32_t userId); + bool CheckUsers(int localUserId, int peerUserId, const std::string &peerDeviceId); static constexpr pid_t UID_CAPACITY = 10000; static constexpr int SYSTEM_USER = 0; }; -bool AuthHandler::CheckAccess( - int localUserId, int peerUserId, const std::string &peerDeviceId, const std::string &appId) -{ - auto group = GetGroupInfo(localUserId, appId, peerDeviceId); - if (group.groupType < GroupType::ALL_GROUP) { - ZLOGE("failed to parse group %{public}s)", group.groupId.c_str()); - return false; - } - auto groupManager = GetGmInstance(); - if (groupManager == nullptr || groupManager->checkAccessToGroup == nullptr) { - ZLOGE("failed to get group manager"); - return false; - } - auto ret = groupManager->checkAccessToGroup(localUserId, appId.c_str(), group.groupId.c_str()); - ZLOGD("check access to group ret:%{public}d", ret); - return ret == HC_SUCCESS; -} - -int32_t AuthHandler::GetGroupType( - int localUserId, int peerUserId, const std::string &peerDeviceId, const std::string &appId) -{ - auto group = GetGroupInfo(localUserId, appId, peerDeviceId); - if (group.groupType < GroupType::ALL_GROUP) { - ZLOGE("failed to parse group json(%{public}d)", group.groupType); - } - return group.groupType; -} - -AuthHandler::RelatedGroup AuthHandler::GetGroupInfo( - int32_t localUserId, const std::string &appId, const std::string &peerDeviceId) -{ - auto groupManager = GetGmInstance(); - if (groupManager == nullptr || groupManager->getRelatedGroups == nullptr || groupManager->destroyInfo == nullptr) { - ZLOGE("failed to get group manager"); - return {}; - } - char *groupInfo = nullptr; - uint32_t groupNum = 0; - ZLOGI("get related groups, user:%{public}d, app:%{public}s", localUserId, appId.c_str()); - auto ret = groupManager->getRelatedGroups(localUserId, appId.c_str(), peerDeviceId.c_str(), &groupInfo, &groupNum); - if (groupInfo == nullptr) { - ZLOGE("failed to get related groups, ret:%{public}d", ret); - return {}; - } - ZLOGI("get related group json :%{public}s", groupInfo); - std::vector groups; - RelatedGroup::Unmarshall(groupInfo, groups); - groupManager->destroyInfo(&groupInfo); - - // same account has priority - std::sort(groups.begin(), groups.end(), - [](const RelatedGroup &group1, const RelatedGroup &group2) { return group1.groupType < group2.groupType; }); - if (!groups.empty()) { - ZLOGI("get group type:%{public}d", groups.front().groupType); - return groups.front(); - } - ZLOGD("there is no group to access to peer device:%{public}s", Anonymous::Change(peerDeviceId).c_str()); - return {}; -} - -std::vector AuthHandler::GetTrustedDevicesByType( - AUTH_GROUP_TYPE type, int32_t localUserId, const std::string &appId) -{ - auto groupManager = GetGmInstance(); - if (groupManager == nullptr || groupManager->getRelatedGroups == nullptr - || groupManager->getTrustedDevices == nullptr || groupManager->destroyInfo == nullptr) { - ZLOGE("failed to get group manager"); - return {}; - } - - char *groupsJson = nullptr; - uint32_t groupNum = 0; - ZLOGI("get joined groups, user:%{public}d, app:%{public}s, type:%{public}d", localUserId, appId.c_str(), type); - auto ret = groupManager->getJoinedGroups(localUserId, appId.c_str(), type, &groupsJson, &groupNum); - if (groupsJson == nullptr) { - ZLOGE("failed to get joined groups, ret:%{public}d", ret); - return {}; - } - ZLOGI("get joined group json :%{public}s", groupsJson); - std::vector groups; - RelatedGroup::Unmarshall(groupsJson, groups); - groupManager->destroyInfo(&groupsJson); - - std::vector trustedDevices; - for (const auto &group : groups) { - if (group.groupType != type) { - continue; - } - char *devicesJson = nullptr; - uint32_t devNum = 0; - ret = groupManager->getTrustedDevices(localUserId, appId.c_str(), group.groupId.c_str(), &devicesJson, &devNum); - if (devicesJson == nullptr) { - ZLOGE("failed to get trusted devicesJson, ret:%{public}d", ret); - return {}; - } - ZLOGI("get trusted device json:%{public}s", devicesJson); - std::vector devices; - TrustDevice::Unmarshall(devicesJson, devices); - groupManager->destroyInfo(&devicesJson); - for (const auto &item : devices) { - auto &dmAdapter = DeviceManagerAdapter::GetInstance(); - auto networkId = dmAdapter.ToNetworkID(item.authId); - auto uuid = dmAdapter.GetUuidByNetworkId(networkId); - trustedDevices.push_back(uuid); - } - } - - return trustedDevices; -} - -bool AuthHandlerStub::CheckAccess( - int localUserId, int peerUserId, const std::string &peerDeviceId, const std::string &appId) +bool AuthHandlerStub::CheckUsers(int localUserId, int peerUserId, const std::string &peerDeviceId) { if (localUserId == SYSTEM_USER) { return peerUserId == SYSTEM_USER; @@ -159,6 +51,17 @@ bool AuthHandlerStub::CheckAccess( return peerUserId != SYSTEM_USER && IsUserActive(localUsers, localUserId) && IsUserActive(peerUsers, peerUserId); } +bool AuthHandlerStub::CheckAccess( + int localUserId, int peerUserId, const std::string &peerDeviceId, int32_t authType, bool isSend) +{ + if (authType == static_cast(DistributedKv::AuthType::IDENTICAL_ACCOUNT) && + !DmAdapter::GetInstance().IsSameAccount(peerDeviceId)) { + ZLOGE("CheckAccess failed."); + return false; + } + return CheckUsers(localUserId, peerUserId, peerDeviceId); +} + bool AuthHandlerStub::IsUserActive(const std::vector &users, int32_t userId) { for (const auto &user : users) { diff --git a/datamgr_service/services/distributeddataservice/service/kvdb/auth_delegate.h b/datamgr_service/services/distributeddataservice/service/kvdb/auth_delegate.h index e6335c071bf53563dd6db3c00029283a03336f31..11a931993306d0ad1a572a482b3a8844af107666 100644 --- a/datamgr_service/services/distributeddataservice/service/kvdb/auth_delegate.h +++ b/datamgr_service/services/distributeddataservice/service/kvdb/auth_delegate.h @@ -32,57 +32,7 @@ enum AUTH_GROUP_TYPE { class AuthHandler { public: virtual bool CheckAccess( - int localUserId, int peerUserId, const std::string &peerDeviceId, const std::string &appId); - virtual int32_t GetGroupType( - int localUserId, int peerUserId, const std::string &peerDeviceId, const std::string &appId); - virtual std::vector GetTrustedDevicesByType( - AUTH_GROUP_TYPE type, int32_t localUserId, const std::string &appId); - -private: - struct RelatedGroup final : public Serializable { - int32_t groupType = -1; - std::string groupId; - RelatedGroup() - { - } - ~RelatedGroup() - { - } - RelatedGroup(const RelatedGroup &) = default; - RelatedGroup &operator=(const RelatedGroup &) = default; - bool Marshal(json &node) const override - { - SetValue(node[GET_NAME(groupType)], groupType); - SetValue(node[GET_NAME(groupId)], groupId); - return true; - } - - bool Unmarshal(const json &node) override - { - GetValue(node, GET_NAME(groupType), groupType); - GetValue(node, GET_NAME(groupId), groupId); - return true; - } - }; - - struct TrustDevice final : public Serializable { - std::string authId; // udid - TrustDevice() = default; - TrustDevice(const TrustDevice &) = default; - TrustDevice &operator=(const TrustDevice &) = default; - bool Marshal(json &node) const override - { - SetValue(node[GET_NAME(authId)], authId); - return true; - } - - bool Unmarshal(const json &node) override - { - GetValue(node, GET_NAME(authId), authId); - return true; - } - }; - static RelatedGroup GetGroupInfo(int32_t localUserId, const std::string &appId, const std::string &peerDeviceId); + int localUserId, int peerUserId, const std::string &peerDeviceId, int32_t authType, bool isSend = true); }; class AuthDelegate { diff --git a/datamgr_service/services/distributeddataservice/service/kvdb/kvdb_general_store.cpp b/datamgr_service/services/distributeddataservice/service/kvdb/kvdb_general_store.cpp index be9c07e48e300decd0404f91cd959d19d2e203da..9d24138d4fc87b52eb7c5ebd08371f3f5e6ee817 100644 --- a/datamgr_service/services/distributeddataservice/service/kvdb/kvdb_general_store.cpp +++ b/datamgr_service/services/distributeddataservice/service/kvdb/kvdb_general_store.cpp @@ -37,7 +37,7 @@ #include "utils/anonymous.h" #include "water_version_manager.h" #include "device_manager_adapter.h" -#include "utils/anonymous.h" +#include "app_id_mapping/app_id_mapping_config_manager.h" namespace OHOS::DistributedKv { using namespace DistributedData; @@ -49,6 +49,31 @@ using ClearMode = DistributedDB::ClearMode; using DMAdapter = DistributedData::DeviceManagerAdapter; using DBInterceptedData = DistributedDB::InterceptedData; constexpr int UUID_WIDTH = 4; +const std::map KVDBGeneralStore::dbStatusMap_ = { + { DBStatus::OK, GenErr::E_OK }, + { DBStatus::CLOUD_NETWORK_ERROR, GenErr::E_NETWORK_ERROR }, + { DBStatus::CLOUD_LOCK_ERROR, GenErr::E_LOCKED_BY_OTHERS }, + { DBStatus::CLOUD_FULL_RECORDS, GenErr::E_RECODE_LIMIT_EXCEEDED }, + { DBStatus::CLOUD_ASSET_SPACE_INSUFFICIENT, GenErr::E_NO_SPACE_FOR_ASSET }, + { DBStatus::CLOUD_SYNC_TASK_MERGED, GenErr::E_SYNC_TASK_MERGED }, + { DBStatus::BUSY, GenErr::E_DB_ERROR }, + { DBStatus::DB_ERROR, GenErr::E_DB_ERROR }, + { DBStatus::INVALID_ARGS, GenErr::E_INVALID_ARGS }, + { DBStatus::NOT_FOUND, GenErr::E_RECORD_NOT_FOUND }, + { DBStatus::INVALID_VALUE_FIELDS, GenErr::E_INVALID_VALUE_FIELDS }, + { DBStatus::INVALID_FIELD_TYPE, GenErr::E_INVALID_FIELD_TYPE }, + { DBStatus::CONSTRAIN_VIOLATION, GenErr::E_CONSTRAIN_VIOLATION }, + { DBStatus::INVALID_FORMAT, GenErr::E_INVALID_FORMAT }, + { DBStatus::INVALID_QUERY_FORMAT, GenErr::E_INVALID_QUERY_FORMAT }, + { DBStatus::INVALID_QUERY_FIELD, GenErr::E_INVALID_QUERY_FIELD }, + { DBStatus::NOT_SUPPORT, GenErr::E_NOT_SUPPORT }, + { DBStatus::TIME_OUT, GenErr::E_TIME_OUT }, + { DBStatus::OVER_MAX_LIMITS, GenErr::E_OVER_MAX_LIMITS }, + { DBStatus::EKEYREVOKED_ERROR, GenErr::E_SECURITY_LEVEL_ERROR }, + { DBStatus::SECURITY_OPTION_CHECK_ERROR, GenErr::E_SECURITY_LEVEL_ERROR }, +}; + +constexpr uint32_t LOCK_TIMEOUT = 3600; // second static DBSchema GetDBSchema(const Database &database) { DBSchema schema; @@ -136,6 +161,9 @@ KVDBGeneralStore::KVDBGeneralStore(const StoreMetaData &meta) meta.instanceId) { observer_.storeId_ = meta.storeId; + StoreMetaDataLocal local; + MetaDataManager::GetInstance().LoadMeta(meta.GetKeyLocal(), local, true); + isPublic_ = local.isPublic; DBStatus status = DBStatus::NOT_FOUND; manager_.SetKvStoreConfig({ meta.dataDir }); std::unique_lock lock(rwMutex_); @@ -153,7 +181,6 @@ KVDBGeneralStore::KVDBGeneralStore(const StoreMetaData &meta) SetDBReceiveDataInterceptor(meta.storeType); delegate_->RegisterObserver({}, DistributedDB::OBSERVER_CHANGES_FOREIGN, &observer_); delegate_->RegisterObserver({}, DistributedDB::OBSERVER_CHANGES_CLOUD, &observer_); - InitWaterVersion(meta); if (DeviceMatrix::GetInstance().IsDynamic(meta) || DeviceMatrix::GetInstance().IsStatics(meta)) { delegate_->SetRemotePushFinishedNotify([meta](const DistributedDB::RemotePushNotifyInfo &info) { DeviceMatrix::GetInstance().OnExchanged(info.deviceId, meta, DeviceMatrix::ChangeType::CHANGE_REMOTE); @@ -238,14 +265,17 @@ bool KVDBGeneralStore::IsBound() return isBound_; } -int32_t KVDBGeneralStore::Close() +int32_t KVDBGeneralStore::Close(bool isForce) { - std::unique_lock lock(rwMutex_); + std::unique_lock lock(rwMutex_, std::chrono::seconds(isForce ? LOCK_TIMEOUT : 0)); + if (!lock) { + return GeneralError::E_BUSY; + } + if (delegate_ == nullptr) { return GeneralError::E_OK; } - int32_t count = delegate_->GetTaskCount(); - if (count > 0) { + if (!isForce && delegate_->GetTaskCount() > 0) { return GeneralError::E_BUSY; } if (delegate_ != nullptr) { @@ -285,15 +315,15 @@ int32_t KVDBGeneralStore::Replace(const std::string &table, VBucket &&value) return GeneralError::E_NOT_SUPPORT; } -std::shared_ptr KVDBGeneralStore::Query( +std::pair> KVDBGeneralStore::Query( __attribute__((unused)) const std::string &table, const std::string &sql, Values &&args) { - return nullptr; + return { GeneralError::E_NOT_SUPPORT, nullptr }; } -std::shared_ptr KVDBGeneralStore::Query(const std::string &table, GenQuery &query) +std::pair> KVDBGeneralStore::Query(const std::string &table, GenQuery &query) { - return nullptr; + return { GeneralError::E_NOT_SUPPORT, nullptr }; } int32_t KVDBGeneralStore::MergeMigratedData(const std::string &tableName, VBuckets &&values) @@ -320,20 +350,14 @@ KVDBGeneralStore::DBSyncCallback KVDBGeneralStore::GetDBSyncCompleteCB(DetailAsy }; } -DBStatus KVDBGeneralStore::CloudSync(const Devices &devices, int32_t mode, DetailAsync async, int64_t wait) +DBStatus KVDBGeneralStore::CloudSync( + const Devices &devices, DistributedDB::SyncMode cloudSyncMode, DetailAsync async, int64_t wait) { - auto syncMode = GeneralStore::GetSyncMode(static_cast(mode)); - if (syncMode < CLOUD_BEGIN || syncMode >= CLOUD_END) { - ZLOGE("Do not need to cloud sync! devices count:%{public}zu, the 1st:%{public}s, syncMode:%{public}d", - devices.size(), devices.empty() ? "null" : Anonymous::Change(*devices.begin()).c_str(), syncMode); - return DBStatus::DB_ERROR; - } DistributedDB::CloudSyncOption syncOption; syncOption.devices = devices; - syncOption.mode = DistributedDB::SyncMode(syncMode); + syncOption.mode = cloudSyncMode; syncOption.waitTime = wait; syncOption.lockAction = DistributedDB::LockAction::NONE; - syncOption.merge = GeneralStore::GetHighMode(static_cast(mode)) == HighMode::AUTO_SYNC_MODE; if (storeInfo_.user == 0) { std::vector users; AccountDelegate::GetInstance()->QueryUsers(users); @@ -346,6 +370,7 @@ DBStatus KVDBGeneralStore::CloudSync(const Devices &devices, int32_t mode, Detai int32_t KVDBGeneralStore::Sync(const Devices &devices, GenQuery &query, DetailAsync async, SyncParam &syncParm) { + auto syncMode = GeneralStore::GetSyncMode(syncParm.mode); std::shared_lock lock(rwMutex_); if (delegate_ == nullptr) { ZLOGE("store already closed! devices count:%{public}zu, the 1st:%{public}s, mode:%{public}d", devices.size(), @@ -353,12 +378,12 @@ int32_t KVDBGeneralStore::Sync(const Devices &devices, GenQuery &query, DetailAs return GeneralError::E_ALREADY_CLOSED; } DBStatus dbStatus; - auto syncMode = GeneralStore::GetSyncMode(syncParm.mode); + auto dbMode = DistributedDB::SyncMode(syncMode); if (syncMode > NEARBY_END && syncMode < CLOUD_END) { if (!enableCloud_) { return GeneralError::E_NOT_SUPPORT; } - dbStatus = CloudSync(devices, syncParm.mode, async, syncParm.wait); + dbStatus = CloudSync(devices, dbMode, async, syncParm.wait); } else { if (devices.empty()) { ZLOGE("Devices is empty! mode:%{public}d", syncParm.mode); @@ -378,7 +403,6 @@ int32_t KVDBGeneralStore::Sync(const Devices &devices, GenQuery &query, DetailAs dbStatus = delegate_->UnSubscribeRemoteQuery(devices, GetDBSyncCompleteCB(std::move(async)), dbQuery, false); } else if (syncMode < NEARBY_END) { - auto dbMode = DistributedDB::SyncMode(syncMode); if (kvQuery->IsEmpty()) { dbStatus = delegate_->Sync(devices, dbMode, GetDBSyncCompleteCB(std::move(async)), false); } else { @@ -394,6 +418,12 @@ int32_t KVDBGeneralStore::Sync(const Devices &devices, GenQuery &query, DetailAs void KVDBGeneralStore::SetEqualIdentifier(const std::string &appId, const std::string &storeId) { + std::shared_lock lock(rwMutex_); + if (delegate_ == nullptr) { + ZLOGE("store already closed! appId:%{public}s storeId:%{public}s", appId.c_str(), + Anonymous::Change(storeId).c_str()); + return; + } std::vector sameAccountDevs {}; std::vector defaultAccountDevs {}; auto uuids = DMAdapter::ToUUID(DMAdapter::GetInstance().GetRemoteDevices()); @@ -401,18 +431,20 @@ void KVDBGeneralStore::SetEqualIdentifier(const std::string &appId, const std::s GetIdentifierParams(defaultAccountDevs, uuids, NO_ACCOUNT); if (!sameAccountDevs.empty()) { auto accountId = AccountDelegate::GetInstance()->GetUnencryptedAccountId(); - auto syncIdentifier = KvManager::GetKvStoreIdentifier(accountId, appId, storeId); - ZLOGI("same account set compatible identifier store:%{public}s, user:%{public}s, device:%{public}.10s", - Anonymous::Change(storeId).c_str(), Anonymous::Change(accountId).c_str(), - DistributedData::Serializable::Marshall(sameAccountDevs).c_str()); - delegate_->SetEqualIdentifier(syncIdentifier, sameAccountDevs); + auto convertedIds = AppIdMappingConfigManager::GetInstance().Convert(appId, accountId); + auto identifier = KvManager::GetKvStoreIdentifier(convertedIds.second, convertedIds.first, storeId); + ZLOGI("same account store:%{public}s, user:%{public}s, device:%{public}.10s, appId:%{public}s", + Anonymous::Change(storeId).c_str(), Anonymous::Change(convertedIds.second).c_str(), + DistributedData::Serializable::Marshall(sameAccountDevs).c_str(), convertedIds.first.c_str()); + delegate_->SetEqualIdentifier(identifier, sameAccountDevs); } if (!defaultAccountDevs.empty()) { - auto syncIdentifier = KvManager::GetKvStoreIdentifier(defaultAccountId, appId, storeId); - ZLOGI("no account set compatible identifier store:%{public}s, device:%{public}.10s", + auto convertedIds = AppIdMappingConfigManager::GetInstance().Convert(appId, defaultAccountId); + auto identifier = KvManager::GetKvStoreIdentifier(convertedIds.second, convertedIds.first, storeId); + ZLOGI("no account store:%{public}s, device:%{public}.10s, appId:%{public}s", Anonymous::Change(storeId).c_str(), - DistributedData::Serializable::Marshall(defaultAccountDevs).c_str()); - delegate_->SetEqualIdentifier(syncIdentifier, defaultAccountDevs); + DistributedData::Serializable::Marshall(defaultAccountDevs).c_str(), convertedIds.first.c_str()); + delegate_->SetEqualIdentifier(identifier, defaultAccountDevs); } } @@ -431,9 +463,9 @@ void KVDBGeneralStore::GetIdentifierParams(std::vector &devices, ZLOGI("devices size: %{public}zu", devices.size()); } -std::shared_ptr KVDBGeneralStore::PreSharing(GenQuery &query) +std::pair> KVDBGeneralStore::PreSharing(GenQuery &query) { - return nullptr; + return { GeneralError::E_NOT_SUPPORT, nullptr }; } int32_t KVDBGeneralStore::Clean(const std::vector &devices, int32_t mode, const std::string &tableName) @@ -450,7 +482,8 @@ int32_t KVDBGeneralStore::Clean(const std::vector &devices, int32_t DBStatus status = OK; switch (mode) { case CLOUD_INFO: - status = delegate_->RemoveDeviceData("", static_cast(CLOUD_INFO)); + status = delegate_->RemoveDeviceData( + "", isPublic_ ? static_cast(CLOUD_DATA) : static_cast(CLOUD_INFO)); break; case CLOUD_DATA: status = delegate_->RemoveDeviceData("", static_cast(CLOUD_DATA)); @@ -467,7 +500,7 @@ int32_t KVDBGeneralStore::Clean(const std::vector &devices, int32_t default: return GeneralError::E_ERROR; } - return status == DistributedDB::OK ? GeneralError::E_OK : GeneralError::E_ERROR; + return ConvertStatus(status); } int32_t KVDBGeneralStore::Watch(int32_t origin, Watcher &watcher) @@ -530,23 +563,11 @@ int32_t KVDBGeneralStore::SetTrackerTable( KVDBGeneralStore::GenErr KVDBGeneralStore::ConvertStatus(DistributedDB::DBStatus status) { - switch (status) { - case DBStatus::OK: - return GenErr::E_OK; - case DBStatus::CLOUD_NETWORK_ERROR: - return GenErr::E_NETWORK_ERROR; - case DBStatus::CLOUD_LOCK_ERROR: - return GenErr::E_LOCKED_BY_OTHERS; - case DBStatus::CLOUD_FULL_RECORDS: - return GenErr::E_RECODE_LIMIT_EXCEEDED; - case DBStatus::CLOUD_ASSET_SPACE_INSUFFICIENT: - return GenErr::E_NO_SPACE_FOR_ASSET; - case DBStatus::CLOUD_SYNC_TASK_MERGED: - return GenErr::E_SYNC_TASK_MERGED; - default: - ZLOGI("status:0x%{public}x", status); - break; + auto it = dbStatusMap_.find(status); + if (it != dbStatusMap_.end()) { + return it->second; } + ZLOGI("status:0x%{public}x", status); return GenErr::E_ERROR; } @@ -584,23 +605,6 @@ std::vector KVDBGeneralStore::GetWaterVersion(const std::string &de return res; } -void KVDBGeneralStore::InitWaterVersion(const StoreMetaData &meta) -{ - CheckerManager::StoreInfo info = { atoi(meta.user.c_str()), meta.tokenId, meta.bundleName, meta.storeId }; - bool isDynamic = CheckerManager::GetInstance().IsDynamic(info); - bool isStatic = CheckerManager::GetInstance().IsStatic(info); - if (!isDynamic && !isStatic) { - return; - } - delegate_->SetGenCloudVersionCallback([info](auto &originVersion) { - return WaterVersionManager::GetInstance().GetWaterVersion(info.bundleName, info.storeId); - }); - callback_ = [meta]() { - auto event = std::make_unique(CloudEvent::CLOUD_SYNC_FINISHED, meta); - EventCenter::GetInstance().PostEvent(std::move(event)); - }; -} - void KVDBGeneralStore::ObserverProxy::OnChange(DBOrigin origin, const std::string &originalId, DBChangeData &&data) { if (!HasWatcher()) { @@ -651,12 +655,11 @@ void KVDBGeneralStore::ObserverProxy::ConvertChangeData(const std::list KVDBGeneralStore::DBProcessCB KVDBGeneralStore::GetDBProcessCB(DetailAsync async) { - return [async, callback = callback_](const std::map &processes) { - if (!async && !callback) { + return [async](const std::map &processes) { + if (!async) { return; } DistributedData::GenDetails details; - bool downloadFinished = false; for (auto &[id, process] : processes) { auto &detail = details[id]; detail.progress = process.process; @@ -672,16 +675,15 @@ KVDBGeneralStore::DBProcessCB KVDBGeneralStore::GetDBProcessCB(DetailAsync async table.download.success = value.downLoadInfo.successCount; table.download.failed = value.downLoadInfo.failCount; table.download.untreated = table.download.total - table.download.success - table.download.failed; - downloadFinished = downloadFinished || - (process.process == FINISHED && value.downLoadInfo.successCount > 0); + detail.changeCount = (process.process == FINISHED) + ? value.downLoadInfo.insertCount + value.downLoadInfo.updateCount + + value.downLoadInfo.deleteCount + : 0; } } if (async) { async(details); } - if (downloadFinished && callback) { - callback(); - } }; } @@ -773,4 +775,19 @@ void KVDBGeneralStore::SetConfig(const GeneralStore::StoreConfig &storeConfig) { enableCloud_ = storeConfig.enableCloud_; } + +std::pair KVDBGeneralStore::LockCloudDB() +{ + return { GeneralError::E_NOT_SUPPORT, 0 }; +} + +int32_t KVDBGeneralStore::UnLockCloudDB() +{ + return GeneralError::E_NOT_SUPPORT; +} + +void KVDBGeneralStore::SetExecutor(std::shared_ptr executor) +{ + return; +} } // namespace OHOS::DistributedKv \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/kvdb/kvdb_general_store.h b/datamgr_service/services/distributeddataservice/service/kvdb/kvdb_general_store.h index b9ad8360c353c01f35600759d553eac8f0276ec8..a21efc30b45c819dd77736605c39120880aaba7a 100644 --- a/datamgr_service/services/distributeddataservice/service/kvdb/kvdb_general_store.h +++ b/datamgr_service/services/distributeddataservice/service/kvdb/kvdb_general_store.h @@ -57,16 +57,17 @@ public: Values &&conditions) override; int32_t Replace(const std::string &table, VBucket &&value) override; int32_t Delete(const std::string &table, const std::string &sql, Values &&args) override; - std::shared_ptr Query(const std::string &table, const std::string &sql, Values &&args) override; - std::shared_ptr Query(const std::string &table, GenQuery &query) override; + std::pair> Query(const std::string &table, const std::string &sql, + Values &&args) override; + std::pair> Query(const std::string &table, GenQuery &query) override; int32_t Sync(const Devices &devices, GenQuery &query, DetailAsync async, SyncParam &syncParm) override; - std::shared_ptr PreSharing(GenQuery &query) override; + std::pair> PreSharing(GenQuery &query) override; int32_t Clean(const std::vector &devices, int32_t mode, const std::string &tableName) override; int32_t Watch(int32_t origin, Watcher &watcher) override; int32_t Unwatch(int32_t origin, Watcher &watcher) override; int32_t RegisterDetailProgressObserver(DetailAsync async) override; int32_t UnregisterDetailProgressObserver() override; - int32_t Close() override; + int32_t Close(bool isForce = false) override; int32_t AddRef() override; int32_t Release() override; int32_t BindSnapshots(std::shared_ptr>> bindAssets) override; @@ -74,10 +75,12 @@ public: std::vector GetWaterVersion(const std::string &deviceId) override; void SetEqualIdentifier(const std::string &appId, const std::string &storeId) override; void SetConfig(const StoreConfig &storeConfig) override; - + void SetExecutor(std::shared_ptr executor) override; static DBPassword GetDBPassword(const StoreMetaData &data); static DBOption GetDBOption(const StoreMetaData &data, const DBPassword &password); static DBSecurity GetDBSecurity(int32_t secLevel); + virtual std::pair LockCloudDB() override; + virtual int32_t UnLockCloudDB() override; private: using KvDelegate = DistributedDB::KvStoreNbDelegate; @@ -91,8 +94,7 @@ private: std::vector GetNewKey(std::vector &key, const std::string &uuid); DBSyncCallback GetDBSyncCompleteCB(DetailAsync async); DBProcessCB GetDBProcessCB(DetailAsync async); - DBStatus CloudSync(const Devices &devices, int32_t mode, DetailAsync async, int64_t wait); - void InitWaterVersion(const StoreMetaData &meta); + DBStatus CloudSync(const Devices &devices, DistributedDB::SyncMode cloudSyncMode, DetailAsync async, int64_t wait); void GetIdentifierParams(std::vector &devices, const std::vector &uuids, int32_t authType); class ObserverProxy : public DistributedDB::KvStoreObserver { @@ -125,14 +127,15 @@ private: std::atomic isBound_ = false; std::mutex mutex_; int32_t ref_ = 1; - mutable std::shared_mutex rwMutex_; + mutable std::shared_timed_mutex rwMutex_; StoreInfo storeInfo_; - std::function callback_; static constexpr int32_t NO_ACCOUNT = 0; static constexpr int32_t IDENTICAL_ACCOUNT = 1; - static constexpr const char *defaultAccountId = "default"; + static constexpr const char *defaultAccountId = "ohosAnonymousUid"; bool enableCloud_ = false; + bool isPublic_ = false; + static const std::map dbStatusMap_; }; } // namespace OHOS::DistributedKv #endif // OHOS_DISTRIBUTED_DATA_DATAMGR_SERVICE_KVDB_GENERAL_STORE_H \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/kvdb/kvdb_service_impl.cpp b/datamgr_service/services/distributeddataservice/service/kvdb/kvdb_service_impl.cpp index ee0f35f0e61f7187138b1f681ec4c3c1e350f21d..b225490dc095a36c90e5dca4a0bfb8fc6839c90c 100644 --- a/datamgr_service/services/distributeddataservice/service/kvdb/kvdb_service_impl.cpp +++ b/datamgr_service/services/distributeddataservice/service/kvdb/kvdb_service_impl.cpp @@ -20,7 +20,6 @@ #include "accesstoken_kit.h" #include "account/account_delegate.h" -#include "auto_sync_matrix.h" #include "backup_manager.h" #include "bootstrap.h" #include "checker/checker_manager.h" @@ -100,10 +99,7 @@ void KVDBServiceImpl::Init() auto process = [this](const Event &event) { const auto &evt = static_cast(event); const auto &storeInfo = evt.GetStoreInfo(); - StoreMetaData meta; - meta.storeId = storeInfo.storeName; - meta.bundleName = storeInfo.bundleName; - meta.user = std::to_string(storeInfo.user); + StoreMetaData meta(storeInfo); meta.deviceId = DMAdapter::GetInstance().GetLocalDevice().uuid; if (!MetaDataManager::GetInstance().LoadMeta(meta.GetKey(), meta, true)) { if (meta.user == "0") { @@ -133,6 +129,7 @@ void KVDBServiceImpl::Init() store->RegisterDetailProgressObserver(nullptr); }; EventCenter::GetInstance().Subscribe(CloudEvent::CLOUD_SYNC, process); + EventCenter::GetInstance().Subscribe(CloudEvent::CLEAN_DATA, process); } void KVDBServiceImpl::RegisterKvServiceInfo() @@ -258,42 +255,14 @@ Status KVDBServiceImpl::Sync(const AppId &appId, const StoreId &storeId, SyncInf syncInfo.syncId = ++syncId_; RADAR_REPORT(STANDARD_DEVICE_SYNC, ADD_SYNC_TASK, RADAR_SUCCESS, BIZ_STATE, START, SYNC_STORE_ID, Anonymous::Change(storeId.storeId), SYNC_APP_ID, appId.appId, CONCURRENT_ID, - std::to_string(syncInfo.syncId), DATA_TYPE, metaData.dataType, SYNC_TYPE, SYNC); + std::to_string(syncInfo.syncId), DATA_TYPE, metaData.dataType, SYNC_TYPE, + SYNC, OS_TYPE, IsOHOSType(syncInfo.devices)); return KvStoreSyncManager::GetInstance()->AddSyncOperation(uintptr_t(metaData.tokenId), delay, std::bind(&KVDBServiceImpl::DoSyncInOrder, this, metaData, syncInfo, std::placeholders::_1, ACTION_SYNC), std::bind(&KVDBServiceImpl::DoComplete, this, metaData, syncInfo, RefCount(), std::placeholders::_1)); } -Status KVDBServiceImpl::SyncExt(const AppId &appId, const StoreId &storeId, SyncInfo &syncInfo) -{ - if (syncInfo.devices.empty()) { - return Status::INVALID_ARGUMENT; - } - StoreMetaData metaData = GetStoreMetaData(appId, storeId); - MetaDataManager::GetInstance().LoadMeta(metaData.GetKey(), metaData); - auto device = DMAdapter::GetInstance().ToUUID(syncInfo.devices[0]); - if (device.empty()) { - ZLOGE("invalid deviceId, appId:%{public}s storeId:%{public}s deviceId:%{public}s", - metaData.bundleName.c_str(), Anonymous::Change(metaData.storeId).c_str(), - Anonymous::Change(syncInfo.devices[0]).c_str()); - return Status::INVALID_ARGUMENT; - } - if (DeviceMatrix::GetInstance().IsSupportMatrix() && - ((!DeviceMatrix::GetInstance().IsStatics(metaData) && !DeviceMatrix::GetInstance().IsDynamic(metaData)) || - !IsRemoteChange(metaData, device))) { - ZLOGD("no change, do not need sync, appId:%{public}s storeId:%{public}s", - metaData.bundleName.c_str(), Anonymous::Change(metaData.storeId).c_str()); - DBResult dbResult = { {syncInfo.devices[0], DBStatus::OK} }; - DoComplete(metaData, syncInfo, RefCount(), std::move(dbResult)); - return SUCCESS; - } - syncInfo.syncId = ++syncId_; - return KvStoreSyncManager::GetInstance()->AddSyncOperation(uintptr_t(metaData.tokenId), 0, - std::bind(&KVDBServiceImpl::DoSyncInOrder, this, metaData, syncInfo, std::placeholders::_1, ACTION_SYNC), - std::bind(&KVDBServiceImpl::DoComplete, this, metaData, syncInfo, RefCount(), std::placeholders::_1)); -} - -Status KVDBServiceImpl::NotifyDataChange(const AppId &appId, const StoreId &storeId) +Status KVDBServiceImpl::NotifyDataChange(const AppId &appId, const StoreId &storeId, uint64_t delay) { StoreMetaData meta = GetStoreMetaData(appId, storeId); if (!MetaDataManager::GetInstance().LoadMeta(meta.GetKey(), meta)) { @@ -301,58 +270,20 @@ Status KVDBServiceImpl::NotifyDataChange(const AppId &appId, const StoreId &stor appId.appId.c_str(), Anonymous::Change(storeId.storeId).c_str()); return Status::INVALID_ARGUMENT; } - if (!DeviceMatrix::GetInstance().IsSupportMatrix()) { - if (meta.cloudAutoSync) { - DoCloudSync(meta, {}); - } - if (meta.isAutoSync) { - TryToSync(meta, true); - } - return SUCCESS; - } - if (DeviceMatrix::GetInstance().IsStatics(meta) || DeviceMatrix::GetInstance().IsDynamic(meta)) { + if (DeviceMatrix::GetInstance().IsSupportMatrix() && + (DeviceMatrix::GetInstance().IsStatics(meta) || DeviceMatrix::GetInstance().IsDynamic(meta))) { WaterVersionManager::GetInstance().GenerateWaterVersion(meta.bundleName, meta.storeId); DeviceMatrix::GetInstance().OnChanged(meta); - if (meta.cloudAutoSync) { - DoCloudSync(meta, {}); - } - return SUCCESS; - } - if (meta.cloudAutoSync) { - DoCloudSync(meta, {}); - } - if (meta.isAutoSync) { - AutoSyncMatrix::GetInstance().OnChanged(meta); - TryToSync(meta); } - return SUCCESS; -} -void KVDBServiceImpl::TryToSync(const StoreMetaData &metaData, bool force) -{ - auto devices = DMAdapter::ToUUID(DMAdapter::GetInstance().GetRemoteDevices()); - if (devices.empty()) { - return; - } - SyncInfo syncInfo; - syncInfo.mode = SyncMode::PUSH; - for (const auto &device : devices) { - if (!force && (!CommContext::GetInstance().IsSessionReady(device) || - !DMAdapter::GetInstance().IsDeviceReady(device))) { - continue; - } - ZLOGI("[TryToSync] appId:%{public}s, storeId:%{public}s", metaData.bundleName.c_str(), - Anonymous::Change(metaData.storeId).c_str()); - syncInfo.devices = { device }; - syncInfo.syncId = ++syncId_; - RADAR_REPORT(STANDARD_DEVICE_SYNC, ADD_SYNC_TASK, RADAR_SUCCESS, BIZ_STATE, START, - SYNC_STORE_ID, Anonymous::Change(metaData.storeId), SYNC_APP_ID, metaData.bundleName, - CONCURRENT_ID, std::to_string(syncInfo.syncId), DATA_TYPE, metaData.dataType, - SYNC_TYPE, REUSE_SOCKET_AUTO_SYNC); - KvStoreSyncManager::GetInstance()->AddSyncOperation(uintptr_t(metaData.tokenId), 0, - std::bind(&KVDBServiceImpl::DoSyncInOrder, this, metaData, syncInfo, std::placeholders::_1, ACTION_SYNC), - std::bind(&KVDBServiceImpl::DoComplete, this, metaData, syncInfo, RefCount(), std::placeholders::_1)); + if (executors_ != nullptr && (meta.cloudAutoSync)) { + executors_->Schedule(std::chrono::milliseconds(delay), [this, meta]() { + if (meta.cloudAutoSync) { + DoCloudSync(meta, {}); + } + }); } + return SUCCESS; } Status KVDBServiceImpl::PutSwitch(const AppId &appId, const SwitchData &data) @@ -416,76 +347,6 @@ Status KVDBServiceImpl::RegServiceNotifier(const AppId &appId, sptr mask) { - auto networkId = DMAdapter::GetInstance().ToNetworkID(device); - if (networkId.empty()) { - return; - } - OnDynamicChange(mask); - OnStaticsChange(mask); - }); -} - -void KVDBServiceImpl::OnStaticsChange(std::pair mask) -{ - bool isChanged = false; - syncAgents_.ForEach([mask, &isChanged](const auto &key, auto &value) { - StoreMetaData meta; - meta.appId = value.appId_; - meta.tokenId = key; - meta.bundleName = value.appId_; - meta.dataType = DataType::TYPE_STATICS; - if (!DeviceMatrix::GetInstance().IsStatics(meta)) { - return false; - } - uint16_t code = DeviceMatrix::GetInstance().GetCode(meta); - std::map clientMask; - bool changed = ((mask.first & code) == code); - if ((value.staticsChanged_ && changed) || (!value.staticsChanged_ && !changed)) { - return false; - } - value.staticsChanged_ = changed; - isChanged = true; - return false; - }); - if (isChanged) { - DoCloudSync(true); - } -} - -void KVDBServiceImpl::OnDynamicChange(std::pair mask) -{ - bool isChanged = false; - syncAgents_.ForEach([mask, &isChanged](const auto &key, auto &value) { - StoreMetaData meta; - meta.appId = value.appId_; - meta.tokenId = key; - meta.bundleName = value.appId_; - meta.dataType = DataType::TYPE_DYNAMICAL; - if (!DeviceMatrix::GetInstance().IsDynamic(meta)) { - return false; - } - uint16_t code = DeviceMatrix::GetInstance().GetCode(meta); - std::map clientMask; - bool changed = ((mask.second & code) == code); - if ((value.dynamicChanged_ && changed) || (!value.dynamicChanged_ && !changed)) { - return false; - } - value.dynamicChanged_ = changed; - isChanged = true; - return false; - }); - if (isChanged) { - DoCloudSync(false); - } -} - Status KVDBServiceImpl::UnregServiceNotifier(const AppId &appId) { syncAgents_.ComputeIfPresent(IPCSkeleton::GetCallingTokenID(), [&appId](const auto &key, SyncAgent &value) { @@ -780,20 +641,20 @@ Status KVDBServiceImpl::BeforeCreate(const AppId &appId, const StoreId &storeId, StoreMetaDataLocal oldLocal; MetaDataManager::GetInstance().LoadMeta(meta.GetKeyLocal(), oldLocal, true); // when user is 0, old store no "isPublic" attr, as well as new store's "isPublic" is true, do not intercept. - if (old.storeType != meta.storeType || Constant::NotEqual(old.isEncrypt, meta.isEncrypt) || - old.area != meta.area || !options.persistent || + if (old.storeType != meta.storeType || Constant::NotEqual(old.isEncrypt, meta.isEncrypt) || old.area != meta.area || + !options.persistent || (meta.securityLevel != NO_LABEL && (old.securityLevel > meta.securityLevel)) || (Constant::NotEqual(oldLocal.isPublic, options.isPublic) && (old.user != DEFAULT_USER_ID || !options.isPublic))) { ZLOGE("meta appId:%{public}s storeId:%{public}s user:%{public}s type:%{public}d->%{public}d " - "encrypt:%{public}d->%{public}d " - "area:%{public}d->%{public}d persistent:%{public}d isPublic:%{public}d->%{public}d", - appId.appId.c_str(), Anonymous::Change(storeId.storeId).c_str(), old.user.c_str(), old.storeType, - meta.storeType, old.isEncrypt, meta.isEncrypt, old.area, meta.area, options.persistent, oldLocal.isPublic, - options.isPublic); + "encrypt:%{public}d->%{public}d area:%{public}d->%{public}d persistent:%{public}d " + "securityLevel:%{public}d->%{public}d isPublic:%{public}d->%{public}d", + appId.appId.c_str(), Anonymous::Change(storeId.storeId).c_str(), old.user.c_str(), old.storeType, + meta.storeType, old.isEncrypt, meta.isEncrypt, old.area, meta.area, options.persistent, + old.securityLevel, meta.securityLevel, oldLocal.isPublic, options.isPublic); return Status::STORE_META_CHANGED; } - if (options.cloudConfig.enableCloud && (!isCreated || !meta.enableCloud) && executors_ != nullptr) { + if (options.cloudConfig.enableCloud && !meta.enableCloud && executors_ != nullptr) { DistributedData::StoreInfo storeInfo; storeInfo.bundleName = appId.appId; storeInfo.instanceId = GetInstIndex(storeInfo.tokenId, appId); @@ -922,36 +783,6 @@ int32_t KVDBServiceImpl::OnUserChange(uint32_t code, const std::string &user, co return SUCCESS; } -int32_t KVDBServiceImpl::OnReady(const std::string &device) -{ - return SUCCESS; -} - -int32_t KVDBServiceImpl::OnSessionReady(const std::string &device) -{ - ZLOGI("session ready, device:%{public}s", Anonymous::Change(device).c_str()); - if (!DMAdapter::GetInstance().IsDeviceReady(device)) { - return SUCCESS; - } - - auto stores = AutoSyncMatrix::GetInstance().GetChangedStore(device); - for (const auto &store : stores) { - ZLOGI("[OnSessionReady] appId:%{public}s, storeId:%{public}s", - store.bundleName.c_str(), Anonymous::Change(store.storeId).c_str()); - SyncInfo syncInfo; - syncInfo.mode = SyncMode::PUSH; - syncInfo.devices = { device }; - syncInfo.syncId = ++syncId_; - RADAR_REPORT(STANDARD_DEVICE_SYNC, ADD_SYNC_TASK, RADAR_SUCCESS, BIZ_STATE, START, - SYNC_STORE_ID, Anonymous::Change(store.storeId), SYNC_APP_ID, store.bundleName, - CONCURRENT_ID, std::to_string(syncInfo.syncId), SYNC_TYPE, AUTOSYNC); - KvStoreSyncManager::GetInstance()->AddSyncOperation(uintptr_t(store.tokenId), 0, - std::bind(&KVDBServiceImpl::DoSyncInOrder, this, store, syncInfo, std::placeholders::_1, ACTION_SYNC), - std::bind(&KVDBServiceImpl::DoComplete, this, store, syncInfo, RefCount(), std::placeholders::_1)); - } - return SUCCESS; -} - bool KVDBServiceImpl::IsRemoteChange(const StoreMetaData &metaData, const std::string &device) { auto code = DeviceMatrix::GetInstance().GetCode(metaData); @@ -970,12 +801,6 @@ bool KVDBServiceImpl::IsRemoteChange(const StoreMetaData &metaData, const std::s return (mask & code) == code; } -int32_t KVDBServiceImpl::Online(const std::string &device) -{ - AutoSyncMatrix::GetInstance().Online(device); - return SUCCESS; -} - void KVDBServiceImpl::AddOptions(const Options &options, StoreMetaData &metaData) { metaData.isAutoSync = options.autoSync; @@ -994,6 +819,7 @@ void KVDBServiceImpl::AddOptions(const Options &options, StoreMetaData &metaData metaData.dataType = options.dataType; metaData.enableCloud = options.cloudConfig.enableCloud; metaData.cloudAutoSync = options.cloudConfig.autoSync; + metaData.authType = static_cast(options.authType); } void KVDBServiceImpl::SaveLocalMetaData(const Options &options, const StoreMetaData &metaData) @@ -1067,33 +893,6 @@ KVDBServiceImpl::DBResult KVDBServiceImpl::HandleGenBriefDetails(const GenDetail return dbResults; } -void KVDBServiceImpl::DoCloudSync(bool isStatic) -{ - if (isStatic) { - auto staticStores = CheckerManager::GetInstance().GetStaticStores(); - for (auto &staticStore : staticStores) { - AppId appId = { staticStore.bundleName }; - StoreId storeId = { staticStore.storeId }; - auto status = CloudSync(appId, storeId, {}); - if (status != SUCCESS) { - ZLOGW("cloud sync failed:%{public}d, appId:%{public}s storeId:%{public}s", status, - staticStore.bundleName.c_str(), Anonymous::Change(staticStore.storeId).c_str()); - } - } - return; - } - auto dynamicStores = CheckerManager::GetInstance().GetDynamicStores(); - for (auto &dynamicStore : dynamicStores) { - AppId appId = { dynamicStore.bundleName }; - StoreId storeId = { dynamicStore.storeId }; - auto status = CloudSync(appId, storeId, {}); - if (status != SUCCESS) { - ZLOGW("cloud sync failed:%{public}d, appId:%{public}s storeId:%{public}s", status, - dynamicStore.bundleName.c_str(), Anonymous::Change(dynamicStore.storeId).c_str()); - } - } -} - Status KVDBServiceImpl::DoCloudSync(const StoreMetaData &meta, const SyncInfo &syncInfo) { if (!meta.enableCloud) { @@ -1134,7 +933,7 @@ Status KVDBServiceImpl::DoCloudSync(const StoreMetaData &meta, const SyncInfo &s }; auto mixMode = static_cast(GeneralStore::MixMode(GeneralStore::CLOUD_TIME_FIRST, meta.isAutoSync ? GeneralStore::AUTO_SYNC_MODE : GeneralStore::MANUAL_SYNC_MODE)); - auto info = ChangeEvent::EventInfo(mixMode, 0, false, nullptr, syncCallback); + auto info = ChangeEvent::EventInfo({ mixMode, 0, false, syncInfo.triggerMode }, false, nullptr, syncCallback); auto evt = std::make_unique(std::move(storeInfo), std::move(info)); EventCenter::GetInstance().PostEvent(std::move(evt)); return SUCCESS; @@ -1203,7 +1002,10 @@ bool KVDBServiceImpl::IsNeedMetaSync(const StoreMetaData &meta, const std::vecto metaData.deviceId = uuid; CapMetaData capMeta; auto capKey = CapMetaRow::GetKeyFor(uuid); - if (!MetaDataManager::GetInstance().LoadMeta(std::string(capKey.begin(), capKey.end()), capMeta) || + auto devInfo = DMAdapter::GetInstance().GetDeviceInfo(uuid); + if ((!MetaDataManager::GetInstance().LoadMeta(std::string(capKey.begin(), capKey.end()), capMeta) && + !(devInfo.osType != OH_OS_TYPE && + devInfo.deviceType == static_cast(DistributedHardware::DmDeviceType::DEVICE_TYPE_CAR))) || !MetaDataManager::GetInstance().LoadMeta(metaData.GetKey(), metaData)) { isAfterMeta = true; break; @@ -1313,7 +1115,6 @@ Status KVDBServiceImpl::DoComplete(const StoreMetaData &meta, const SyncInfo &in for (const auto &device : info.devices) { auto it = result.find(device); if (it != result.end() && it->second == SUCCESS) { - AutoSyncMatrix::GetInstance().OnExchanged(device, meta); DeviceMatrix::GetInstance().OnExchanged(device, meta, ConvertType(static_cast(info.mode))); } } @@ -1392,6 +1193,43 @@ Status KVDBServiceImpl::ConvertDbStatus(DBStatus status) const return Status::ERROR; } +Status KVDBServiceImpl::ConvertGeneralErr(GeneralError error) const +{ + switch (error) { + case GeneralError::E_DB_ERROR: + return Status::DB_ERROR; + case GeneralError::E_OK: + return Status::SUCCESS; + case GeneralError::E_INVALID_ARGS: + return Status::INVALID_ARGUMENT; + case GeneralError::E_RECORD_NOT_FOUND: + return Status::KEY_NOT_FOUND; + case GeneralError::E_INVALID_VALUE_FIELDS: + return Status::INVALID_VALUE_FIELDS; + case GeneralError::E_INVALID_FIELD_TYPE: + return Status::INVALID_FIELD_TYPE; + case GeneralError::E_CONSTRAIN_VIOLATION: + return Status::CONSTRAIN_VIOLATION; + case GeneralError::E_INVALID_FORMAT: + return Status::INVALID_FORMAT; + case GeneralError::E_INVALID_QUERY_FORMAT: + return Status::INVALID_QUERY_FORMAT; + case GeneralError::E_INVALID_QUERY_FIELD: + return Status::INVALID_QUERY_FIELD; + case GeneralError::E_NOT_SUPPORT: + return Status::NOT_SUPPORT; + case GeneralError::E_TIME_OUT: + return Status::TIME_OUT; + case GeneralError::E_OVER_MAX_LIMITS: + return Status::OVER_MAX_LIMITS; + case GeneralError::E_SECURITY_LEVEL_ERROR: + return Status::SECURITY_LEVEL_ERROR; + default: + break; + } + return Status::ERROR; +} + KVDBServiceImpl::DBMode KVDBServiceImpl::ConvertDBMode(SyncMode syncMode) const { DBMode dbMode; @@ -1513,7 +1351,43 @@ int32_t KVDBServiceImpl::OnInitialize() RegisterKvServiceInfo(); RegisterHandler(); Init(); - RegisterMatrixChange(); return SUCCESS; } + +bool KVDBServiceImpl::IsOHOSType(const std::vector &ids) +{ + if (ids.empty()) { + ZLOGI("ids is empty"); + return true; + } + bool isOHOSType = true; + for (auto &id : ids) { + if (!DMAdapter::GetInstance().IsOHOSType(id)) { + isOHOSType = false; + break; + } + } + return isOHOSType; +} + +Status KVDBServiceImpl::RemoveDeviceData(const AppId &appId, const StoreId &storeId, const std::string &device) +{ + StoreMetaData metaData = GetStoreMetaData(appId, storeId); + MetaDataManager::GetInstance().LoadMeta(metaData.GetKey(), metaData); + auto watcher = GetWatchers(metaData.tokenId, metaData.storeId); + auto store = AutoCache::GetInstance().GetStore(metaData, watcher); + if (store == nullptr) { + ZLOGE("GetStore failed! appId:%{public}s storeId:%{public}s dir:%{public}s", metaData.bundleName.c_str(), + Anonymous::Change(metaData.storeId).c_str(), metaData.dataDir.c_str()); + return Status::ERROR; + } + + int32_t ret; + if (device.empty()) { + ret = store->Clean({}, KVDBGeneralStore::NEARBY_DATA, ""); + } else { + ret = store->Clean({ DMAdapter::GetInstance().ToUUID(device) }, KVDBGeneralStore::NEARBY_DATA, ""); + } + return ConvertGeneralErr(GeneralError(ret)); +} } // namespace OHOS::DistributedKv \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/kvdb/kvdb_service_impl.h b/datamgr_service/services/distributeddataservice/service/kvdb/kvdb_service_impl.h index a43b204507884af3d6e9bce7f04d31acf2516664..38038ba2813c1851dc7cd87d3c1cc837bbe9cfe9 100644 --- a/datamgr_service/services/distributeddataservice/service/kvdb/kvdb_service_impl.h +++ b/datamgr_service/services/distributeddataservice/service/kvdb/kvdb_service_impl.h @@ -49,7 +49,6 @@ public: Status Close(const AppId &appId, const StoreId &storeId) override; Status CloudSync(const AppId &appId, const StoreId &storeId, const SyncInfo &syncInfo) override; Status Sync(const AppId &appId, const StoreId &storeId, SyncInfo &syncInfo) override; - Status SyncExt(const AppId &appId, const StoreId &storeId, SyncInfo &syncInfo) override; Status RegServiceNotifier(const AppId &appId, sptr notifier) override; Status UnregServiceNotifier(const AppId &appId) override; Status SetSyncParam(const AppId &appId, const StoreId &storeId, const KvSyncParam &syncParam) override; @@ -63,7 +62,7 @@ public: Status Subscribe(const AppId &appId, const StoreId &storeId, sptr observer) override; Status Unsubscribe(const AppId &appId, const StoreId &storeId, sptr observer) override; Status GetBackupPassword(const AppId &appId, const StoreId &storeId, std::vector &password) override; - Status NotifyDataChange(const AppId &appId, const StoreId &storeId) override; + Status NotifyDataChange(const AppId &appId, const StoreId &storeId, uint64_t delay) override; Status PutSwitch(const AppId &appId, const SwitchData &data) override; Status GetSwitch(const AppId &appId, const std::string &networkId, SwitchData &data) override; Status SubscribeSwitchData(const AppId &appId) override; @@ -74,9 +73,7 @@ public: int32_t OnAppExit(pid_t uid, pid_t pid, uint32_t tokenId, const std::string &appId) override; int32_t ResolveAutoLaunch(const std::string &identifier, DBLaunchParam ¶m) override; int32_t OnUserChange(uint32_t code, const std::string &user, const std::string &account) override; - int32_t Online(const std::string &device) override; - int32_t OnReady(const std::string &device) override; - int32_t OnSessionReady(const std::string &device) override; + Status RemoveDeviceData(const AppId &appId, const StoreId &storeId, const std::string &device) override; private: using StoreMetaData = OHOS::DistributedData::StoreMetaData; @@ -90,6 +87,7 @@ private: using DBStatus = DistributedDB::DBStatus; using DBMode = DistributedDB::SyncMode; using Action = OHOS::DistributedData::MetaDataManager::Action; + using GeneralError = DistributedData::GeneralError; enum SyncAction { ACTION_SYNC, ACTION_SUBSCRIBE, @@ -122,7 +120,7 @@ private: int32_t GetInstIndex(uint32_t tokenId, const AppId &appId); bool IsNeedMetaSync(const StoreMetaData &meta, const std::vector &uuids); Status DoCloudSync(const StoreMetaData &meta, const SyncInfo &syncInfo); - void DoCloudSync(bool isStatic); + void DoCloudSync(bool statics, bool dynamic); Status DoSync(const StoreMetaData &meta, const SyncInfo &info, const SyncEnd &complete, int32_t type); Status DoSyncInOrder(const StoreMetaData &meta, const SyncInfo &info, const SyncEnd &complete, int32_t type); Status DoSyncBegin(const std::vector &devices, const StoreMetaData &meta, @@ -130,6 +128,7 @@ private: Status DoComplete(const StoreMetaData &meta, const SyncInfo &info, RefCount refCount, const DBResult &dbResult); uint32_t GetSyncDelayTime(uint32_t delay, const StoreId &storeId); Status ConvertDbStatus(DBStatus status) const; + Status ConvertGeneralErr(GeneralError error) const; DBMode ConvertDBMode(SyncMode syncMode) const; ChangeType ConvertType(SyncMode syncMode) const; SwitchState ConvertAction(Action action) const; @@ -145,16 +144,15 @@ private: void SaveLocalMetaData(const Options &options, const StoreMetaData &metaData); void RegisterKvServiceInfo(); void RegisterHandler(); - void RegisterMatrixChange(); void DumpKvServiceInfo(int fd, std::map> ¶ms); void TryToSync(const StoreMetaData &metaData, bool force = false); - void OnStaticsChange(std::pair mask); - void OnDynamicChange(std::pair mask); bool IsRemoteChange(const StoreMetaData &metaData, const std::string &device); + bool IsOHOSType(const std::vector &ids); static Factory factory_; ConcurrentMap syncAgents_; std::shared_ptr executors_; std::atomic_uint64_t syncId_ = 0; + static constexpr int32_t OH_OS_TYPE = 10; }; } // namespace OHOS::DistributedKv #endif // OHOS_DISTRIBUTED_DATA_SERVICE_KVDB_SERVICE_IMPL_H \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/kvdb/kvdb_service_stub.cpp b/datamgr_service/services/distributeddataservice/service/kvdb/kvdb_service_stub.cpp index c224ccaa595dd53f2d75905770676453c028c6ae..cf7761ae8ed4f6928f343032f4937e3249e2b091 100644 --- a/datamgr_service/services/distributeddataservice/service/kvdb/kvdb_service_stub.cpp +++ b/datamgr_service/services/distributeddataservice/service/kvdb/kvdb_service_stub.cpp @@ -41,7 +41,6 @@ const KVDBServiceStub::Handler &KVDBServiceStub::OnSubscribe, &KVDBServiceStub::OnUnsubscribe, &KVDBServiceStub::OnGetBackupPassword, - &KVDBServiceStub::OnSyncExt, &KVDBServiceStub::OnCloudSync, &KVDBServiceStub::OnNotifyDataChange, &KVDBServiceStub::OnSetConfig, @@ -50,6 +49,7 @@ const KVDBServiceStub::Handler &KVDBServiceStub::OnSubscribeSwitchData, &KVDBServiceStub::OnUnsubscribeSwitchData, &KVDBServiceStub::OnClose, + &KVDBServiceStub::OnRemoveDeviceData, }; int KVDBServiceStub::OnRemoteRequest(uint32_t code, MessageParcel &data, MessageParcel &reply) @@ -108,7 +108,7 @@ std::pair KVDBServiceStub::GetStoreInfo(uin bool KVDBServiceStub::CheckPermission(uint32_t code, const StoreInfo &storeInfo) { if (code >= static_cast(KVDBServiceInterfaceCode::TRANS_PUT_SWITCH) && - code < static_cast(KVDBServiceInterfaceCode::TRANS_BUTT)) { + code <= static_cast(KVDBServiceInterfaceCode::TRANS_UNSUBSCRIBE_SWITCH_DATA)) { return CheckerManager::GetInstance().IsSwitches(storeInfo); } return CheckerManager::GetInstance().IsValid(storeInfo); @@ -221,29 +221,16 @@ int32_t KVDBServiceStub::OnCloudSync( return ERR_NONE; } -int32_t KVDBServiceStub::OnSyncExt( +int32_t KVDBServiceStub::OnNotifyDataChange( const AppId &appId, const StoreId &storeId, MessageParcel &data, MessageParcel &reply) { - SyncInfo syncInfo; - if (!ITypesUtil::Unmarshal( - data, syncInfo.seqId, syncInfo.mode, syncInfo.devices, syncInfo.delay, syncInfo.query)) { - ZLOGE("Unmarshal appId:%{public}s storeId:%{public}s", - appId.appId.c_str(), Anonymous::Change(storeId.storeId).c_str()); + uint64_t delay = 0; + if (!ITypesUtil::Unmarshal(data, delay)) { + ZLOGE("Unmarshal appId:%{public}s storeId:%{public}s", appId.appId.c_str(), + Anonymous::Change(storeId.storeId).c_str()); return IPC_STUB_INVALID_DATA_ERR; } - int32_t status = SyncExt(appId, storeId, syncInfo); - if (!ITypesUtil::Marshal(reply, status)) { - ZLOGE("Marshal status:0x%{public}x appId:%{public}s storeId:%{public}s", status, - appId.appId.c_str(), Anonymous::Change(storeId.storeId).c_str()); - return IPC_STUB_WRITE_PARCEL_ERR; - } - return ERR_NONE; -} - -int32_t KVDBServiceStub::OnNotifyDataChange( - const AppId &appId, const StoreId &storeId, MessageParcel &data, MessageParcel &reply) -{ - int32_t status = NotifyDataChange(appId, storeId); + int32_t status = NotifyDataChange(appId, storeId, delay); if (!ITypesUtil::Marshal(reply, status)) { ZLOGE("Marshal status:0x%{public}x appId:%{public}s storeId:%{public}s", status, appId.appId.c_str(), Anonymous::Change(storeId.storeId).c_str()); @@ -519,4 +506,21 @@ int32_t KVDBServiceStub::OnSetConfig(const AppId &appId, const StoreId &storeId, } return ERR_NONE; } + +int32_t KVDBServiceStub::OnRemoveDeviceData(const AppId &appId, const StoreId &storeId, MessageParcel &data, + MessageParcel &reply) +{ + std::string device; + if (!ITypesUtil::Unmarshal(data, device)) { + ZLOGE("Unmarshal appId:%{public}s storeId:%{public}s", appId.appId.c_str(), + Anonymous::Change(storeId.storeId).c_str()); + return IPC_STUB_INVALID_DATA_ERR; + } + int32_t status = RemoveDeviceData(appId, storeId, device); + if (!ITypesUtil::Marshal(reply, status)) { + ZLOGE("Marshal status:0x%{public}x appId:%{public}s", status, appId.appId.c_str()); + return IPC_STUB_WRITE_PARCEL_ERR; + } + return ERR_NONE; +} } // namespace OHOS::DistributedKv diff --git a/datamgr_service/services/distributeddataservice/service/kvdb/kvdb_service_stub.h b/datamgr_service/services/distributeddataservice/service/kvdb/kvdb_service_stub.h index 71abe63480c24cc018b44169edaf9e7ab3af03d5..a5deeaf1b28c7fe0cc648f0d9def3bfae2a5356b 100644 --- a/datamgr_service/services/distributeddataservice/service/kvdb/kvdb_service_stub.h +++ b/datamgr_service/services/distributeddataservice/service/kvdb/kvdb_service_stub.h @@ -50,7 +50,6 @@ private: int32_t OnSubscribe(const AppId &appId, const StoreId &storeId, MessageParcel &data, MessageParcel &reply); int32_t OnUnsubscribe(const AppId &appId, const StoreId &storeId, MessageParcel &data, MessageParcel &reply); int32_t OnGetBackupPassword(const AppId &appId, const StoreId &storeId, MessageParcel &data, MessageParcel &reply); - int32_t OnSyncExt(const AppId &appId, const StoreId &storeId, MessageParcel &data, MessageParcel &reply); int32_t OnNotifyDataChange(const AppId &appId, const StoreId &storeId, MessageParcel &data, MessageParcel &reply); int32_t OnPutSwitch(const AppId &appId, const StoreId &storeId, MessageParcel &data, MessageParcel &reply); int32_t OnGetSwitch(const AppId &appId, const StoreId &storeId, MessageParcel &data, MessageParcel &reply); @@ -59,6 +58,7 @@ private: int32_t OnUnsubscribeSwitchData(const AppId &appId, const StoreId &storeId, MessageParcel &data, MessageParcel &reply); int32_t OnSetConfig(const AppId &appId, const StoreId &storeId, MessageParcel &data, MessageParcel &reply); + int32_t OnRemoveDeviceData(const AppId &appId, const StoreId &storeId, MessageParcel &data, MessageParcel &reply); static const Handler HANDLERS[static_cast(KVDBServiceInterfaceCode::TRANS_BUTT)]; bool CheckPermission(uint32_t code, const StoreInfo &storeInfo); diff --git a/datamgr_service/services/distributeddataservice/service/matrix/include/auto_sync_matrix.h b/datamgr_service/services/distributeddataservice/service/matrix/include/auto_sync_matrix.h index 75445a8db74498d1e933a2c77f0c468175c808ab..d875a2358e68bf7a77ac97e065d23af54cccce71 100644 --- a/datamgr_service/services/distributeddataservice/service/matrix/include/auto_sync_matrix.h +++ b/datamgr_service/services/distributeddataservice/service/matrix/include/auto_sync_matrix.h @@ -19,6 +19,7 @@ #include #include #include + #include "metadata/store_meta_data.h" namespace OHOS::DistributedData { diff --git a/datamgr_service/services/distributeddataservice/service/matrix/include/device_matrix.h b/datamgr_service/services/distributeddataservice/service/matrix/include/device_matrix.h index 4fd6bc5c3e9162c00ebf0853a4e08cb1eec25e3d..6fb6068597c4a169c5c9d19783510dd2ffe8c4d9 100644 --- a/datamgr_service/services/distributeddataservice/service/matrix/include/device_matrix.h +++ b/datamgr_service/services/distributeddataservice/service/matrix/include/device_matrix.h @@ -16,6 +16,7 @@ #define OHOS_DISTRIBUTED_DATA_SERVICE_MATRIX_DEVICE_MATRIX_H #include #include + #include "eventcenter/event.h" #include "executor_pool.h" #include "lru_bucket.h" @@ -24,6 +25,7 @@ #include "metadata/store_meta_data.h" #include "utils/ref_count.h" #include "visibility.h" + namespace OHOS::DistributedData { class API_EXPORT DeviceMatrix { public: @@ -74,7 +76,6 @@ public: const StoreMetaData &metaData, ChangeType type = ChangeType::CHANGE_ALL); void UpdateLevel(const std::string &device, uint16_t level, LevelType type, bool isConsistent = false); void Clear(); - void RegRemoteChange(std::function)> observer); void SetExecutor(std::shared_ptr executors); uint16_t GetCode(const StoreMetaData &metaData); std::pair GetMask(const std::string &device, LevelType type = LevelType::DYNAMIC); @@ -87,6 +88,7 @@ public: bool IsDynamic(const StoreMetaData &metaData); bool IsStatics(const StoreMetaData &metaData); bool IsSupportMatrix(); + bool IsConsistent(); private: static constexpr uint32_t RESET_MASK_DELAY = 10; // min @@ -133,12 +135,13 @@ private: void UpdateMask(Mask &mask); void UpdateConsistentMeta(const std::string &device, const Mask &remote); void SaveSwitches(const std::string &device, const DataLevel &dataLevel); - void UpdateRemoteMeta(const std::string &device, Mask &mask); + void UpdateRemoteMeta(const std::string &device, Mask &mask, MatrixMetaData &newMeta); Task GenResetTask(); std::pair ConvertMask(const std::string &device, const DataLevel &dataLevel); uint16_t ConvertDynamic(const MatrixMetaData &meta, uint16_t mask); uint16_t ConvertStatics(const MatrixMetaData &meta, uint16_t mask); MatrixMetaData GetMatrixInfo(const std::string &device); + MatrixMetaData GetMatrixMetaData(const std::string &device, const Mask &mask); static inline uint16_t ConvertIndex(uint16_t code); MatrixEvent::MatrixData lasts_; @@ -155,9 +158,9 @@ private: std::map remotes_; std::vector dynamicApps_; std::vector staticsApps_; - std::function)> observer_; + std::function observer_; LRUBucket matrices_{ MAX_DEVICES }; LRUBucket versions_{ MAX_DEVICES }; }; } // namespace OHOS::DistributedData -#endif // OHOS_DISTRIBUTED_DATA_SERVICE_MATRIX_DEVICE_MATRIX_H +#endif // OHOS_DISTRIBUTED_DATA_SERVICE_MATRIX_DEVICE_MATRIX_H \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/matrix/src/auto_sync_matrix.cpp b/datamgr_service/services/distributeddataservice/service/matrix/src/auto_sync_matrix.cpp index c9986722a6b7693cc408494942ab965b2d4fcf26..4b6b38b5403c5dc4202b05731e4bd5de8cc9ca7a 100644 --- a/datamgr_service/services/distributeddataservice/service/matrix/src/auto_sync_matrix.cpp +++ b/datamgr_service/services/distributeddataservice/service/matrix/src/auto_sync_matrix.cpp @@ -16,10 +16,11 @@ #define LOG_TAG "AutoSyncMatrix" #include "auto_sync_matrix.h" + #include "bootstrap.h" #include "checker/checker_manager.h" -#include "device_matrix.h" #include "device_manager_adapter.h" +#include "device_matrix.h" #include "log_print.h" #include "metadata/meta_data_manager.h" #include "utils/anonymous.h" @@ -64,7 +65,7 @@ AutoSyncMatrix::AutoSyncMatrix() break; } return true; - }); + }); } AutoSyncMatrix::~AutoSyncMatrix() diff --git a/datamgr_service/services/distributeddataservice/service/matrix/src/device_matrix.cpp b/datamgr_service/services/distributeddataservice/service/matrix/src/device_matrix.cpp index da5c1ba546f08ab1af368f455e6c2137cae61966..337ae78613bf6c00286eeb44d462eaef2e53da4e 100644 --- a/datamgr_service/services/distributeddataservice/service/matrix/src/device_matrix.cpp +++ b/datamgr_service/services/distributeddataservice/service/matrix/src/device_matrix.cpp @@ -48,7 +48,7 @@ DeviceMatrix::DeviceMatrix() return true; } auto deviceId = std::move(metaData.deviceId); - ZLOGI("Matrix ver:%{public}u origin:%{public}d device:%{public}s", + ZLOGI("matrix version:%{public}u origin:%{public}d device:%{public}s", metaData.version, metaData.origin, Anonymous::Change(deviceId).c_str()); if (metaData.origin == MatrixMetaData::Origin::REMOTE_CONSISTENT) { return true; @@ -69,7 +69,7 @@ DeviceMatrix::DeviceMatrix() } auto deviceId = std::move(metaData.deviceId); versions_.Set(deviceId, metaData); - ZLOGI("Matrix ver:%{public}u device:%{public}s", + ZLOGI("matrix version:%{public}u device:%{public}s", metaData.version, Anonymous::Change(deviceId).c_str()); return true; }); @@ -118,7 +118,7 @@ bool DeviceMatrix::Initialize(uint32_t token, std::string storeId) newMeta.dynamic = Merge(oldMeta.dynamic, newMeta.dynamic); newMeta.statics = Merge(oldMeta.statics, newMeta.statics); } - ZLOGI("Save Matrix ver:%{public}u -> %{public}u ", oldMeta.version, newMeta.version); + ZLOGI("Save Matrix, oldMeta.version:%{public}u , newMeta.version:%{public}u ", oldMeta.version, newMeta.version); MetaDataManager::GetInstance().SaveMeta(newMeta.GetKey(), newMeta, true); return MetaDataManager::GetInstance().SaveMeta(newMeta.GetKey(), newMeta); } @@ -205,7 +205,8 @@ std::pair DeviceMatrix::OnBroadcast(const std::string &devic } else { mask.statics &= ~dataLevel.statics; } - UpdateRemoteMeta(device, mask); + auto meta = GetMatrixMetaData(device, mask); + UpdateRemoteMeta(device, mask, meta); { std::lock_guard lockGuard(mutex_); auto it = remotes_.find(device); @@ -215,9 +216,6 @@ std::pair DeviceMatrix::OnBroadcast(const std::string &devic } remotes_.insert_or_assign(device, mask); } - if (observer_) { - observer_(device, { mask.statics, mask.dynamic }); - } return { mask.dynamic, mask.statics }; } @@ -288,15 +286,20 @@ uint16_t DeviceMatrix::ConvertIndex(uint16_t code) return index; } -void DeviceMatrix::UpdateRemoteMeta(const std::string &device, Mask &mask) +MatrixMetaData DeviceMatrix::GetMatrixMetaData(const std::string &device, const Mask &mask) +{ + MatrixMetaData meta; + meta.dynamic = mask.dynamic; + meta.statics = mask.statics; + meta.deviceId = device; + meta.origin = Origin::REMOTE_RECEIVED; + meta.dynamicInfo = dynamicApps_; + meta.staticsInfo = staticsApps_; + return meta; +} + +void DeviceMatrix::UpdateRemoteMeta(const std::string &device, Mask &mask, MatrixMetaData &newMeta) { - MatrixMetaData newMeta; - newMeta.dynamic = mask.dynamic; - newMeta.statics = mask.statics; - newMeta.deviceId = device; - newMeta.origin = Origin::REMOTE_RECEIVED; - newMeta.dynamicInfo = dynamicApps_; - newMeta.staticsInfo = staticsApps_; auto [exist, oldMeta] = GetMatrixMeta(device); if (exist && oldMeta == newMeta) { return; @@ -364,15 +367,15 @@ void DeviceMatrix::Broadcast(const DataLevel &dataLevel) } matrix.dynamic |= Low(lasts_.dynamic); matrix.statics |= Low(lasts_.statics); - if (High(matrix.dynamic) != INVALID_HIGH && High(lasts_.dynamic)!= INVALID_HIGH && + if (High(matrix.dynamic) != INVALID_HIGH && High(lasts_.dynamic) != INVALID_HIGH && High(matrix.dynamic) < High(lasts_.dynamic)) { - matrix.dynamic &= 0x000F; - matrix.dynamic |= High(matrix.dynamic); + matrix.dynamic &= 0x000F; + matrix.dynamic |= High(matrix.dynamic); } - if (High(matrix.statics) != INVALID_HIGH && High(lasts_.statics)!= INVALID_HIGH && + if (High(matrix.statics) != INVALID_HIGH && High(lasts_.statics) != INVALID_HIGH && High(matrix.statics) < High(lasts_.statics)) { - matrix.statics &= 0x000F; - matrix.statics |= High(matrix.statics); + matrix.statics &= 0x000F; + matrix.statics |= High(matrix.statics); } EventCenter::GetInstance().PostEvent(std::make_unique(MATRIX_BROADCAST, "", matrix)); lasts_ = matrix; @@ -458,7 +461,7 @@ void DeviceMatrix::OnChanged(const StoreMetaData &metaData) void DeviceMatrix::OnExchanged(const std::string &device, uint16_t code, LevelType type, ChangeType changeType) { if (device.empty() || type < LevelType::STATICS || type > LevelType::DYNAMIC) { - ZLOGE("Invalid args.device:%{public}s, code:%{public}d, type:%{public}d", Anonymous::Change(device).c_str(), + ZLOGE("invalid args, device:%{public}s, code:%{public}d, type:%{public}d", Anonymous::Change(device).c_str(), code, type); return; } @@ -486,9 +489,6 @@ void DeviceMatrix::OnExchanged(const std::string &device, uint16_t code, LevelTy it->second.statics &= ~codes[LevelType::STATICS]; it->second.dynamic &= ~codes[LevelType::DYNAMIC]; UpdateConsistentMeta(device, it->second); - if (observer_) { - observer_(device, { it->second.statics, it->second.dynamic }); - } } } @@ -675,7 +675,7 @@ void DeviceMatrix::UpdateLevel(const std::string &device, uint16_t level, Device bool isConsistent) { if (device.empty() || type < 0 || type >= LevelType::BUTT) { - ZLOGE("Invalid args.device:%{public}s, level:%{public}d, type:%{public}d", Anonymous::Change(device).c_str(), + ZLOGE("invalid args, device:%{public}s, level:%{public}d, type:%{public}d", Anonymous::Change(device).c_str(), level, type); return; } @@ -713,15 +713,6 @@ MatrixMetaData DeviceMatrix::GetMatrixInfo(const std::string &device) return meta; } -void DeviceMatrix::RegRemoteChange(std::function)> observer) -{ - if (observer_) { - ZLOGD("duplicate register"); - return; - } - observer_ = std::move(observer); -} - bool DeviceMatrix::IsDynamic(const StoreMetaData &metaData) { if (metaData.dataType != LevelType::DYNAMIC) { @@ -771,4 +762,26 @@ bool DeviceMatrix::IsSupportMatrix() { return isSupportBroadcast_; } + +bool DeviceMatrix::IsConsistent() +{ + std::vector metas; + if (!MetaDataManager::GetInstance().LoadMeta(MatrixMetaData::GetPrefix({}), metas, true)) { + return true; + } + for (const auto &meta : metas) { + if (meta.origin == MatrixMetaData::Origin::REMOTE_RECEIVED) { + MatrixMetaData consistentMeta; + consistentMeta.deviceId = meta.deviceId; + if (!MetaDataManager::GetInstance().LoadMeta(consistentMeta.GetConsistentKey(), consistentMeta, true)) { + return false; + } + if ((High(meta.statics) > High(consistentMeta.statics)) || + (High(meta.dynamic) > High(consistentMeta.dynamic))) { + return false; + } + } + } + return true; +} } // namespace OHOS::DistributedData \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/object/object_asset_loader.cpp b/datamgr_service/services/distributeddataservice/service/object/object_asset_loader.cpp index acafa07b7bd5fa856035b9742d23ca8016284226..c3d582e6aef6ae46beef39d1bc06ae2c34d3794c 100644 --- a/datamgr_service/services/distributeddataservice/service/object/object_asset_loader.cpp +++ b/datamgr_service/services/distributeddataservice/service/object/object_asset_loader.cpp @@ -67,7 +67,6 @@ bool ObjectAssetLoader::Transfer(const int32_t userId, const std::string& bundle void ObjectAssetLoader::TransferAssetsAsync(const int32_t userId, const std::string& bundleName, const std::string& deviceId, const std::vector& assets, const TransferFunc& callback) { - RADAR_REPORT(ObjectStore::CREATE, ObjectStore::TRANSFER, ObjectStore::IDLE); if (executors_ == nullptr) { ZLOGE("executors is null, bundleName: %{public}s, deviceId: %{public}s, userId: %{public}d", bundleName.c_str(), DistributedData::Anonymous::Change(deviceId).c_str(), userId); @@ -124,9 +123,6 @@ void ObjectAssetLoader::FinishTask(const std::string& uri, bool result) if (task.downloadAssets.size() == 0 && task.callback != nullptr) { task.callback(result); finishedTasks.emplace_back(seq); - if (result) { - RADAR_REPORT(ObjectStore::CREATE, ObjectStore::TRANSFER, ObjectStore::RADAR_SUCCESS); - } } return false; }); @@ -171,7 +167,8 @@ bool ObjectAssetLoader::IsDownloaded(const DistributedData::Asset& asset) int32_t ObjectAssetLoader::PushAsset(int32_t userId, const sptr &assetObj, const sptr &sendCallback) { - RADAR_REPORT(ObjectStore::SAVE, ObjectStore::PUSH_ASSETS, ObjectStore::IDLE); + ObjectStore::RadarReporter::ReportStage(std::string(__FUNCTION__), ObjectStore::SAVE, + ObjectStore::PUSH_ASSETS, ObjectStore::IDLE); ZLOGI("PushAsset start, asset size:%{public}zu, bundleName:%{public}s, sessionId:%{public}s", assetObj->uris_.size(), assetObj->dstBundleName_.c_str(), assetObj->sessionId_.c_str()); auto status = Storage::DistributedFile::DistributedFileDaemonManager::GetInstance().PushAsset(userId, assetObj, @@ -179,20 +176,27 @@ int32_t ObjectAssetLoader::PushAsset(int32_t userId, const sptr &asset if (status != OBJECT_SUCCESS) { ZLOGE("PushAsset err status: %{public}d, asset size:%{public}zu, bundleName:%{public}s, sessionId:%{public}s", status, assetObj->uris_.size(), assetObj->dstBundleName_.c_str(), assetObj->sessionId_.c_str()); - RADAR_REPORT(ObjectStore::SAVE, ObjectStore::PUSH_ASSETS, ObjectStore::RADAR_FAILED, - ObjectStore::ERROR_CODE, status); + ObjectStore::RadarReporter::ReportStateError(std::string(__FUNCTION__), ObjectStore::SAVE, + ObjectStore::PUSH_ASSETS, ObjectStore::RADAR_FAILED, status, ObjectStore::FINISHED); } return status; } int32_t ObjectAssetsSendListener::OnSendResult(const sptr &assetObj, int32_t result) { + if (assetObj == nullptr) { + ZLOGE("OnSendResult error! status:%{public}d", result); + ObjectStore::RadarReporter::ReportStateError(std::string(__FUNCTION__), ObjectStore::SAVE, + ObjectStore::PUSH_ASSETS, ObjectStore::RADAR_FAILED, result, ObjectStore::FINISHED); + return result; + } ZLOGI("OnSendResult, status:%{public}d, asset size:%{public}zu", result, assetObj->uris_.size()); if (result == OBJECT_SUCCESS) { - RADAR_REPORT(ObjectStore::SAVE, ObjectStore::PUSH_ASSETS, ObjectStore::RADAR_SUCCESS); + ObjectStore::RadarReporter::ReportStage(std::string(__FUNCTION__), ObjectStore::SAVE, + ObjectStore::PUSH_ASSETS, ObjectStore::RADAR_SUCCESS); } else { - RADAR_REPORT(ObjectStore::SAVE, ObjectStore::PUSH_ASSETS, ObjectStore::RADAR_FAILED, - ObjectStore::ERROR_CODE, result); + ObjectStore::RadarReporter::ReportStateError(std::string(__FUNCTION__), ObjectStore::SAVE, + ObjectStore::PUSH_ASSETS, ObjectStore::RADAR_FAILED, result, ObjectStore::FINISHED); } return result; } diff --git a/datamgr_service/services/distributeddataservice/service/object/object_asset_machine.cpp b/datamgr_service/services/distributeddataservice/service/object/object_asset_machine.cpp index ce67d4df90da1df64b81162aea7d850ca32f6707..b15277a6cedaa221bbd1157cedf0cb36b1d27a79 100644 --- a/datamgr_service/services/distributeddataservice/service/object/object_asset_machine.cpp +++ b/datamgr_service/services/distributeddataservice/service/object/object_asset_machine.cpp @@ -125,7 +125,7 @@ static const DFAAction AssetDFA[STATUS_BUTT][EVENT_BUTT] = { { STATUS_STABLE, nullptr, (Action)CompensateSync }, // transfer_finished { STATUS_WAIT_UPLOAD, nullptr, (Action)ChangeAssetToNormal }, // upload { STATUS_NO_CHANGE, nullptr, (Action)Recover }, // upload_finished - { STATUS_WAIT_DOWNLOAD, nullptr, (Action)STATUS_WAIT_DOWNLOAD }, // download + { STATUS_WAIT_DOWNLOAD, nullptr, (Action)ChangeAssetToNormal }, // download { STATUS_NO_CHANGE, nullptr, (Action)Recover }, // download_finished } }; @@ -201,8 +201,8 @@ static VBuckets GetMigratedData(AutoCache::Store& store, AssetBindInfo& assetBin Values args; VBuckets vBuckets; auto sql = BuildSql(assetBindInfo, args); - auto cursor = store->Query(assetBindInfo.tableName, sql, std::move(args)); - if (cursor == nullptr) { + auto [errCode, cursor] = store->Query(assetBindInfo.tableName, sql, std::move(args)); + if (errCode != E_OK || cursor == nullptr) { return vBuckets; } int32_t count = cursor->GetCount(); diff --git a/datamgr_service/services/distributeddataservice/service/object/object_data_listener.cpp b/datamgr_service/services/distributeddataservice/service/object/object_data_listener.cpp index 4bd3c3d5d7977f4eabcfd9382cd21330b10cafb8..1c58fb4934c315ffb37f25faddceaf7815418497 100644 --- a/datamgr_service/services/distributeddataservice/service/object/object_data_listener.cpp +++ b/datamgr_service/services/distributeddataservice/service/object/object_data_listener.cpp @@ -18,6 +18,8 @@ #include "object_data_listener.h" #include "log_print.h" #include "object_manager.h" +#include "object_radar_reporter.h" +#include "utils/anonymous.h" namespace OHOS { namespace DistributedObject { ObjectDataListener::ObjectDataListener() @@ -56,10 +58,17 @@ int32_t ObjectAssetsRecvListener::OnStart(const std::string &srcNetworkId, const int32_t ObjectAssetsRecvListener::OnFinished(const std::string &srcNetworkId, const sptr &assetObj, int32_t result) { + if (assetObj == nullptr) { + ZLOGE("OnFinished error! status:%{public}d, srcNetworkId:%{public}s", result, + DistributedData::Anonymous::Change(srcNetworkId).c_str()); + ObjectStore::RadarReporter::ReportStageError(std::string(__FUNCTION__), ObjectStore::DATA_RESTORE, + ObjectStore::ASSETS_RECV, ObjectStore::RADAR_FAILED, result); + return result; + } auto objectKey = assetObj->dstBundleName_+assetObj->sessionId_; ZLOGI("OnFinished, status:%{public}d objectKey:%{public}s, asset size:%{public}zu", result, objectKey.c_str(), assetObj->uris_.size()); - ObjectStoreManager::GetInstance()->NotifyAssetsReady(objectKey, srcNetworkId); + ObjectStoreManager::GetInstance()->NotifyAssetsReady(objectKey, assetObj->dstBundleName_, srcNetworkId); return OBJECT_SUCCESS; } } // namespace DistributedObject diff --git a/datamgr_service/services/distributeddataservice/service/object/object_manager.cpp b/datamgr_service/services/distributeddataservice/service/object/object_manager.cpp index c4c231e28692b41f87c4919fe6d0965558afc166..2089491ab32e79efc5afb4e1a8730958782819e2 100644 --- a/datamgr_service/services/distributeddataservice/service/object/object_manager.cpp +++ b/datamgr_service/services/distributeddataservice/service/object/object_manager.cpp @@ -47,6 +47,7 @@ using Account = OHOS::DistributedKv::AccountDelegate; using AccessTokenKit = Security::AccessToken::AccessTokenKit; using ValueProxy = OHOS::DistributedData::ValueProxy; using DistributedFileDaemonManager = Storage::DistributedFile::DistributedFileDaemonManager; +constexpr const char *SAVE_INFO = "p_###SAVEINFO###"; ObjectStoreManager::ObjectStoreManager() { ZLOGI("ObjectStoreManager construct"); @@ -150,8 +151,8 @@ int32_t ObjectStoreManager::Save(const std::string &appId, const std::string &se if (result != OBJECT_SUCCESS) { ZLOGE("Open failed, errCode = %{public}d", result); proxy->Completed(std::map()); - RADAR_REPORT(ObjectStore::SAVE, ObjectStore::SAVE_TO_STORE, ObjectStore::RADAR_FAILED, - ObjectStore::ERROR_CODE, ObjectStore::GETKV_FAILED, ObjectStore::BIZ_STATE, ObjectStore::FINISHED); + ObjectStore::RadarReporter::ReportStateError(std::string(__FUNCTION__), ObjectStore::SAVE, + ObjectStore::SAVE_TO_STORE, ObjectStore::RADAR_FAILED, ObjectStore::GETKV_FAILED, ObjectStore::FINISHED); return STORE_NOT_OPEN; } @@ -160,6 +161,8 @@ int32_t ObjectStoreManager::Save(const std::string &appId, const std::string &se result = SaveToStore(appId, sessionId, deviceId, data); if (result != OBJECT_SUCCESS) { ZLOGE("Save failed, errCode = %{public}d", result); + ObjectStore::RadarReporter::ReportStateError(std::string(__FUNCTION__), ObjectStore::SAVE, + ObjectStore::SAVE_TO_STORE, ObjectStore::RADAR_FAILED, result, ObjectStore::FINISHED); Close(); proxy->Completed(std::map()); return result; @@ -168,14 +171,15 @@ int32_t ObjectStoreManager::Save(const std::string &appId, const std::string &se proxy->Completed(results); ProcessSyncCallback(results, appId, sessionId, deviceId); }; - ZLOGD("start SyncOnStore"); + ZLOGI("Sync data, bundleName: %{public}s, sessionId: %{public}s, deviceId: %{public}s", appId.c_str(), + sessionId.c_str(), Anonymous::Change(deviceId).c_str()); std::vector deviceList = {deviceId}; result = SyncOnStore(GetPropertyPrefix(appId, sessionId, deviceId), deviceList, tmp); if (result != OBJECT_SUCCESS) { ZLOGE("sync failed, errCode = %{public}d", result); proxy->Completed(std::map()); - RADAR_REPORT(ObjectStore::SAVE, ObjectStore::SAVE_TO_STORE, ObjectStore::RADAR_FAILED, - ObjectStore::ERROR_CODE, result, ObjectStore::BIZ_STATE, ObjectStore::FINISHED); + ObjectStore::RadarReporter::ReportStateError(std::string(__FUNCTION__), ObjectStore::SAVE, + ObjectStore::SYNC_DATA, ObjectStore::RADAR_FAILED, result, ObjectStore::FINISHED); } result = PushAssets(std::stoi(GetCurrentUser()), appId, sessionId, data, deviceId); Close(); @@ -268,13 +272,16 @@ int32_t ObjectStoreManager::Retrieve( allReady = true; } else { auto objectKey = bundleName + sessionId; - restoreStatus_.ComputeIfAbsent( - objectKey, [](const std::string& key) -> auto { - return RestoreStatus::NONE; + restoreStatus_.ComputeIfPresent(objectKey, [&allReady](const auto &key, auto &value) { + if (value == RestoreStatus::ALL_READY) { + allReady = true; + return false; + } + if (value == RestoreStatus::DATA_READY) { + value = RestoreStatus::DATA_NOTIFIED; + } + return true; }); - if (restoreStatus_[objectKey] == RestoreStatus::ALL_READY) { - allReady = true; - } } // delete local data status = RevokeSaveToStore(GetPrefixWithoutDeviceId(bundleName, sessionId)); @@ -286,8 +293,10 @@ int32_t ObjectStoreManager::Retrieve( } Close(); proxy->Completed(results, allReady); - RADAR_REPORT(ObjectStore::CREATE, ObjectStore::RESTORE, ObjectStore::RADAR_SUCCESS, ObjectStore::BIZ_STATE, - ObjectStore::FINISHED); + if (allReady) { + ObjectStore::RadarReporter::ReportStateFinished(std::string(__FUNCTION__), ObjectStore::DATA_RESTORE, + ObjectStore::NOTIFY, ObjectStore::RADAR_SUCCESS, ObjectStore::FINISHED); + } return status; } @@ -399,61 +408,113 @@ void ObjectStoreManager::UnregisterRemoteCallback(const std::string &bundleName, void ObjectStoreManager::NotifyChange(std::map> &changedData) { ZLOGI("OnChange start, size:%{public}zu", changedData.size()); - std::map> changedAssets = GetAssetsFromStore(changedData); - std::map>> data; bool hasAsset = false; - for (const auto &item : changedData) { - std::vector splitKeys = SplitEntryKey(item.first); - if (splitKeys.empty()) { - continue; - } - std::string prefix = splitKeys[BUNDLE_NAME_INDEX] + splitKeys[SESSION_ID_INDEX]; - std::string propertyName = splitKeys[PROPERTY_NAME_INDEX]; - data[prefix].insert_or_assign(propertyName, item.second); - if (IsAssetKey(propertyName)) { - hasAsset = true; + SaveInfo saveInfo; + for (const auto &[key, value] : changedData) { + if (key.find(SAVE_INFO) != std::string::npos) { + DistributedData::Serializable::Unmarshall(std::string(value.begin(), value.end()), saveInfo); + break; } } + auto data = GetObjectData(changedData, saveInfo, hasAsset); if (!hasAsset) { + ObjectStore::RadarReporter::ReportStateStart(std::string(__FUNCTION__), ObjectStore::DATA_RESTORE, + ObjectStore::DATA_RECV, ObjectStore::RADAR_SUCCESS, ObjectStore::START, saveInfo.bundleName); callbacks_.ForEach([this, &data](uint32_t tokenId, const CallbackInfo& value) { DoNotify(tokenId, value, data, true); // no asset, data ready means all ready return false; }); return; } - NotifyDataChanged(data); + NotifyDataChanged(data, saveInfo); SaveUserToMeta(); } -void ObjectStoreManager::NotifyDataChanged(std::map>>& data) +std::map>> ObjectStoreManager::GetObjectData( + const std::map>& changedData, SaveInfo& saveInfo, bool& hasAsset) { - for (auto const& [objectKey, results] : data) { - restoreStatus_.ComputeIfAbsent( - objectKey, [](const std::string& key) -> auto { - return RestoreStatus::NONE; - }); - if (restoreStatus_[objectKey] == RestoreStatus::ASSETS_READY) { - restoreStatus_[objectKey] = RestoreStatus::ALL_READY; + std::map>> data; + std::string keyPrefix = saveInfo.ToPropertyPrefix(); + if (!keyPrefix.empty()) { + std::string observerKey = saveInfo.bundleName + saveInfo.sessionId; + for (const auto &[key, value] : changedData) { + if (key.size() < keyPrefix.size() || key.find(SAVE_INFO) != std::string::npos) { + continue; + } + std::string propertyName = key.substr(keyPrefix.size()); + data[observerKey].insert_or_assign(propertyName, value); + if (!hasAsset && IsAssetKey(propertyName)) { + hasAsset = true; + } + } + } else { + for (const auto &item : changedData) { + std::vector splitKeys = SplitEntryKey(item.first); + if (splitKeys.size() <= PROPERTY_NAME_INDEX) { + continue; + } + if (saveInfo.sourceDeviceId.empty() || saveInfo.bundleName.empty()) { + saveInfo.sourceDeviceId = splitKeys[SOURCE_DEVICE_UDID_INDEX]; + saveInfo.bundleName = splitKeys[BUNDLE_NAME_INDEX]; + saveInfo.sessionId = splitKeys[SESSION_ID_INDEX]; + saveInfo.timestamp = splitKeys[TIME_INDEX]; + } + std::string prefix = splitKeys[BUNDLE_NAME_INDEX] + splitKeys[SESSION_ID_INDEX]; + std::string propertyName = splitKeys[PROPERTY_NAME_INDEX]; + data[prefix].insert_or_assign(propertyName, item.second); + if (IsAssetKey(propertyName)) { + hasAsset = true; + } + } + } + return data; +} + +void ObjectStoreManager::ComputeStatus(const std::string& objectKey, const SaveInfo& saveInfo, + const std::map>>& data) +{ + restoreStatus_.Compute(objectKey, [this, &data, saveInfo] (const auto &key, auto &value) { + if (value == RestoreStatus::ASSETS_READY) { + value = RestoreStatus::ALL_READY; + ObjectStore::RadarReporter::ReportStage(std::string(__FUNCTION__), ObjectStore::DATA_RESTORE, + ObjectStore::DATA_RECV, ObjectStore::RADAR_SUCCESS); callbacks_.ForEach([this, &data](uint32_t tokenId, const CallbackInfo& value) { DoNotify(tokenId, value, data, true); return false; }); } else { - restoreStatus_[objectKey] = RestoreStatus::DATA_READY; + value = RestoreStatus::DATA_READY; + ObjectStore::RadarReporter::ReportStateStart(std::string(__FUNCTION__), ObjectStore::DATA_RESTORE, + ObjectStore::DATA_RECV, ObjectStore::RADAR_SUCCESS, ObjectStore::START, saveInfo.bundleName); callbacks_.ForEach([this, &data](uint32_t tokenId, const CallbackInfo& value) { DoNotify(tokenId, value, data, false); return false; }); - WaitAssets(objectKey); + WaitAssets(key, saveInfo, data); } + return true; + }); +} + +void ObjectStoreManager::NotifyDataChanged( + const std::map>>& data, const SaveInfo& saveInfo) +{ + for (auto const& [objectKey, results] : data) { + restoreStatus_.ComputeIfAbsent( + objectKey, [](const std::string& key) -> auto { + return RestoreStatus::NONE; + }); + ComputeStatus(objectKey, saveInfo, data); } } -int32_t ObjectStoreManager::WaitAssets(const std::string& objectKey) +int32_t ObjectStoreManager::WaitAssets(const std::string& objectKey, const SaveInfo& saveInfo, + const std::map>>& data) { - auto taskId = executors_->Schedule(std::chrono::seconds(WAIT_TIME), [this, objectKey]() { - ZLOGE("wait assets finisehd timeout, objectKey:%{public}s", objectKey.c_str()); - NotifyAssetsReady(objectKey); + auto taskId = executors_->Schedule(std::chrono::seconds(WAIT_TIME), [this, objectKey, data, saveInfo]() { + ZLOGE("wait assets finisehd timeout, try pull assets, objectKey:%{public}s", objectKey.c_str()); + PullAssets(data, saveInfo); + DoNotifyWaitAssetTimeout(objectKey); }); objectTimer_.ComputeIfAbsent( @@ -463,73 +524,66 @@ int32_t ObjectStoreManager::WaitAssets(const std::string& objectKey) return OBJECT_SUCCESS; } -void ObjectStoreManager::NotifyAssetsReady(const std::string& objectKey, const std::string& srcNetworkId) +void ObjectStoreManager::PullAssets(const std::map>>& data, + const SaveInfo& saveInfo) { - restoreStatus_.ComputeIfAbsent( - objectKey, [](const std::string& key) -> auto { - return RestoreStatus::NONE; - }); - if (restoreStatus_[objectKey] == RestoreStatus::DATA_READY) { - restoreStatus_[objectKey] = RestoreStatus::ALL_READY; - callbacks_.ForEach([this, objectKey](uint32_t tokenId, const CallbackInfo& value) { - DoNotifyAssetsReady(tokenId, value, objectKey, true); - return false; + std::map changedAssets; + for (auto const& [objectId, result] : data) { + changedAssets[objectId] = GetAssetsFromDBRecords(result); + } + for (const auto& [objectId, assets] : changedAssets) { + std::string networkId = DmAdaper::GetInstance().ToNetworkID(saveInfo.sourceDeviceId); + auto block = std::make_shared>>(WAIT_TIME, std::tuple{ true, true }); + ObjectAssetLoader::GetInstance()->TransferAssetsAsync(std::stoi(GetCurrentUser()), + saveInfo.bundleName, networkId, assets, [this, block](bool success) { + block->SetValue({ false, success }); }); - } else { - restoreStatus_[objectKey] = RestoreStatus::ASSETS_READY; + auto [timeout, success] = block->GetValue(); + ZLOGI("Pull assets end, timeout: %{public}d, success: %{public}d, size:%{public}zu, deviceId: %{public}s", + timeout, success, assets.size(), DistributedData::Anonymous::Change(networkId).c_str()); } } -void ObjectStoreManager::NotifyAssetsStart(const std::string& objectKey, const std::string& srcNetworkId) +void ObjectStoreManager::NotifyAssetsReady(const std::string& objectKey, const std::string& bundleName, + const std::string& srcNetworkId) { restoreStatus_.ComputeIfAbsent( objectKey, [](const std::string& key) -> auto { return RestoreStatus::NONE; }); + restoreStatus_.Compute(objectKey, [this, &bundleName] (const auto &key, auto &value) { + if (value == RestoreStatus::DATA_NOTIFIED) { + value = RestoreStatus::ALL_READY; + ObjectStore::RadarReporter::ReportStage(std::string(__FUNCTION__), ObjectStore::DATA_RESTORE, + ObjectStore::ASSETS_RECV, ObjectStore::RADAR_SUCCESS); + callbacks_.ForEach([this, key](uint32_t tokenId, const CallbackInfo& value) { + DoNotifyAssetsReady(tokenId, value, key, true); + return false; + }); + } else if (value == RestoreStatus::DATA_READY) { + value = RestoreStatus::ALL_READY; + ObjectStore::RadarReporter::ReportStage(std::string(__FUNCTION__), ObjectStore::DATA_RESTORE, + ObjectStore::ASSETS_RECV, ObjectStore::RADAR_SUCCESS); + auto [has, taskId] = objectTimer_.Find(key); + if (has) { + executors_->Remove(taskId); + objectTimer_.Erase(key); + } + } else { + value = RestoreStatus::ASSETS_READY; + ObjectStore::RadarReporter::ReportStateStart(std::string(__FUNCTION__), ObjectStore::DATA_RESTORE, + ObjectStore::ASSETS_RECV, ObjectStore::RADAR_SUCCESS, ObjectStore::START, bundleName); + } + return true; + }); } -std::map> ObjectStoreManager::GetAssetsFromStore( - const std::map>& changedData) +void ObjectStoreManager::NotifyAssetsStart(const std::string& objectKey, const std::string& srcNetworkId) { - std::set assetKeyPrefix; - for (const auto& item : changedData) { - if (IsAssetKey(GetPropertyName(item.first))) { - assetKeyPrefix.insert(item.first.substr(0, item.first.find_last_of(ObjectStore::ASSET_DOT))); - } - } - std::map>>> results; - for (const auto& keyPrefix : assetKeyPrefix) { - std::vector entries; - auto status = delegate_->GetEntries(std::vector(keyPrefix.begin(), keyPrefix.end()), entries); - if (status != DistributedDB::DBStatus::OK) { - ZLOGE("GetEntries fail. keyPrefix = %{public}s", keyPrefix.c_str()); - continue; - } - std::map> result{}; - std::for_each(entries.begin(), entries.end(), [&result, this](const DistributedDB::Entry entry) { - std::string key(entry.key.begin(), entry.key.end()); - result[GetPropertyName(key)] = entry.value; - }); - std::vector splitKeys = SplitEntryKey(keyPrefix); - if (splitKeys.empty() || !IsAssetComplete(result, splitKeys[PROPERTY_NAME_INDEX])) { - continue; - } - std::string bundleName = splitKeys[BUNDLE_NAME_INDEX]; - std::string networkId = DmAdaper::GetInstance().ToNetworkID(splitKeys[SOURCE_DEVICE_UDID_INDEX]); - for (const auto &[key, value] : result) { - results[bundleName][networkId][key] = value; - } - } - std::map> changedAssets{}; - for (const auto& resultOfBundle : results) { - std::string bundleName = resultOfBundle.first; - for (const auto& resultOfDevice : resultOfBundle.second) { - std::string deviceId = resultOfDevice.first; - Assets assets = GetAssetsFromDBRecords(resultOfDevice.second); - changedAssets[bundleName][deviceId] = assets; - } - } - return changedAssets; + restoreStatus_.ComputeIfAbsent( + objectKey, [](const std::string& key) -> auto { + return RestoreStatus::NONE; + }); } bool ObjectStoreManager::IsAssetKey(const std::string& key) @@ -601,6 +655,13 @@ void ObjectStoreManager::DoNotify(uint32_t tokenId, const CallbackInfo& value, observer.second->Completed((*it).second, allReady); if (allReady) { restoreStatus_.Erase(observer.first); + ObjectStore::RadarReporter::ReportStateFinished(std::string(__FUNCTION__), ObjectStore::DATA_RESTORE, + ObjectStore::NOTIFY, ObjectStore::RADAR_SUCCESS, ObjectStore::FINISHED); + } else { + restoreStatus_.ComputeIfPresent(observer.first, [](const auto &key, auto &value) { + value = RestoreStatus::DATA_NOTIFIED; + return true; + }); } } } @@ -615,6 +676,8 @@ void ObjectStoreManager::DoNotifyAssetsReady(uint32_t tokenId, const CallbackInf observer.second->Completed(std::map>(), allReady); if (allReady) { restoreStatus_.Erase(objectKey); + ObjectStore::RadarReporter::ReportStateFinished(std::string(__FUNCTION__), ObjectStore::DATA_RESTORE, + ObjectStore::NOTIFY, ObjectStore::RADAR_SUCCESS, ObjectStore::FINISHED); } auto [has, taskId] = objectTimer_.Find(objectKey); if (has) { @@ -624,6 +687,29 @@ void ObjectStoreManager::DoNotifyAssetsReady(uint32_t tokenId, const CallbackInf } } +void ObjectStoreManager::DoNotifyWaitAssetTimeout(const std::string &objectKey) +{ + ObjectStore::RadarReporter::ReportStageError(std::string(__FUNCTION__), ObjectStore::DATA_RESTORE, + ObjectStore::ASSETS_RECV, ObjectStore::RADAR_FAILED, ObjectStore::TIMEOUT); + callbacks_.ForEach([this, &objectKey](uint32_t tokenId, const CallbackInfo &value) { + for (const auto& observer : value.observers_) { + if (objectKey != observer.first) { + continue; + } + observer.second->Completed(std::map>(), true); + restoreStatus_.Erase(objectKey); + auto [has, taskId] = objectTimer_.Find(objectKey); + if (has) { + executors_->Remove(taskId); + objectTimer_.Erase(objectKey); + } + ObjectStore::RadarReporter::ReportStateError(std::string(__FUNCTION__), ObjectStore::DATA_RESTORE, + ObjectStore::NOTIFY, ObjectStore::RADAR_FAILED, ObjectStore::TIMEOUT, ObjectStore::FINISHED); + } + return false; + }); +} + void ObjectStoreManager::SetData(const std::string &dataDir, const std::string &userId) { ZLOGI("enter %{public}s", dataDir.c_str()); @@ -662,6 +748,12 @@ void ObjectStoreManager::Close() if (delegate_ == nullptr) { return; } + int32_t taskCount = delegate_->GetTaskCount(); + if (taskCount > 0 && syncCount_ == 1) { + CloseAfterMinute(); + ZLOGW("Store is busy, close after a minute, task count: %{public}d", taskCount); + return; + } syncCount_--; ZLOGI("closed a store, syncCount = %{public}d", syncCount_); FlushClosedStore(); @@ -677,8 +769,19 @@ void ObjectStoreManager::SyncCompleted( SetSyncStatus(false); FlushClosedStore(); } + for (const auto &item : results) { + if (item.second == DistributedDB::DBStatus::OK) { + ZLOGI("Sync success, sequenceId: 0x%{public}" PRIx64 "", sequenceId); + ObjectStore::RadarReporter::ReportStateFinished(std::string(__FUNCTION__), ObjectStore::SAVE, + ObjectStore::SYNC_DATA, ObjectStore::RADAR_SUCCESS, ObjectStore::FINISHED); + } else { + ZLOGE("Sync failed, sequenceId: 0x%{public}" PRIx64 ", status: %{public}d", sequenceId, item.second); + ObjectStore::RadarReporter::ReportStateError(std::string(__FUNCTION__), ObjectStore::SAVE, + ObjectStore::SYNC_DATA, ObjectStore::RADAR_FAILED, item.second, ObjectStore::FINISHED); + } + } } - + void ObjectStoreManager::FlushClosedStore() { std::lock_guard lock(kvStoreMutex_); @@ -719,14 +822,15 @@ void ObjectStoreManager::ProcessOldEntry(const std::string &appId) if (splitKeys.empty()) { continue; } - std::string id = splitKeys[SESSION_ID_INDEX]; - if (sessionIds.count(id) == 0) { + std::string bundleName = splitKeys[BUNDLE_NAME_INDEX]; + std::string sessionId = splitKeys[SESSION_ID_INDEX]; + if (sessionIds.count(sessionId) == 0) { char *end = nullptr; - sessionIds[id] = strtol(splitKeys[TIME_INDEX].c_str(), &end, DECIMAL_BASE); + sessionIds[sessionId] = strtol(splitKeys[TIME_INDEX].c_str(), &end, DECIMAL_BASE); } - if (oldestTime == 0 || oldestTime > sessionIds[id]) { - oldestTime = sessionIds[id]; - deleteKey = GetPrefixWithoutDeviceId(appId, id); + if (oldestTime == 0 || oldestTime > sessionIds[sessionId]) { + oldestTime = sessionIds[sessionId]; + deleteKey = GetPrefixWithoutDeviceId(bundleName, sessionId); } } if (sessionIds.size() < MAX_OBJECT_SIZE_PER_APP) { @@ -747,6 +851,13 @@ int32_t ObjectStoreManager::SaveToStore(const std::string &appId, const std::str RevokeSaveToStore(GetPropertyPrefix(appId, sessionId, toDeviceId)); std::string timestamp = std::to_string(GetSecondsSince1970ToNow()); std::vector entries; + DistributedDB::Entry saveInfoEntry; + std::string saveInfoKey = GetPropertyPrefix(appId, sessionId, toDeviceId) + timestamp + SEPERATOR + SAVE_INFO; + saveInfoEntry.key = std::vector(saveInfoKey.begin(), saveInfoKey.end()); + SaveInfo saveInfo(appId, sessionId, DmAdaper::GetInstance().GetLocalDevice().udid, toDeviceId, timestamp); + std::string saveInfoValue = DistributedData::Serializable::Marshall(saveInfo); + saveInfoEntry.value = std::vector(saveInfoValue.begin(), saveInfoValue.end()); + entries.emplace_back(saveInfoEntry); for (auto &item : data) { DistributedDB::Entry entry; std::string tmp = GetPropertyPrefix(appId, sessionId, toDeviceId) + timestamp + SEPERATOR + item.first; @@ -757,8 +868,6 @@ int32_t ObjectStoreManager::SaveToStore(const std::string &appId, const std::str auto status = delegate_->PutBatch(entries); if (status != DistributedDB::DBStatus::OK) { ZLOGE("putBatch fail %{public}d", status); - RADAR_REPORT(ObjectStore::SAVE, ObjectStore::SAVE_TO_STORE, ObjectStore::RADAR_FAILED, - ObjectStore::ERROR_CODE, status, ObjectStore::BIZ_STATE, ObjectStore::FINISHED); } return status; } @@ -782,7 +891,7 @@ int32_t ObjectStoreManager::SyncOnStore( uint64_t sequenceId = SequenceSyncManager::GetInstance()->AddNotifier(userId_, callback); DistributedDB::Query dbQuery = DistributedDB::Query::Select(); dbQuery.PrefixKey(std::vector(prefix.begin(), prefix.end())); - ZLOGD("start sync"); + ZLOGI("Start sync, sequenceId: 0x%{public}" PRIx64 "", sequenceId); auto status = delegate_->Sync( syncDevices, DistributedDB::SyncMode::SYNC_MODE_PUSH_ONLY, [this, sequenceId](const std::map &devicesMap) { @@ -855,28 +964,69 @@ int32_t ObjectStoreManager::RetrieveFromStore( return DB_ERROR; } ZLOGI("GetEntries successfully"); - std::for_each(entries.begin(), entries.end(), [&results, this](const DistributedDB::Entry &entry) { + for (const auto &entry : entries) { std::string key(entry.key.begin(), entry.key.end()); - results[GetPropertyName(key)] = entry.value; - }); + if (key.find(SAVE_INFO) != std::string::npos) { + continue; + } + auto splitKeys = SplitEntryKey(key); + if (!splitKeys.empty()) { + results[splitKeys[PROPERTY_NAME_INDEX]] = entry.value; + } + } return OBJECT_SUCCESS; } +ObjectStoreManager::SaveInfo::SaveInfo(const std::string &bundleName, const std::string &sessionId, + const std::string &sourceDeviceId, const std::string &targetDeviceId, const std::string ×tamp) + : bundleName(bundleName), sessionId(sessionId), sourceDeviceId(sourceDeviceId), targetDeviceId(targetDeviceId), + timestamp(timestamp) {} + +bool ObjectStoreManager::SaveInfo::Marshal(json &node) const +{ + SetValue(node[GET_NAME(bundleName)], bundleName); + SetValue(node[GET_NAME(sessionId)], sessionId); + SetValue(node[GET_NAME(sourceDeviceId)], sourceDeviceId); + SetValue(node[GET_NAME(targetDeviceId)], targetDeviceId); + SetValue(node[GET_NAME(timestamp)], timestamp); + return true; +} + +bool ObjectStoreManager::SaveInfo::Unmarshal(const json &node) +{ + GetValue(node, GET_NAME(bundleName), bundleName); + GetValue(node, GET_NAME(sessionId), sessionId); + GetValue(node, GET_NAME(sourceDeviceId), sourceDeviceId); + GetValue(node, GET_NAME(targetDeviceId), targetDeviceId); + GetValue(node, GET_NAME(timestamp), timestamp); + return true; +} + +std::string ObjectStoreManager::SaveInfo::ToPropertyPrefix() +{ + if (bundleName.empty() || sessionId.empty() || sourceDeviceId.empty() || targetDeviceId.empty() || + timestamp.empty()) { + return ""; + } + return bundleName + SEPERATOR + sessionId + SEPERATOR + sourceDeviceId + SEPERATOR + targetDeviceId + SEPERATOR + + timestamp + SEPERATOR; +} + std::vector ObjectStoreManager::SplitEntryKey(const std::string &key) { std::smatch match; std::regex timeRegex(TIME_REGEX); if (!std::regex_search(key, match, timeRegex)) { - ZLOGE("Format error, key.size = %{public}zu", key.size()); + ZLOGW("Format error, key.size = %{public}zu", key.size()); return {}; } - size_t timePos = match.position(); + auto timePos = match.position(); std::string fromTime = key.substr(timePos + 1); std::string beforeTime = key.substr(0, timePos); size_t targetDevicePos = beforeTime.find_last_of(SEPERATOR); if (targetDevicePos == std::string::npos) { - ZLOGE("Format error, key.size = %{public}zu", key.size()); + ZLOGW("Format error, key.size = %{public}zu", key.size()); return {}; } std::string targetDevice = beforeTime.substr(targetDevicePos + 1); @@ -884,7 +1034,7 @@ std::vector ObjectStoreManager::SplitEntryKey(const std::string &ke size_t sourceDeviceUdidPos = beforeTargetDevice.find_last_of(SEPERATOR); if (sourceDeviceUdidPos == std::string::npos) { - ZLOGE("Format error, key.size = %{public}zu", key.size()); + ZLOGW("Format error, key.size = %{public}zu", key.size()); return {}; } std::string sourceDeviceUdid = beforeTargetDevice.substr(sourceDeviceUdidPos + 1); @@ -892,7 +1042,7 @@ std::vector ObjectStoreManager::SplitEntryKey(const std::string &ke size_t sessionIdPos = beforeSourceDeviceUdid.find_last_of(SEPERATOR); if (sessionIdPos == std::string::npos) { - ZLOGE("Format error, key.size = %{public}zu", key.size()); + ZLOGW("Format error, key.size = %{public}zu", key.size()); return {}; } std::string sessionId = beforeSourceDeviceUdid.substr(sessionIdPos + 1); @@ -900,7 +1050,7 @@ std::vector ObjectStoreManager::SplitEntryKey(const std::string &ke size_t propertyNamePos = fromTime.find_first_of(SEPERATOR); if (propertyNamePos == std::string::npos) { - ZLOGE("Format error, key.size = %{public}zu", key.size()); + ZLOGW("Format error, key.size = %{public}zu", key.size()); return {}; } std::string propertyName = fromTime.substr(propertyNamePos + 1); @@ -909,12 +1059,6 @@ std::vector ObjectStoreManager::SplitEntryKey(const std::string &ke return { bundleName, sessionId, sourceDeviceUdid, targetDevice, time, propertyName }; } -std::string ObjectStoreManager::GetPropertyName(const std::string &key) -{ - std::vector splitKeys = SplitEntryKey(key); - return splitKeys.empty() ? "" : splitKeys[PROPERTY_NAME_INDEX]; -} - std::string ObjectStoreManager::GetCurrentUser() { std::vector users; @@ -1026,7 +1170,11 @@ int32_t ObjectStoreManager::BindAsset(const uint32_t tokenId, const std::string& storeKey, [](const std::string& key) -> auto { return std::make_shared>>(); }); - bindSnapshots_[storeKey]->emplace(std::pair{asset.uri, snapshots_[snapshotKey]}); + auto snapshots = snapshots_.Find(snapshotKey).second; + bindSnapshots_.Compute(storeKey, [this, &asset, snapshots] (const auto &key, auto &value) { + value->emplace(std::pair{asset.uri, snapshots}); + return true; + }); HapTokenInfo tokenInfo; auto status = AccessTokenKit::GetHapTokenInfo(tokenId, tokenInfo); @@ -1041,7 +1189,10 @@ int32_t ObjectStoreManager::BindAsset(const uint32_t tokenId, const std::string& storeInfo.user = tokenInfo.userID; storeInfo.storeName = bindInfo.storeName; - snapshots_[snapshotKey]->BindAsset(ValueProxy::Convert(std::move(asset)), ConvertBindInfo(bindInfo), storeInfo); + snapshots_.Compute(snapshotKey, [this, &asset, &bindInfo, &storeInfo] (const auto &key, auto &value) { + value->BindAsset(ValueProxy::Convert(std::move(asset)), ConvertBindInfo(bindInfo), storeInfo); + return true; + }); return OBJECT_SUCCESS; } @@ -1063,8 +1214,16 @@ int32_t ObjectStoreManager::OnAssetChanged(const uint32_t tokenId, const std::st auto objectAsset = asset; Asset dataAsset = ValueProxy::Convert(std::move(objectAsset)); auto snapshotKey = appId + SEPERATOR + sessionId; - if (snapshots_.Contains(snapshotKey) && snapshots_[snapshotKey]->IsBoundAsset(dataAsset)) { - return snapshots_[snapshotKey]->OnDataChanged(dataAsset, deviceId); // needChange + int32_t res = OBJECT_SUCCESS; + bool exist = snapshots_.ComputeIfPresent(snapshotKey, + [&res, &dataAsset, &deviceId](const std::string &key, std::shared_ptr snapshot) { + if (snapshot != nullptr) { + res = snapshot->OnDataChanged(dataAsset, deviceId); // needChange + } + return snapshot != nullptr; + }); + if (exist) { + return res; } auto block = std::make_shared>>(WAIT_TIME, std::tuple{ true, true }); @@ -1088,17 +1247,17 @@ ObjectStoreManager::UriToSnapshot ObjectStoreManager::GetSnapShots(const std::st storeKey, [](const std::string& key) -> auto { return std::make_shared>>(); }); - return bindSnapshots_[storeKey]; + return bindSnapshots_.Find(storeKey).second; } void ObjectStoreManager::DeleteSnapshot(const std::string& bundleName, const std::string& sessionId) { auto snapshotKey = bundleName + SEPERATOR + sessionId; - if (!snapshots_.Contains(snapshotKey)) { + auto snapshot = snapshots_.Find(snapshotKey).second; + if (snapshot == nullptr) { ZLOGD("Not find snapshot, don't need delete"); return; } - auto snapshot = snapshots_[snapshotKey]; bindSnapshots_.ForEach([snapshot](auto& key, auto& value) { for (auto pos = value->begin(); pos != value->end();) { if (pos->second == snapshot) { diff --git a/datamgr_service/services/distributeddataservice/service/object/object_manager.h b/datamgr_service/services/distributeddataservice/service/object/object_manager.h index 8ff416a5761ab90a4c8ed53a70b26fe944ac2d2a..e927912387a4edeba01b472d4841207b5eae8455 100644 --- a/datamgr_service/services/distributeddataservice/service/object/object_manager.h +++ b/datamgr_service/services/distributeddataservice/service/object/object_manager.h @@ -28,6 +28,7 @@ #include "object_data_listener.h" #include "object_snapshot.h" #include "object_types.h" +#include "serializable/serializable.h" #include "types.h" #include "value_proxy.h" namespace OHOS { @@ -67,6 +68,7 @@ public: enum RestoreStatus : int32_t { NONE = 0, DATA_READY, + DATA_NOTIFIED, ASSETS_READY, ALL_READY, STATUS_BUTT @@ -95,7 +97,8 @@ public: void UnregisterRemoteCallback(const std::string &bundleName, pid_t pid, uint32_t tokenId, const std::string &sessionId = ""); void NotifyChange(std::map> &changedData); - void NotifyAssetsReady(const std::string& objectKey, const std::string& srcNetworkId = ""); + void NotifyAssetsReady(const std::string& objectKey, const std::string& bundleName, + const std::string& srcNetworkId = ""); void NotifyAssetsStart(const std::string& objectKey, const std::string& srcNetworkId = ""); void CloseAfterMinute(); int32_t Open(); @@ -132,6 +135,19 @@ private: return false; } }; + struct SaveInfo : DistributedData::Serializable { + std::string bundleName; + std::string sessionId; + std::string sourceDeviceId; + std::string targetDeviceId; + std::string timestamp; + SaveInfo() = default; + SaveInfo(const std::string &bundleName, const std::string &sessionId, const std::string &sourceDeviceId, + const std::string &targetDeviceId, const std::string ×tamp); + bool Marshal(json &node) const override; + bool Unmarshal(const json &node) override; + std::string ToPropertyPrefix(); + }; DistributedDB::KvStoreNbDelegate *OpenObjectKvStore(); void FlushClosedStore(); void Close(); @@ -144,7 +160,6 @@ private: const std::string &appId, const std::string &sessionId, std::map> &results); void SyncCompleted(const std::map &results, uint64_t sequenceId); std::vector SplitEntryKey(const std::string &key); - std::string GetPropertyName(const std::string &key); void ProcessOldEntry(const std::string &appId); void ProcessSyncCallback(const std::map &results, const std::string &appId, const std::string &sessionId, const std::string &deviceId); @@ -153,6 +168,7 @@ private: void DoNotify(uint32_t tokenId, const CallbackInfo& value, const std::map>>& data, bool allReady); void DoNotifyAssetsReady(uint32_t tokenId, const CallbackInfo& value, const std::string& objectKey, bool allReady); + void DoNotifyWaitAssetTimeout(const std::string &objectKey); std::map> GetAssetsFromStore( const std::map>& changedData); static bool IsAssetKey(const std::string& key); @@ -160,10 +176,19 @@ private: const std::string& assetPrefix); Assets GetAssetsFromDBRecords(const std::map>& result); bool RegisterAssetsLister(); - void NotifyDataChanged(std::map>>& data); + void ComputeStatus(const std::string& objectKey, const SaveInfo& saveInfo, + const std::map>>& data); + void NotifyDataChanged(const std::map>>& data, + const SaveInfo& saveInfo); int32_t PushAssets(int32_t userId, const std::string &appId, const std::string &sessionId, const std::map> &data, const std::string &deviceId); - int32_t WaitAssets(const std::string& objectKey); + int32_t WaitAssets(const std::string& objectKey, const SaveInfo& saveInfo, + const std::map>>& data); + void PullAssets(const std::map>>& data, + const SaveInfo& saveInfo); + std::map>> GetObjectData( + const std::map>& changedData, SaveInfo& saveInfo, bool& hasAsset); + inline std::string GetPropertyPrefix(const std::string &appId, const std::string &sessionId) { return appId + SEPERATOR + sessionId + SEPERATOR + DmAdaper::GetInstance().GetLocalDevice().udid + SEPERATOR; diff --git a/datamgr_service/services/distributeddataservice/service/object/object_service_impl.cpp b/datamgr_service/services/distributeddataservice/service/object/object_service_impl.cpp index 4b225813216623c323c90a45f34493f878dc21fe..206dd1065d533e4a6f0dc5bc0373cc58b4fc34f6 100644 --- a/datamgr_service/services/distributeddataservice/service/object/object_service_impl.cpp +++ b/datamgr_service/services/distributeddataservice/service/object/object_service_impl.cpp @@ -63,7 +63,8 @@ int32_t ObjectServiceImpl::ObjectStoreSave(const std::string &bundleName, const sptr callback) { ZLOGI("begin."); - RADAR_REPORT(ObjectStore::SAVE, ObjectStore::SAVE_TO_STORE, ObjectStore::IDLE); + ObjectStore::RadarReporter::ReportStage(std::string(__FUNCTION__), ObjectStore::SAVE, + ObjectStore::SAVE_TO_STORE, ObjectStore::IDLE); uint32_t tokenId = IPCSkeleton::GetCallingTokenID(); int32_t status = IsBundleNameEqualTokenId(bundleName, sessionId, tokenId); if (status != OBJECT_SUCCESS) { @@ -73,8 +74,8 @@ int32_t ObjectServiceImpl::ObjectStoreSave(const std::string &bundleName, const if (status != OBJECT_SUCCESS) { ZLOGE("save fail %{public}d", status); } - RADAR_REPORT(ObjectStore::SAVE, ObjectStore::SAVE_TO_STORE, ObjectStore::RADAR_SUCCESS, ObjectStore::BIZ_STATE, - ObjectStore::FINISHED); + ObjectStore::RadarReporter::ReportStage(std::string(__FUNCTION__), ObjectStore::SAVE, + ObjectStore::SAVE_TO_STORE, ObjectStore::RADAR_SUCCESS); return status; } @@ -196,8 +197,6 @@ int32_t ObjectServiceImpl::ObjectStoreRetrieve( status = ObjectStoreManager::GetInstance()->Retrieve(bundleName, sessionId, callback, tokenId); if (status != OBJECT_SUCCESS) { ZLOGE("retrieve fail %{public}d", status); - RADAR_REPORT(ObjectStore::CREATE, ObjectStore::RESTORE, ObjectStore::RADAR_FAILED, - ObjectStore::ERROR_CODE, status, ObjectStore::BIZ_STATE, ObjectStore::FINISHED); return status; } return OBJECT_SUCCESS; @@ -251,8 +250,8 @@ int32_t ObjectServiceImpl::IsBundleNameEqualTokenId( storeInfo.storeId = sessionId; std::string appId = DistributedData::CheckerManager::GetInstance().GetAppId(storeInfo); if (appId.empty()) { - ZLOGE("object bundleName wrong, bundleName = %{public}s, uid = %{public}d, tokenId = 0x%{public}x", - bundleName.c_str(), storeInfo.uid, storeInfo.tokenId); + ZLOGE("object bundleName wrong, bundleName = %{public}s, uid = %{public}d, tokenId = %{public}s", + bundleName.c_str(), storeInfo.uid, Anonymous::Change(std::to_string(storeInfo.tokenId)).c_str()); return OBJECT_PERMISSION_DENIED; } return OBJECT_SUCCESS; @@ -308,6 +307,7 @@ int32_t ObjectServiceImpl::ResolveAutoLaunch(const std::string &identifier, Dist continue; } DistributedObject::ObjectStoreManager::GetInstance()->CloseAfterMinute(); + ZLOGI("Auto launch, close after a minute"); return OBJECT_SUCCESS; } } diff --git a/datamgr_service/services/distributeddataservice/service/rdb/rdb_cloud.cpp b/datamgr_service/services/distributeddataservice/service/rdb/rdb_cloud.cpp index 0dd0afdab46a921f1cd49e3894bce7e019b19a6e..096d3fc638ac2b81f9eadbdde288b26e16e9e1c0 100644 --- a/datamgr_service/services/distributeddataservice/service/rdb/rdb_cloud.cpp +++ b/datamgr_service/services/distributeddataservice/service/rdb/rdb_cloud.cpp @@ -42,6 +42,7 @@ DBStatus RdbCloud::BatchInsert( VBuckets temp = records; auto error = cloudDB_->BatchInsert(tableName, std::move(records), extends); PostEvent(temp, skipAssets, extends, DistributedData::AssetEvent::UPLOAD_FINISHED); + ConvertErrorField(extends); extend = ValueProxy::Convert(std::move(extends)); return ConvertStatus(static_cast(error)); } @@ -57,6 +58,7 @@ DBStatus RdbCloud::BatchUpdate( VBuckets temp = records; auto error = cloudDB_->BatchUpdate(tableName, std::move(records), extends); PostEvent(temp, skipAssets, extends, DistributedData::AssetEvent::UPLOAD_FINISHED); + ConvertErrorField(extends); extend = ValueProxy::Convert(std::move(extends)); return ConvertStatus(static_cast(error)); } @@ -65,6 +67,7 @@ DBStatus RdbCloud::BatchDelete(const std::string &tableName, std::vectorBatchDelete(tableName, extends); + ConvertErrorField(extends); extend = ValueProxy::Convert(std::move(extends)); return ConvertStatus(static_cast(error)); } @@ -115,15 +118,13 @@ DistributedData::GeneralError RdbCloud::PreSharing(const std::string& tableName, std::pair RdbCloud::Lock() { - auto error = cloudDB_->Lock(); - return std::make_pair( // int64_t <-> uint32_t, s <-> ms - ConvertStatus(static_cast(error)), cloudDB_->AliveTime() * TO_MS); + auto result = InnerLock(FLAG::SYSTEM_ABILITY); + return { ConvertStatus(result.first), result.second }; } DBStatus RdbCloud::UnLock() { - auto error = cloudDB_->Unlock(); - return ConvertStatus(static_cast(error)); + return ConvertStatus(InnerUnLock(FLAG::SYSTEM_ABILITY)); } DBStatus RdbCloud::HeartBeat() @@ -138,6 +139,34 @@ DBStatus RdbCloud::Close() return ConvertStatus(static_cast(error)); } +std::pair RdbCloud::InnerLock(FLAG flag) +{ + std::lock_guard lock(mutex_); + flag_ |= flag; + // int64_t <-> uint32_t, s <-> ms + return std::make_pair(static_cast(cloudDB_->Lock()), cloudDB_->AliveTime() * TO_MS); +} + +GeneralError RdbCloud::InnerUnLock(FLAG flag) +{ + std::lock_guard lock(mutex_); + flag_ &= ~flag; + if (flag_ == 0) { + return static_cast(cloudDB_->Unlock()); + } + return GeneralError::E_OK; +} + +std::pair RdbCloud::LockCloudDB(FLAG flag) +{ + return InnerLock(flag); +} + +GeneralError RdbCloud::UnLockCloudDB(FLAG flag) +{ + return InnerUnLock(flag); +} + std::pair RdbCloud::GetEmptyCursor(const std::string &tableName) { auto [error, cursor] = cloudDB_->GetEmptyCursor(tableName); @@ -157,8 +186,18 @@ DBStatus RdbCloud::ConvertStatus(DistributedData::GeneralError error) return DBStatus::CLOUD_FULL_RECORDS; case GeneralError::E_NO_SPACE_FOR_ASSET: return DBStatus::CLOUD_ASSET_SPACE_INSUFFICIENT; + case GeneralError::E_VERSION_CONFLICT: + return DBStatus::CLOUD_VERSION_CONFLICT; case GeneralError::E_RECORD_EXIST_CONFLICT: return DBStatus::CLOUD_RECORD_EXIST_CONFLICT; + case GeneralError::E_RECORD_NOT_FOUND: + return DBStatus::CLOUD_RECORD_NOT_FOUND; + case GeneralError::E_RECORD_ALREADY_EXISTED: + return DBStatus::CLOUD_RECORD_ALREADY_EXISTED; + case GeneralError::E_FILE_NOT_EXIST: + return DBStatus::LOCAL_ASSET_NOT_FOUND; + case GeneralError::E_TIME_OUT: + return DBStatus::TIME_OUT; default: ZLOGI("error:0x%{public}x", error); break; @@ -286,4 +325,24 @@ void RdbCloud::PostEventAsset(DistributedData::Asset& asset, DataBucket& extend, it->second->Uploaded(asset); } } -} // namespace OHOS::DistributedRdb + +uint8_t RdbCloud::GetLockFlag() const +{ + return flag_; +} + +void RdbCloud::ConvertErrorField(DistributedData::VBuckets& extends) +{ + for (auto& extend : extends) { + auto errorField = extend.find(SchemaMeta::ERROR_FIELD); + if (errorField == extend.end()) { + continue; + } + auto errCode = Traits::get_if(&(errorField->second)); + if (errCode == nullptr) { + continue; + } + errorField->second = ConvertStatus(static_cast(*errCode)); + } +} +} // namespace OHOS::DistributedRdb \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/rdb/rdb_cloud.h b/datamgr_service/services/distributeddataservice/service/rdb/rdb_cloud.h index be8b11793242e1aed296fb1ed4f900e2a1dbf008..0478110cb0a2cfacfe8d3cbf0b6c4bd291c45735 100644 --- a/datamgr_service/services/distributeddataservice/service/rdb/rdb_cloud.h +++ b/datamgr_service/services/distributeddataservice/service/rdb/rdb_cloud.h @@ -15,6 +15,9 @@ #ifndef OHOS_DISTRIBUTED_DATA_DATAMGR_SERVICE_RDB_CLOUD_H #define OHOS_DISTRIBUTED_DATA_DATAMGR_SERVICE_RDB_CLOUD_H + +#include + #include "cloud/cloud_db.h" #include "cloud/cloud_store_types.h" #include "cloud/icloud_db.h" @@ -24,11 +27,16 @@ namespace OHOS::DistributedRdb { class RdbCloud : public DistributedDB::ICloudDb { public: + enum FLAG : uint8_t { + SYSTEM_ABILITY = 1, + APPLICATION + }; using DBStatus = DistributedDB::DBStatus; using DBVBucket = DistributedDB::VBucket; using DBQueryNodes = std::vector; using DataBucket = DistributedData::VBucket; using BindAssets = DistributedData::BindAssets; + using GeneralError = DistributedData::GeneralError; explicit RdbCloud(std::shared_ptr cloudDB, BindAssets* bindAssets); virtual ~RdbCloud() = default; @@ -45,6 +53,9 @@ public: DBStatus Close() override; std::pair GetEmptyCursor(const std::string &tableName) override; static DBStatus ConvertStatus(DistributedData::GeneralError error); + uint8_t GetLockFlag() const; + std::pair LockCloudDB(FLAG flag); + GeneralError UnLockCloudDB(FLAG flag); private: static constexpr const char *TYPE_FIELD = "#_type"; @@ -52,9 +63,12 @@ private: using QueryNodes = std::vector; static std::pair ConvertQuery(DBVBucket& extend); static QueryNodes ConvertQuery(DBQueryNodes&& nodes); + static void ConvertErrorField(DistributedData::VBuckets& extends); static constexpr int32_t TO_MS = 1000; // s > ms std::shared_ptr cloudDB_; BindAssets* snapshots_; + uint8_t flag_ = 0; + std::mutex mutex_; void PostEvent(DistributedData::VBuckets& records, std::set& skipAssets, DistributedData::VBuckets& extend, DistributedData::AssetEvent eventId); @@ -62,6 +76,8 @@ private: DistributedData::AssetEvent eventId); void PostEventAsset(DistributedData::Asset& asset, DataBucket& extend, std::set& skipAssets, DistributedData::AssetEvent eventId); + std::pair InnerLock(FLAG flag); + GeneralError InnerUnLock(FLAG flag); }; } // namespace OHOS::DistributedRdb #endif // OHOS_DISTRIBUTED_DATA_DATAMGR_SERVICE_RDB_CLOUD_H diff --git a/datamgr_service/services/distributeddataservice/service/rdb/rdb_cloud_data_translate.cpp b/datamgr_service/services/distributeddataservice/service/rdb/rdb_cloud_data_translate.cpp index 05d7d580f12c5d4e2e6c4c581a3d3670746b110c..833474bd410f5f8f0d8cb55bf1e5b33447f22b8e 100644 --- a/datamgr_service/services/distributeddataservice/service/rdb/rdb_cloud_data_translate.cpp +++ b/datamgr_service/services/distributeddataservice/service/rdb/rdb_cloud_data_translate.cpp @@ -138,7 +138,7 @@ size_t RdbCloudDataTranslate::ParserRawData(const uint8_t *data, size_t length, break; } used += dataLen; - assets.push_back(ValueProxy::Convert(asset)); + assets.push_back(std::move(asset)); count++; } return used; diff --git a/datamgr_service/services/distributeddataservice/service/rdb/rdb_general_store.cpp b/datamgr_service/services/distributeddataservice/service/rdb/rdb_general_store.cpp index cc1bfb6ea814a88c70e65be14ea078a6c8fa8be5..b5be9c581efb4be38ac9c5ef0a9ef9c6081f7ed2 100644 --- a/datamgr_service/services/distributeddataservice/service/rdb/rdb_general_store.cpp +++ b/datamgr_service/services/distributeddataservice/service/rdb/rdb_general_store.cpp @@ -20,6 +20,7 @@ #include #include "cache_cursor.h" +#include "changeevent/remote_change_event.h" #include "cloud/asset_loader.h" #include "cloud/cloud_db.h" #include "cloud/cloud_store_types.h" @@ -57,11 +58,13 @@ using DmAdapter = OHOS::DistributedData::DeviceManagerAdapter; constexpr const char *INSERT = "INSERT INTO "; constexpr const char *REPLACE = "REPLACE INTO "; constexpr const char *VALUES = " VALUES "; +constexpr const char *LOGOUT_DELETE_FLAG = "DELETE#ALL_CLOUDDATA"; constexpr const LockAction LOCK_ACTION = static_cast(static_cast(LockAction::INSERT) | static_cast(LockAction::UPDATE) | static_cast(LockAction::DELETE) | static_cast(LockAction::DOWNLOAD)); constexpr uint32_t CLOUD_SYNC_FLAG = 1; constexpr uint32_t SEARCHABLE_FLAG = 2; +constexpr uint32_t LOCK_TIMEOUT = 3600; // second static DBSchema GetDBSchema(const Database &database) { @@ -84,9 +87,11 @@ static DBSchema GetDBSchema(const Database &database) return schema; } -RdbGeneralStore::RdbGeneralStore(const StoreMetaData &meta) : manager_(meta.appId, meta.user, meta.instanceId) +RdbGeneralStore::RdbGeneralStore(const StoreMetaData &meta) + : manager_(meta.appId, meta.user, meta.instanceId), tasks_(std::make_shared>()) { observer_.storeId_ = meta.storeId; + observer_.meta_ = meta; RelationalStoreDelegate::Option option; option.observer = &observer_; if (meta.isEncrypt) { @@ -106,11 +111,13 @@ RdbGeneralStore::RdbGeneralStore(const StoreMetaData &meta) : manager_(meta.appI break; } manager_.CloseStore(delegate_); + delegate_ = nullptr; } } else { auto ret = manager_.OpenStore(meta.dataDir, meta.storeId, option, delegate_); if (ret != DBStatus::OK || delegate_ == nullptr) { manager_.CloseStore(delegate_); + delegate_ = nullptr; } } @@ -142,6 +149,9 @@ RdbGeneralStore::~RdbGeneralStore() bindInfo_.db_ = nullptr; rdbCloud_ = nullptr; rdbLoader_ = nullptr; + RemoveTasks(); + tasks_ = nullptr; + executor_ = nullptr; } int32_t RdbGeneralStore::BindSnapshots(std::shared_ptr>> bindAssets) @@ -177,8 +187,11 @@ int32_t RdbGeneralStore::Bind(Database &database, const std::map(BindEvent::BIND_SNAPSHOT, std::move(eventInfo)); EventCenter::GetInstance().PostEvent(std::move(evt)); bindInfo_ = std::move(bindInfo); - rdbCloud_ = std::make_shared(bindInfo_.db_, &snapshots_); - rdbLoader_ = std::make_shared(bindInfo_.loader_, &snapshots_); + { + std::unique_lock lock(rdbCloudMutex_); + rdbCloud_ = std::make_shared(bindInfo_.db_, &snapshots_); + rdbLoader_ = std::make_shared(bindInfo_.loader_, &snapshots_); + } DistributedDB::CloudSyncConfig dbConfig; dbConfig.maxUploadCount = config.maxNumber; @@ -204,28 +217,37 @@ bool RdbGeneralStore::IsBound() return isBound_; } -int32_t RdbGeneralStore::Close() +int32_t RdbGeneralStore::Close(bool isForce) { - std::unique_lock lock(rwMutex_); - if (delegate_ == nullptr) { - return 0; - } - int32_t count = delegate_->GetCloudSyncTaskCount(); - if (count > 0) { - return GeneralError::E_BUSY; - } - auto status = manager_.CloseStore(delegate_); - if (status != DBStatus::OK) { - return status; + { + std::unique_lock lock(rwMutex_, std::chrono::seconds(isForce ? LOCK_TIMEOUT : 0)); + if (!lock) { + return GeneralError::E_BUSY; + } + + if (delegate_ == nullptr) { + return GeneralError::E_OK; + } + if (!isForce && delegate_->GetCloudSyncTaskCount() > 0) { + return GeneralError::E_BUSY; + } + auto status = manager_.CloseStore(delegate_); + if (status != DBStatus::OK) { + return status; + } + delegate_ = nullptr; } - delegate_ = nullptr; + RemoveTasks(); bindInfo_.loader_ = nullptr; if (bindInfo_.db_ != nullptr) { bindInfo_.db_->Close(); } bindInfo_.db_ = nullptr; - rdbCloud_ = nullptr; - rdbLoader_ = nullptr; + { + std::unique_lock lock(rdbCloudMutex_); + rdbCloud_ = nullptr; + rdbLoader_ = nullptr; + } return GeneralError::E_OK; } @@ -414,40 +436,40 @@ int32_t RdbGeneralStore::Delete(const std::string &table, const std::string &sql return 0; } -std::shared_ptr RdbGeneralStore::Query(__attribute__((unused))const std::string &table, +std::pair> RdbGeneralStore::Query(__attribute__((unused))const std::string &table, const std::string &sql, Values &&args) { std::shared_lock lock(rwMutex_); if (delegate_ == nullptr) { ZLOGE("Database already closed! database:%{public}s", Anonymous::Change(storeInfo_.storeName).c_str()); - return nullptr; + return { GeneralError::E_ALREADY_CLOSED, nullptr }; } - std::vector records = QuerySql(sql, std::move(args)); - return std::make_shared(std::move(records)); + auto [errCode, records] = QuerySql(sql, std::move(args)); + return { errCode, std::make_shared(std::move(records)) }; } -std::shared_ptr RdbGeneralStore::Query(const std::string &table, GenQuery &query) +std::pair> RdbGeneralStore::Query(const std::string &table, GenQuery &query) { RdbQuery *rdbQuery = nullptr; auto ret = query.QueryInterface(rdbQuery); if (ret != GeneralError::E_OK || rdbQuery == nullptr) { ZLOGE("not RdbQuery!"); - return nullptr; + return { GeneralError::E_INVALID_ARGS, nullptr }; } std::shared_lock lock(rwMutex_); if (delegate_ == nullptr) { ZLOGE("Database already closed! database:%{public}s, table:%{public}s", Anonymous::Change(storeInfo_.storeName).c_str(), Anonymous::Change(table).c_str()); - return nullptr; + return { GeneralError::E_ALREADY_CLOSED, nullptr }; } if (rdbQuery->IsRemoteQuery()) { if (rdbQuery->GetDevices().size() != 1) { ZLOGE("RemoteQuery: devices size error! size:%{public}zu", rdbQuery->GetDevices().size()); - return nullptr; + return { GeneralError::E_ERROR, nullptr }; } - return RemoteQuery(*rdbQuery->GetDevices().begin(), rdbQuery->GetRemoteCondition()); + return { GeneralError::E_OK, RemoteQuery(*rdbQuery->GetDevices().begin(), rdbQuery->GetRemoteCondition()) }; } - return nullptr; + return { GeneralError::E_ERROR, nullptr }; } int32_t RdbGeneralStore::MergeMigratedData(const std::string &tableName, VBuckets &&values) @@ -470,7 +492,7 @@ int32_t RdbGeneralStore::Sync(const Devices &devices, GenQuery &query, DetailAsy bool isPriority = false; auto ret = query.QueryInterface(rdbQuery); if (ret != GeneralError::E_OK || rdbQuery == nullptr) { - dbQuery.FromTable(query.GetTables()); + dbQuery.FromTable(GetIntersection(query.GetTables(), GetTables())); } else { dbQuery = rdbQuery->GetQuery(); isPriority = rdbQuery->IsPriority(); @@ -485,30 +507,47 @@ int32_t RdbGeneralStore::Sync(const Devices &devices, GenQuery &query, DetailAsy return GeneralError::E_ALREADY_CLOSED; } auto highMode = GetHighMode(static_cast(syncParam.mode)); - auto status = (syncMode < NEARBY_END) - ? delegate_->Sync(devices, dbMode, dbQuery, GetDBBriefCB(std::move(async), syncMode), syncParam.wait != 0) - : (syncMode > NEARBY_END && syncMode < CLOUD_END) - ? delegate_->Sync({ devices, dbMode, dbQuery, syncParam.wait, (isPriority || highMode == MANUAL_SYNC_MODE), - syncParam.isCompensation, {}, highMode == AUTO_SYNC_MODE, LOCK_ACTION }, - GetDBProcessCB(std::move(async), syncMode, highMode)) - : DistributedDB::INVALID_ARGS; - OnSyncStart(storeInfo_, syncNotifyFlag_, syncMode, status); - return status; + SyncId syncId = ++syncTaskId_; + auto dbStatus = DistributedDB::INVALID_ARGS; + if (syncMode < NEARBY_END) { + dbStatus = delegate_->Sync(devices, dbMode, dbQuery, GetDBBriefCB(std::move(async)), syncParam.wait != 0); + } else if (syncMode > NEARBY_END && syncMode < CLOUD_END) { + auto callback = GetDBProcessCB(std::move(async), syncMode, syncId, highMode); + if (executor_ != nullptr && tasks_ != nullptr) { + auto id = executor_->Schedule(GetFinishTask(syncId), std::chrono::minutes(INTERVAL), + std::chrono::minutes(INTERVAL)); + tasks_->Insert(syncId, { id, callback }); + } + dbStatus = + delegate_->Sync({ devices, dbMode, dbQuery, syncParam.wait, (isPriority || highMode == MANUAL_SYNC_MODE), + syncParam.isCompensation, {}, highMode == AUTO_SYNC_MODE, LOCK_ACTION }, + tasks_ != nullptr ? GetCB(syncId) : callback, syncId); + if (dbStatus == DBStatus::OK || tasks_ == nullptr) { + return ConvertStatus(dbStatus); + } + tasks_->ComputeIfPresent(syncId, [executor = executor_](SyncId syncId, const FinishTask &task) { + if (executor != nullptr) { + executor->Remove(task.taskId); + } + return false; + }); + } + return ConvertStatus(dbStatus); } -std::shared_ptr RdbGeneralStore::PreSharing(GenQuery &query) +std::pair> RdbGeneralStore::PreSharing(GenQuery &query) { RdbQuery *rdbQuery = nullptr; auto ret = query.QueryInterface(rdbQuery); if (ret != GeneralError::E_OK || rdbQuery == nullptr) { ZLOGE("not RdbQuery!"); - return nullptr; + return { GeneralError::E_INVALID_ARGS, nullptr }; } auto tables = rdbQuery->GetTables(); auto statement = rdbQuery->GetStatement(); if (statement.empty() || tables.empty()) { ZLOGE("statement size:%{public}zu, tables size:%{public}zu", statement.size(), tables.size()); - return nullptr; + return { GeneralError::E_INVALID_ARGS, nullptr }; } std::string sql = BuildSql(*tables.begin(), statement, rdbQuery->GetColumns()); VBuckets values; @@ -516,23 +555,25 @@ std::shared_ptr RdbGeneralStore::PreSharing(GenQuery &query) std::shared_lock lock(rwMutex_); if (delegate_ == nullptr) { ZLOGE("Database already closed! database:%{public}s", Anonymous::Change(storeInfo_.storeName).c_str()); - return nullptr; + return { GeneralError::E_ALREADY_CLOSED, nullptr }; } - values = QuerySql(sql, rdbQuery->GetBindArgs()); + auto [errCode, ret] = QuerySql(sql, rdbQuery->GetBindArgs()); + values = std::move(ret); } - if (rdbCloud_ == nullptr || values.empty()) { - ZLOGW("rdbCloud is %{public}s, values size:%{public}zu", rdbCloud_ == nullptr ? "nullptr" : "not nullptr", + auto rdbCloud = GetRdbCloud(); + if (rdbCloud == nullptr || values.empty()) { + ZLOGW("rdbCloud is %{public}s, values size:%{public}zu", rdbCloud == nullptr ? "nullptr" : "not nullptr", values.size()); - return nullptr; + return { GeneralError::E_CLOUD_DISABLED, nullptr }; } VBuckets extends = ExtractExtend(values); - rdbCloud_->PreSharing(*tables.begin(), extends); + rdbCloud->PreSharing(*tables.begin(), extends); for (auto value = values.begin(), extend = extends.begin(); value != values.end() && extend != extends.end(); ++value, ++extend) { value->insert_or_assign(DistributedRdb::Field::SHARING_RESOURCE_FIELD, (*extend)[SchemaMeta::SHARING_RESOURCE]); value->erase(CLOUD_GID); } - return std::make_shared(std::move(values)); + return { GeneralError::E_OK, std::make_shared(std::move(values)) }; } VBuckets RdbGeneralStore::ExtractExtend(VBuckets &values) const @@ -636,21 +677,18 @@ int32_t RdbGeneralStore::Unwatch(int32_t origin, Watcher &watcher) return GeneralError::E_OK; } -RdbGeneralStore::DBBriefCB RdbGeneralStore::GetDBBriefCB(DetailAsync async, uint32_t syncMode) +RdbGeneralStore::DBBriefCB RdbGeneralStore::GetDBBriefCB(DetailAsync async) { if (!async) { - return [storeInfo = storeInfo_, flag = syncNotifyFlag_, syncMode](auto &) { - RdbGeneralStore::OnSyncFinish(storeInfo, flag, syncMode); - }; + return [](auto &) {}; } - return [async = std::move(async), storeInfo = storeInfo_, flag = syncNotifyFlag_, syncMode]( + return [async = std::move(async)]( const std::map> &result) { DistributedData::GenDetails details; for (auto &[key, tables] : result) { auto &value = details[key]; value.progress = FINISHED; value.code = GeneralError::E_OK; - RdbGeneralStore::OnSyncFinish(storeInfo, flag, syncMode); for (auto &table : tables) { if (table.status != DBStatus::OK) { value.code = GeneralError::E_ERROR; @@ -661,35 +699,47 @@ RdbGeneralStore::DBBriefCB RdbGeneralStore::GetDBBriefCB(DetailAsync async, uint }; } -RdbGeneralStore::DBProcessCB RdbGeneralStore::GetDBProcessCB(DetailAsync async, uint32_t syncMode, uint32_t highMode) +RdbGeneralStore::DBProcessCB RdbGeneralStore::GetDBProcessCB(DetailAsync async, uint32_t syncMode, SyncId syncId, + uint32_t highMode) { - if (!async && (highMode == MANUAL_SYNC_MODE || !async_)) { - return [storeInfo = storeInfo_, flag = syncNotifyFlag_, syncMode](auto &) { - RdbGeneralStore::OnSyncFinish(storeInfo, flag, syncMode); - }; - } - - return [async, autoAsync = async_, highMode, storeInfo = storeInfo_, flag = syncNotifyFlag_, syncMode]( - const std::map &processes) { + std::shared_lock lock(asyncMutex_); + return [async, autoAsync = async_, highMode, storeInfo = storeInfo_, flag = syncNotifyFlag_, syncMode, syncId, + rdbCloud = GetRdbCloud()](const std::map &processes) { DistributedData::GenDetails details; for (auto &[id, process] : processes) { + bool isDownload = false; auto &detail = details[id]; detail.progress = process.process; detail.code = ConvertStatus(process.errCode); detail.dbCode = DB_ERR_OFFSET + process.errCode; - if (process.process == FINISHED) { - RdbGeneralStore::OnSyncFinish(storeInfo, flag, syncMode); - } + uint32_t totalCount = 0; for (auto [key, value] : process.tableProcess) { auto &table = detail.details[key]; table.upload.total = value.upLoadInfo.total; table.upload.success = value.upLoadInfo.successCount; table.upload.failed = value.upLoadInfo.failCount; table.upload.untreated = table.upload.total - table.upload.success - table.upload.failed; + totalCount += table.upload.total; + isDownload = table.download.total > 0; table.download.total = value.downLoadInfo.total; table.download.success = value.downLoadInfo.successCount; table.download.failed = value.downLoadInfo.failCount; table.download.untreated = table.download.total - table.download.success - table.download.failed; + detail.changeCount = (process.process == FINISHED) + ? value.downLoadInfo.insertCount + value.downLoadInfo.updateCount + + value.downLoadInfo.deleteCount + : 0; + totalCount += table.download.total; + } + if (process.process == FINISHED) { + RdbGeneralStore::OnSyncFinish(storeInfo, flag, syncMode, syncId); + } else { + RdbGeneralStore::OnSyncStart(storeInfo, flag, syncMode, syncId, totalCount); + } + + if (isDownload && (process.process == FINISHED || process.process == PROCESSING) && rdbCloud != nullptr && + (rdbCloud->GetLockFlag() & RdbCloud::FLAG::APPLICATION)) { + rdbCloud->LockCloudDB(RdbCloud::FLAG::APPLICATION); } } if (async) { @@ -827,17 +877,19 @@ bool RdbGeneralStore::IsValid() int32_t RdbGeneralStore::RegisterDetailProgressObserver(GeneralStore::DetailAsync async) { + std::unique_lock lock(asyncMutex_); async_ = std::move(async); return GenErr::E_OK; } int32_t RdbGeneralStore::UnregisterDetailProgressObserver() { + std::unique_lock lock(asyncMutex_); async_ = nullptr; return GenErr::E_OK; } -VBuckets RdbGeneralStore::QuerySql(const std::string &sql, Values &&args) +std::pair RdbGeneralStore::QuerySql(const std::string &sql, Values &&args) { std::vector changedData; std::vector bindArgs = ValueProxy::Convert(std::move(args)); @@ -845,9 +897,9 @@ VBuckets RdbGeneralStore::QuerySql(const std::string &sql, Values &&args) if (status != DBStatus::OK) { ZLOGE("Failed! ret:%{public}d, sql:%{public}s, data size:%{public}zu", status, Anonymous::Change(sql).c_str(), changedData.size()); - return {}; + return { GenErr::E_ERROR, {} }; } - return ValueProxy::Convert(std::move(changedData)); + return { GenErr::E_OK, ValueProxy::Convert(std::move(changedData)) }; } std::vector RdbGeneralStore::GetWaterVersion(const std::string &deviceId) @@ -855,28 +907,77 @@ std::vector RdbGeneralStore::GetWaterVersion(const std::string &dev return {}; } -void RdbGeneralStore::OnSyncStart(const StoreInfo &storeInfo, uint32_t flag, uint32_t syncMode, int status) +void RdbGeneralStore::OnSyncStart(const StoreInfo &storeInfo, uint32_t flag, uint32_t syncMode, uint32_t traceId, + uint32_t syncCount) { uint32_t requiredFlag = (CLOUD_SYNC_FLAG | SEARCHABLE_FLAG); if (requiredFlag != (requiredFlag & flag)) { return; } - if (status != GeneralError::E_OK) { - return; - } StoreInfo info = storeInfo; - auto evt = std::make_unique(std::move(info), syncMode, DataSyncEvent::DataSyncStatus::START); + auto evt = std::make_unique(std::move(info), syncMode, DataSyncEvent::DataSyncStatus::START, + traceId, syncCount); EventCenter::GetInstance().PostEvent(std::move(evt)); } -void RdbGeneralStore::OnSyncFinish(const StoreInfo &storeInfo, uint32_t flag, uint32_t syncMode) +void RdbGeneralStore::OnSyncFinish(const StoreInfo &storeInfo, uint32_t flag, uint32_t syncMode, uint32_t traceId) { uint32_t requiredFlag = (CLOUD_SYNC_FLAG | SEARCHABLE_FLAG); if (requiredFlag != (requiredFlag & flag)) { return; } StoreInfo info = storeInfo; - auto evt = std::make_unique(std::move(info), syncMode, DataSyncEvent::DataSyncStatus::FINISH); + auto evt = std::make_unique(std::move(info), syncMode, DataSyncEvent::DataSyncStatus::FINISH, + traceId); + EventCenter::GetInstance().PostEvent(std::move(evt)); +} + +std::set RdbGeneralStore::GetTables() +{ + std::set tables; + std::shared_lock lock(rwMutex_); + if (delegate_ == nullptr) { + ZLOGE("Database already closed! database:%{public}s", Anonymous::Change(storeInfo_.storeName).c_str()); + return tables; + } + auto [errCode, res] = QuerySql(QUERY_TABLES_SQL, {}); + if (errCode != GenErr::E_OK) { + return tables; + } + for (auto &table : res) { + auto it = table.find("name"); + if (it == table.end() || TYPE_INDEX != it->second.index()) { + ZLOGW("error res! database:%{public}s", Anonymous::Change(storeInfo_.storeName).c_str()); + continue; + } + tables.emplace(std::move(*std::get_if(&(it->second)))); + } + return tables; +} + +std::vector RdbGeneralStore::GetIntersection(std::vector &&syncTables, + const std::set &localTables) +{ + std::vector res; + for (auto &it : syncTables) { + if (localTables.count(it)) { + res.push_back(std::move(it)); + } + } + return res; +} + +void RdbGeneralStore::ObserverProxy::PostDataChange(const StoreMetaData &meta, + const std::vector &tables, ChangeType type) +{ + RemoteChangeEvent::DataInfo info; + info.userId = meta.user; + info.storeId = meta.storeId; + info.deviceId = meta.deviceId; + info.bundleName = meta.bundleName; + info.tables = tables; + info.changeType = type; + auto evt = std::make_unique(RemoteChangeEvent::DATA_CHANGE, std::move(info)); EventCenter::GetInstance().PostEvent(std::move(evt)); } @@ -917,17 +1018,143 @@ void RdbGeneralStore::ObserverProxy::OnChange(DBOrigin origin, const std::string genOrigin.store = storeId_; Watcher::PRIFields fields; Watcher::ChangeInfo changeInfo; + bool notifyFlag = false; for (uint32_t i = 0; i < DistributedDB::OP_BUTT; ++i) { auto &info = changeInfo[data.tableName][i]; for (auto &priData : data.primaryData[i]) { Watcher::PRIValue value; Convert(std::move(*(priData.begin())), value); + if (notifyFlag || origin != DBOrigin::ORIGIN_CLOUD || i != DistributedDB::OP_DELETE) { + info.push_back(std::move(value)); + continue; + } + auto deleteKey = std::get_if(&value); + if (deleteKey != nullptr && (*deleteKey == LOGOUT_DELETE_FLAG)) { + // notify to start app + notifyFlag = true; + } info.push_back(std::move(value)); } } + if (notifyFlag) { + ZLOGI("post data change for cleaning cloud data"); + PostDataChange(meta_, {}, CLOUD_DATA_CLEAN); + } if (!data.field.empty()) { fields[std::move(data.tableName)] = std::move(*(data.field.begin())); } watcher_->OnChange(genOrigin, fields, std::move(changeInfo)); } + +std::pair RdbGeneralStore::LockCloudDB() +{ + auto rdbCloud = GetRdbCloud(); + if (rdbCloud == nullptr) { + return { GeneralError::E_ERROR, 0 }; + } + return rdbCloud->LockCloudDB(RdbCloud::FLAG::APPLICATION); +} + +int32_t RdbGeneralStore::UnLockCloudDB() +{ + auto rdbCloud = GetRdbCloud(); + if (rdbCloud == nullptr) { + return GeneralError::E_ERROR; + } + return rdbCloud->UnLockCloudDB(RdbCloud::FLAG::APPLICATION); +} + +std::shared_ptr RdbGeneralStore::GetRdbCloud() const +{ + std::shared_lock lock(rdbCloudMutex_); + return rdbCloud_; +} + +bool RdbGeneralStore::IsFinished(SyncId syncId) const +{ + std::shared_lock lock(rwMutex_); + if (delegate_ == nullptr) { + ZLOGE("database already closed! database:%{public}s", Anonymous::Change(storeInfo_.storeName).c_str()); + return true; + } + return delegate_->GetCloudTaskStatus(syncId).process == DistributedDB::FINISHED; +} + +Executor::Task RdbGeneralStore::GetFinishTask(SyncId syncId) +{ + return [this, syncId]() { + if (!IsFinished(syncId)) { + return; + } + DBProcessCB cb; + ZLOGW("database:%{public}s syncId:%{public}" PRIu64 " miss finished. ", + Anonymous::Change(storeInfo_.storeName).c_str(), syncId); + tasks_->ComputeIfPresent(syncId, [&cb, executor = executor_](SyncId syncId, const FinishTask &task) { + cb = task.cb; + if (executor != nullptr) { + executor->Remove(task.taskId); + } + return false; + }); + if (cb != nullptr) { + std::map result; + result.insert({ "", { DistributedDB::FINISHED, DBStatus::DB_ERROR } }); + cb(result); + } + }; +} + +void RdbGeneralStore::SetExecutor(std::shared_ptr executor) +{ + if (executor_ == nullptr) { + executor_ = executor; + } +} + +void RdbGeneralStore::RemoveTasks() +{ + if (tasks_ == nullptr) { + return; + } + std::list cbs; + tasks_->ForEach([&cbs, executor = executor_, store = storeInfo_.storeName](SyncId syncId, const FinishTask &task) { + cbs.push_back(std::move(task.cb)); + ZLOGW("database:%{public}s syncId:%{public}" PRIu64 " miss finished. ", + Anonymous::Change(store).c_str(), syncId); + if (executor != nullptr) { + executor->Remove(task.taskId); + } + return false; + }); + tasks_->Clear(); + std::map result; + result.insert({ "", { DistributedDB::FINISHED, DBStatus::DB_ERROR } }); + for (auto &cb : cbs) { + if (cb != nullptr) { + cb(result); + } + } +} + +RdbGeneralStore::DBProcessCB RdbGeneralStore::GetCB(SyncId syncId) +{ + return [task = tasks_, executor = executor_, syncId](const std::map &progress) { + if (task == nullptr) { + return; + } + DBProcessCB cb; + task->ComputeIfPresent(syncId, [&cb, &progress, executor](SyncId syncId, const FinishTask &finishTask) { + cb = finishTask.cb; + bool isFinished = !progress.empty() && progress.begin()->second.process == DistributedDB::FINISHED; + if (isFinished && executor != nullptr) { + executor->Remove(finishTask.taskId); + } + return !isFinished; + }); + if (cb != nullptr) { + cb(progress); + } + return; + }; +} } // namespace OHOS::DistributedRdb \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/rdb/rdb_general_store.h b/datamgr_service/services/distributeddataservice/service/rdb/rdb_general_store.h index 567177c0c78f5776e9b56f61b7eaf2ecb5fee1f5..f096b6c31f111f87865242a6aef944a101c3d102 100644 --- a/datamgr_service/services/distributeddataservice/service/rdb/rdb_general_store.h +++ b/datamgr_service/services/distributeddataservice/service/rdb/rdb_general_store.h @@ -19,6 +19,7 @@ #include #include +#include "concurrent_map.h" #include "metadata/store_meta_data.h" #include "rdb_asset_loader.h" #include "rdb_cloud.h" @@ -48,8 +49,11 @@ public: explicit RdbGeneralStore(const StoreMetaData &meta); ~RdbGeneralStore(); - static void OnSyncStart(const DistributedData::StoreInfo &storeInfo, uint32_t flag, uint32_t syncMode, int status); - static void OnSyncFinish(const DistributedData::StoreInfo &storeInfo, uint32_t flag, uint32_t syncMode); + static void OnSyncStart(const DistributedData::StoreInfo &storeInfo, uint32_t flag, uint32_t syncMode, + uint32_t traceId, uint32_t syncCount); + static void OnSyncFinish(const DistributedData::StoreInfo &storeInfo, uint32_t flag, uint32_t syncMode, + uint32_t traceId); + void SetExecutor(std::shared_ptr executor) override; int32_t Bind(Database &database, const std::map &bindInfos, const CloudConfig &config) override; bool IsBound() override; @@ -64,22 +68,25 @@ public: Values &&conditions) override; int32_t Replace(const std::string &table, VBucket &&value) override; int32_t Delete(const std::string &table, const std::string &sql, Values &&args) override; - std::shared_ptr Query(const std::string &table, const std::string &sql, Values &&args) override; - std::shared_ptr Query(const std::string &table, GenQuery &query) override; + std::pair> Query(const std::string &table, const std::string &sql, + Values &&args) override; + std::pair> Query(const std::string &table, GenQuery &query) override; int32_t Sync( const Devices &devices, GenQuery &query, DetailAsync async, DistributedData::SyncParam &syncParam) override; - std::shared_ptr PreSharing(GenQuery &query) override; + std::pair> PreSharing(GenQuery &query) override; int32_t Clean(const std::vector &devices, int32_t mode, const std::string &tableName) override; int32_t Watch(int32_t origin, Watcher &watcher) override; int32_t Unwatch(int32_t origin, Watcher &watcher) override; int32_t RegisterDetailProgressObserver(DetailAsync async) override; int32_t UnregisterDetailProgressObserver() override; - int32_t Close() override; + int32_t Close(bool isForce = false) override; int32_t AddRef() override; int32_t Release() override; int32_t BindSnapshots(std::shared_ptr>> bindAssets) override; int32_t MergeMigratedData(const std::string &tableName, VBuckets&& values) override; std::vector GetWaterVersion(const std::string &deviceId) override; + std::pair LockCloudDB() override; + int32_t UnLockCloudDB() override; private: RdbGeneralStore(const RdbGeneralStore& rdbGeneralStore); @@ -89,10 +96,18 @@ private: using SyncProcess = DistributedDB::SyncProcess; using DBBriefCB = DistributedDB::SyncStatusCallback; using DBProcessCB = std::function &processes)>; + using TaskId = ExecutorPool::TaskId; + using Time = std::chrono::steady_clock::time_point; + using SyncId = uint64_t; static GenErr ConvertStatus(DistributedDB::DBStatus status); + // GetIntersection and return results in the order of collecter1 + static std::vector GetIntersection(std::vector &&syncTables, + const std::set &localTables); static constexpr inline uint64_t REMOTE_QUERY_TIME_OUT = 30 * 1000; + static constexpr int64_t INTERVAL = 1; static constexpr const char* CLOUD_GID = "cloud_gid"; static constexpr const char* DATE_KEY = "data_key"; + static constexpr const char* QUERY_TABLES_SQL = "select name from sqlite_master where type = 'table';"; static constexpr uint32_t ITER_V0 = 10000; static constexpr uint32_t ITER_V1 = 5000; static constexpr uint32_t ITERS[] = {ITER_V0, ITER_V1}; @@ -110,20 +125,33 @@ private: return watcher_ != nullptr; } private: + enum ChangeType { + CLOUD_DATA_CHANGE = 0, + CLOUD_DATA_CLEAN + }; + void PostDataChange(const StoreMetaData &meta, const std::vector &tables, ChangeType type); friend RdbGeneralStore; Watcher *watcher_ = nullptr; std::string storeId_; + StoreMetaData meta_; }; - DBBriefCB GetDBBriefCB(DetailAsync async, uint32_t syncMode); - DBProcessCB GetDBProcessCB(DetailAsync async, uint32_t syncMode, uint32_t highMode = AUTO_SYNC_MODE); + DBBriefCB GetDBBriefCB(DetailAsync async); + DBProcessCB GetCB(SyncId syncId); + DBProcessCB GetDBProcessCB(DetailAsync async, uint32_t syncMode, SyncId syncId, + uint32_t highMode = AUTO_SYNC_MODE); + Executor::Task GetFinishTask(SyncId syncId); std::shared_ptr RemoteQuery(const std::string &device, const DistributedDB::RemoteCondition &remoteCondition); std::string BuildSql(const std::string& table, const std::string& statement, const std::vector& columns) const; - VBuckets QuerySql(const std::string& sql, Values &&args); + std::pair QuerySql(const std::string& sql, Values &&args); + std::set GetTables(); VBuckets ExtractExtend(VBuckets& values) const; size_t SqlConcatenate(VBucket &value, std::string &strColumnSql, std::string &strRowValueSql); bool IsPrintLog(DistributedDB::DBStatus status); + std::shared_ptr GetRdbCloud() const; + bool IsFinished(uint64_t syncId) const; + void RemoveTasks(); ObserverProxy observer_; RdbManager manager_; @@ -135,7 +163,7 @@ private: std::atomic isBound_ = false; std::mutex mutex_; int32_t ref_ = 1; - mutable std::shared_mutex rwMutex_; + mutable std::shared_timed_mutex rwMutex_; BindAssets snapshots_; DistributedData::StoreInfo storeInfo_; @@ -144,6 +172,15 @@ private: static constexpr uint32_t PRINT_ERROR_CNT = 150; uint32_t lastErrCnt_ = 0; uint32_t syncNotifyFlag_ = 0; + std::atomic syncTaskId_ = 0; + std::shared_mutex asyncMutex_ {}; + mutable std::shared_mutex rdbCloudMutex_; + struct FinishTask { + TaskId taskId = Executor::INVALID_TASK_ID; + DBProcessCB cb = nullptr; + }; + std::shared_ptr executor_ = nullptr; + std::shared_ptr> tasks_; }; } // namespace OHOS::DistributedRdb #endif // OHOS_DISTRIBUTED_DATA_DATAMGR_SERVICE_RDB_GENERAL_STORE_H diff --git a/datamgr_service/services/distributeddataservice/service/rdb/rdb_notifier_proxy.cpp b/datamgr_service/services/distributeddataservice/service/rdb/rdb_notifier_proxy.cpp index eba9b47b84d8d8836bb16aa067564b7b8a4d046a..ceb200a3777656b880950fe6c4925d6974b44caa 100644 --- a/datamgr_service/services/distributeddataservice/service/rdb/rdb_notifier_proxy.cpp +++ b/datamgr_service/services/distributeddataservice/service/rdb/rdb_notifier_proxy.cpp @@ -62,7 +62,7 @@ int32_t RdbNotifierProxy::OnChange(const Origin &origin, const PrimaryFields &pr } MessageParcel reply; - MessageOption option; + MessageOption option(MessageOption::TF_ASYNC); if (Remote()->SendRequest( static_cast(NotifierIFCode::RDB_NOTIFIER_CMD_DATA_CHANGE), data, reply, option) != 0) { ZLOGE("storeName:%{public}s, send request failed", DistributedData::Anonymous::Change(origin.store).c_str()); diff --git a/datamgr_service/services/distributeddataservice/service/rdb/rdb_service_impl.cpp b/datamgr_service/services/distributeddataservice/service/rdb/rdb_service_impl.cpp index 4b3a16c70a430ba4c938b149561820e968f6904e..e8730147ea1214b4311e540e26223afe30bfd779 100644 --- a/datamgr_service/services/distributeddataservice/service/rdb/rdb_service_impl.cpp +++ b/datamgr_service/services/distributeddataservice/service/rdb/rdb_service_impl.cpp @@ -21,8 +21,10 @@ #include "changeevent/remote_change_event.h" #include "cloud/change_event.h" #include "cloud/cloud_share_event.h" +#include "cloud/cloud_lock_event.h" #include "cloud/make_query_event.h" #include "commonevent/data_change_event.h" +#include "commonevent/set_searchable_event.h" #include "communicator/device_manager_adapter.h" #include "crypto_manager.h" #include "directory/directory_manager.h" @@ -47,6 +49,8 @@ #include "rdb_general_store.h" #include "rdb_result_set_impl.h" #include "xcollie.h" +#include "device_matrix.h" +#include "metadata/capability_meta_data.h" using OHOS::DistributedKv::AccountDelegate; using OHOS::DistributedData::CheckerManager; using OHOS::DistributedData::MetaDataManager; @@ -116,6 +120,7 @@ RdbServiceImpl::RdbServiceImpl() store->RegisterDetailProgressObserver(GetCallbacks(meta.tokenId, storeInfo.storeName)); }; EventCenter::GetInstance().Subscribe(CloudEvent::CLOUD_SYNC, process); + EventCenter::GetInstance().Subscribe(CloudEvent::CLEAN_DATA, process); EventCenter::GetInstance().Subscribe(CloudEvent::MAKE_QUERY, [](const Event& event) { auto& evt = static_cast(event); @@ -170,7 +175,7 @@ int32_t RdbServiceImpl::ResolveAutoLaunch(const std::string &identifier, Distrib if (entry.isEncrypt) { param.option.iterateTimes = ITERATE_TIMES; param.option.cipher = DistributedDB::CipherType::AES_256_GCM; - GetPassword(entry, param.option.passwd); + GetDBPassword(entry, param.option.passwd); } AutoCache::GetInstance().GetStore(entry, GetWatchers(entry.tokenId, entry.storeId)); return true; @@ -182,22 +187,28 @@ int32_t RdbServiceImpl::ResolveAutoLaunch(const std::string &identifier, Distrib int32_t RdbServiceImpl::OnAppExit(pid_t uid, pid_t pid, uint32_t tokenId, const std::string &bundleName) { ZLOGI("client dead, tokenId:%{public}d, pid:%{public}d ", tokenId, pid); - syncAgents_.EraseIf([pid](auto& key, SyncAgent& agent) { - if (agent.pid_ != pid) { - return false; + bool destroyed = false; + syncAgents_.ComputeIfPresent(tokenId, [pid, &destroyed](auto &key, SyncAgents &agents) { + auto it = agents.find(pid); + if (it != agents.end()) { + it->second.SetNotifier(nullptr); + agents.erase(it); } - if (agent.watcher_ != nullptr) { - agent.watcher_->SetNotifier(nullptr); + if (!agents.empty()) { + return true; } - auto stores = AutoCache::GetInstance().GetStoresIfPresent(key); + destroyed = true; + return false; + }); + if (destroyed) { + auto stores = AutoCache::GetInstance().GetStoresIfPresent(tokenId); for (auto store : stores) { if (store != nullptr) { store->UnregisterDetailProgressObserver(); } } - return true; - }); - AutoCache::GetInstance().Enable(tokenId); + AutoCache::GetInstance().Enable(tokenId); + } return E_OK; } @@ -241,15 +252,15 @@ int32_t RdbServiceImpl::InitNotifier(const RdbSyncerParam ¶m, const sptr(notifier); pid_t pid = IPCSkeleton::GetCallingPid(); uint32_t tokenId = IPCSkeleton::GetCallingTokenID(); - syncAgents_.Compute(tokenId, [¶m, notifierProxy, pid](auto, SyncAgent &agent) { - if (pid != agent.pid_) { - agent.ReInit(pid, param.bundleName_); + syncAgents_.Compute(tokenId, [bundleName = param.bundleName_, notifierProxy, pid](auto, SyncAgents &agents) { + auto [it, success] = agents.try_emplace(pid, SyncAgent(bundleName)); + if (it == agents.end()) { + return true; } - agent.SetNotifier(notifierProxy); + it->second.SetNotifier(notifierProxy); return true; }); ZLOGI("success tokenId:%{public}x, pid=%{public}d", tokenId, pid); - return RDB_OK; } @@ -307,12 +318,19 @@ int32_t RdbServiceImpl::SetDistributedTables(const RdbSyncerParam ¶m, const return store->SetDistributedTables(tables, type, relationships); } -void RdbServiceImpl::OnAsyncComplete(uint32_t tokenId, uint32_t seqNum, Details &&result) +void RdbServiceImpl::OnAsyncComplete(uint32_t tokenId, pid_t pid, uint32_t seqNum, Details &&result) { - ZLOGI("tokenId=%{public}x seqnum=%{public}u", tokenId, seqNum); - auto [success, agent] = syncAgents_.Find(tokenId); - if (success && agent.notifier_ != nullptr) { - agent.notifier_->OnComplete(seqNum, std::move(result)); + ZLOGI("tokenId=%{public}x, pid=%{public}d, seqnum=%{public}u", tokenId, pid, seqNum); + sptr notifier = nullptr; + syncAgents_.ComputeIfPresent(tokenId, [¬ifier, pid](auto, SyncAgents &syncAgents) { + auto it = syncAgents.find(pid); + if (it != syncAgents.end()) { + notifier = it->second.notifier_; + } + return true; + }); + if (notifier != nullptr) { + notifier->OnComplete(seqNum, std::move(result)); } } @@ -333,28 +351,37 @@ std::string RdbServiceImpl::TransferStringToHex(const std::string &origStr) AutoCache::Watchers RdbServiceImpl::GetWatchers(uint32_t tokenId, const std::string &storeName) { - auto [success, agent] = syncAgents_.Find(tokenId); - if (agent.watcher_ == nullptr) { - return {}; - } - return { agent.watcher_ }; + AutoCache::Watchers watchers; + syncAgents_.ComputeIfPresent(tokenId, [&watchers](auto, SyncAgents &syncAgents) { + std::for_each(syncAgents.begin(), syncAgents.end(), [&watchers](const auto &item) { + if (item.second.watcher_ != nullptr) { + watchers.insert(item.second.watcher_); + } + }); + return true; + }); + return watchers; } -RdbServiceImpl::DetailAsync RdbServiceImpl::GetCallbacks(uint32_t tokenId, const std::string& storeName) +RdbServiceImpl::DetailAsync RdbServiceImpl::GetCallbacks(uint32_t tokenId, const std::string &storeName) { - sptr notifier = nullptr; - syncAgents_.ComputeIfPresent(tokenId, [&storeName, ¬ifier](auto, SyncAgent& syncAgent) { - if (syncAgent.callBackStores_.count(storeName) != 0) { - notifier = syncAgent.notifier_; - } + std::list> notifiers; + syncAgents_.ComputeIfPresent(tokenId, [&storeName, ¬ifiers](auto, SyncAgents &syncAgents) { + std::for_each(syncAgents.begin(), syncAgents.end(), [&storeName, ¬ifiers](const auto &item) { + if (item.second.callBackStores_.count(storeName) != 0) { + notifiers.push_back(item.second.notifier_); + } + }); return true; }); - if (notifier == nullptr) { + if (notifiers.empty()) { return nullptr; } - return [notifier, storeName](const GenDetails& details) { - if (notifier != nullptr) { - notifier->OnComplete(storeName, HandleGenDetails(details)); + return [notifiers, storeName](const GenDetails &details) { + for (const auto ¬ifier : notifiers) { + if (notifier != nullptr) { + notifier->OnComplete(storeName, HandleGenDetails(details)); + } } }; } @@ -374,7 +401,10 @@ std::pair> RdbServiceImpl::R } RdbQuery rdbQuery; rdbQuery.MakeRemoteQuery(DmAdapter::GetInstance().ToUUID(device), sql, ValueProxy::Convert(selectionArgs)); - auto cursor = store->Query("", rdbQuery); + auto [errCode, cursor] = store->Query("", rdbQuery); + if (errCode != GeneralError::E_OK) { + return { RDB_ERROR, nullptr }; + } return { RDB_OK, std::make_shared(cursor) }; } @@ -405,33 +435,71 @@ int RdbServiceImpl::DoSync(const RdbSyncerParam ¶m, const RdbService::Option rdbQuery.MakeQuery(predicates); auto devices = rdbQuery.GetDevices().empty() ? DmAdapter::ToUUID(DmAdapter::GetInstance().GetRemoteDevices()) : DmAdapter::ToUUID(rdbQuery.GetDevices()); - if (!option.isAsync) { - SyncParam syncParam = { option.mode, 1, option.isCompensation }; - Details details = {}; - auto status = store->Sync( - devices, rdbQuery, - [&details, ¶m](const GenDetails &result) mutable { - ZLOGD("Sync complete, bundleName:%{public}s, storeName:%{public}s", param.bundleName_.c_str(), - Anonymous::Change(param.storeName_).c_str()); - details = HandleGenDetails(result); + auto pid = IPCSkeleton::GetCallingPid(); + SyncParam syncParam = { option.mode, 0, option.isCompensation }; + StoreMetaData meta = GetStoreMetaData(param); + auto tokenId = IPCSkeleton::GetCallingTokenID(); + ZLOGD("seqNum=%{public}u", option.seqNum); + auto complete = [this, rdbQuery, store, pid, syncParam, tokenId, async, seq = option.seqNum]( + const auto &results) mutable { + auto ret = ProcessResult(results); + store->Sync( + ret.first, rdbQuery, + [this, tokenId, seq, pid](const GenDetails &result) mutable { + OnAsyncComplete(tokenId, pid, seq, HandleGenDetails(result)); }, syncParam); - if (async != nullptr) { - async(std::move(details)); - } - return status; + }; + if (IsNeedMetaSync(meta, devices)) { + auto result = MetaDataManager::GetInstance().Sync(devices, complete); + return result ? GeneralError::E_OK : GeneralError::E_ERROR; } - ZLOGD("seqNum=%{public}u", option.seqNum); - auto tokenId = IPCSkeleton::GetCallingTokenID(); - SyncParam syncParam = { option.mode, 0, option.isCompensation }; return store->Sync( devices, rdbQuery, - [this, tokenId, seqNum = option.seqNum](const GenDetails &result) mutable { - OnAsyncComplete(tokenId, seqNum, HandleGenDetails(result)); + [this, tokenId, pid, seqNum = option.seqNum](const GenDetails &result) mutable { + OnAsyncComplete(tokenId, pid, seqNum, HandleGenDetails(result)); }, syncParam); } +bool RdbServiceImpl::IsNeedMetaSync(const StoreMetaData &meta, const std::vector &uuids) +{ + bool isAfterMeta = false; + for (const auto &uuid : uuids) { + auto metaData = meta; + metaData.deviceId = uuid; + CapMetaData capMeta; + auto capKey = CapMetaRow::GetKeyFor(uuid); + if (!MetaDataManager::GetInstance().LoadMeta(std::string(capKey.begin(), capKey.end()), capMeta) || + !MetaDataManager::GetInstance().LoadMeta(metaData.GetKey(), metaData)) { + isAfterMeta = true; + break; + } + auto [exist, mask] = DeviceMatrix::GetInstance().GetRemoteMask(uuid); + if ((mask & DeviceMatrix::META_STORE_MASK) == DeviceMatrix::META_STORE_MASK) { + isAfterMeta = true; + break; + } + } + return isAfterMeta; +} + +RdbServiceImpl::SyncResult RdbServiceImpl::ProcessResult(const std::map &results) +{ + std::map dbResults; + std::vector devices; + for (const auto &[uuid, status] : results) { + dbResults.insert_or_assign(uuid, static_cast(status)); + if (static_cast(status) != DBStatus::OK) { + continue; + } + DeviceMatrix::GetInstance().OnExchanged(uuid, DeviceMatrix::META_STORE_MASK); + devices.emplace_back(uuid); + } + ZLOGD("meta sync finish, total size:%{public}zu, success size:%{public}zu", dbResults.size(), devices.size()); + return { devices, dbResults }; +} + void RdbServiceImpl::DoCompensateSync(const BindEvent& event) { auto bindInfo = event.GetBindInfo(); @@ -471,9 +539,10 @@ void RdbServiceImpl::DoCloudSync(const RdbSyncerParam ¶m, const RdbService:: query = std::make_shared(); query->MakeCloudQuery(predicates); } - GenAsync asyncCallback = [this, tokenId = storeInfo.tokenId, seqNum = option.seqNum]( + auto pid = IPCSkeleton::GetCallingPid(); + GenAsync asyncCallback = [this, tokenId = storeInfo.tokenId, seqNum = option.seqNum, pid]( const GenDetails &result) mutable { - OnAsyncComplete(tokenId, seqNum, HandleGenDetails(result)); + OnAsyncComplete(tokenId, pid, seqNum, HandleGenDetails(result)); }; GenAsync syncCallback = [async, ¶m](const GenDetails &details) { ZLOGD("Cloud Sync complete, bundleName:%{public}s, storeName:%{public}s", param.bundleName_.c_str(), @@ -484,7 +553,7 @@ void RdbServiceImpl::DoCloudSync(const RdbSyncerParam ¶m, const RdbService:: }; auto mixMode = static_cast(GeneralStore::MixMode(option.mode, option.isAutoSync ? GeneralStore::AUTO_SYNC_MODE : GeneralStore::MANUAL_SYNC_MODE)); - SyncParam syncParam = { mixMode, (option.isAsync ? 0 : static_cast(WAIT_TIME)), option.isCompensation }; + SyncParam syncParam = { mixMode, (option.isAsync ? 0 : WAIT_TIME), option.isCompensation }; auto info = ChangeEvent::EventInfo(syncParam, option.isAutoSync, query, option.isAutoSync ? nullptr : option.isAsync ? asyncCallback @@ -503,15 +572,16 @@ int32_t RdbServiceImpl::Subscribe(const RdbSyncerParam ¶m, const SubscribeOp pid_t pid = IPCSkeleton::GetCallingPid(); auto tokenId = IPCSkeleton::GetCallingTokenID(); bool isCreate = false; - syncAgents_.Compute(tokenId, [pid, ¶m, &isCreate](auto &key, SyncAgent &agent) { - if (pid != agent.pid_) { - agent.ReInit(pid, param.bundleName_); + syncAgents_.Compute(tokenId, [pid, ¶m, &isCreate](auto &key, SyncAgents &agents) { + auto [it, _] = agents.try_emplace(pid, param.bundleName_); + if (it == agents.end()) { + return !agents.empty(); } - if (agent.watcher_ == nullptr) { + if (it->second.watcher_ == nullptr) { isCreate = true; - agent.SetWatcher(std::make_shared()); + it->second.SetWatcher(std::make_shared()); } - agent.count_++; + it->second.count_++; return true; }); if (isCreate) { @@ -530,13 +600,16 @@ int32_t RdbServiceImpl::UnSubscribe(const RdbSyncerParam ¶m, const Subscribe } bool destroyed = false; auto tokenId = IPCSkeleton::GetCallingTokenID(); - syncAgents_.ComputeIfPresent(tokenId, [&destroyed](auto &key, SyncAgent &agent) { - if (agent.count_ > 0) { - agent.count_--; + auto pid = IPCSkeleton::GetCallingPid(); + syncAgents_.ComputeIfPresent(tokenId, [pid, &destroyed](auto, SyncAgents &agents) { + auto it = agents.find(pid); + if (it == agents.end()) { + return !agents.empty(); } - if (agent.count_ == 0) { + it->second.count_--; + if (it->second.count_ <= 0) { destroyed = true; - agent.SetWatcher(nullptr); + it->second.SetWatcher(nullptr); } return true; }); @@ -553,25 +626,17 @@ int32_t RdbServiceImpl::RegisterAutoSyncCallback(const RdbSyncerParam& param, pid_t pid = IPCSkeleton::GetCallingPid(); auto tokenId = IPCSkeleton::GetCallingTokenID(); auto storeName = RemoveSuffix(param.storeName_); - bool isCreate = false; - syncAgents_.Compute(tokenId, [pid, ¶m, &storeName, &isCreate](auto, SyncAgent& agent) { - if (pid != agent.pid_) { - agent.ReInit(pid, param.bundleName_); + syncAgents_.Compute(tokenId, [pid, ¶m, &storeName](auto, SyncAgents &agents) { + auto [it, success] = agents.try_emplace(pid, param.bundleName_); + if (it == agents.end()) { + return !agents.empty(); } - auto it = agent.callBackStores_.find(storeName); - if (it == agent.callBackStores_.end()) { - agent.callBackStores_.insert(std::make_pair(storeName, 0)); - isCreate = true; + if (success) { + it->second.callBackStores_.insert(std::make_pair(storeName, 0)); } - agent.callBackStores_[storeName]++; + it->second.callBackStores_[storeName]++; return true; }); - if (isCreate) { - auto stores = AutoCache::GetInstance().GetStoresIfPresent(tokenId, storeName); - if (!stores.empty() && *stores.begin() != nullptr) { - (*stores.begin())->RegisterDetailProgressObserver(GetCallbacks(tokenId, storeName)); - } - } return RDB_OK; } @@ -579,26 +644,23 @@ int32_t RdbServiceImpl::UnregisterAutoSyncCallback(const RdbSyncerParam& param, std::shared_ptr observer) { auto tokenId = IPCSkeleton::GetCallingTokenID(); + auto pid = IPCSkeleton::GetCallingPid(); auto storeName = RemoveSuffix(param.storeName_); - bool destroyed = false; - syncAgents_.ComputeIfPresent(tokenId, [&storeName, &destroyed](auto, SyncAgent& agent) { - auto it = agent.callBackStores_.find(storeName); - if (it == agent.callBackStores_.end()) { - return true; + syncAgents_.ComputeIfPresent(tokenId, [pid, &storeName](auto, SyncAgents &agents) { + auto agent = agents.find(pid); + if (agent == agents.end()) { + return !agents.empty(); + } + auto it = agent->second.callBackStores_.find(storeName); + if (it == agent->second.callBackStores_.end()) { + return !agents.empty(); } it->second--; if (it->second <= 0) { - agent.callBackStores_.erase(it); - destroyed = true; + agent->second.callBackStores_.erase(it); } - return true; + return !agents.empty(); }); - if (destroyed) { - auto stores = AutoCache::GetInstance().GetStoresIfPresent(tokenId, storeName); - if (!stores.empty() && *stores.begin() != nullptr) { - (*stores.begin())->UnregisterDetailProgressObserver(); - } - } return RDB_OK; } @@ -688,6 +750,7 @@ void RdbServiceImpl::SetReturnParam(StoreMetaData &metadata, RdbSyncerParam &par param.isEncrypt_ = metadata.isEncrypt; param.isAutoClean_ = !metadata.isManualClean; param.isSearchable_ = metadata.isSearchable; + param.haMode_ = metadata.haMode; } int32_t RdbServiceImpl::AfterOpen(const RdbSyncerParam ¶m) @@ -782,6 +845,7 @@ StoreMetaData RdbServiceImpl::GetStoreMetaData(const RdbSyncerParam ¶m) metaData.isEncrypt = param.isEncrypt_; metaData.isManualClean = !param.isAutoClean_; metaData.isSearchable = param.isSearchable_; + metaData.haMode = param.haMode_; return metaData; } @@ -828,7 +892,7 @@ Details RdbServiceImpl::HandleGenDetails(const GenDetails &details) return dbDetails; } -bool RdbServiceImpl::GetPassword(const StoreMetaData &metaData, DistributedDB::CipherPassword &password) +bool RdbServiceImpl::GetDBPassword(const StoreMetaData &metaData, DistributedDB::CipherPassword &password) { if (!metaData.isEncrypt) { return true; @@ -881,18 +945,6 @@ int32_t RdbServiceImpl::OnBind(const BindInfo &bindInfo) return 0; } -void RdbServiceImpl::SyncAgent::ReInit(pid_t pid, const std::string &bundleName) -{ - pid_ = pid; - count_ = 0; - callBackStores_.clear(); - bundleName_ = bundleName; - notifier_ = nullptr; - if (watcher_ != nullptr) { - watcher_->SetNotifier(nullptr); - } -} - void RdbServiceImpl::SyncAgent::SetNotifier(sptr notifier) { notifier_ = notifier; @@ -911,6 +963,14 @@ void RdbServiceImpl::SyncAgent::SetWatcher(std::shared_ptr watcher) } } +RdbServiceImpl::SyncAgent::SyncAgent(const std::string &bundleName) : bundleName_(bundleName) +{ + notifier_ = nullptr; + watcher_ = nullptr; + count_ = 0; + callBackStores_.clear(); +} + int32_t RdbServiceImpl::RdbStatic::CloseStore(const std::string &bundleName, int32_t user, int32_t index, int32_t tokenId) const { @@ -990,7 +1050,8 @@ RdbServiceImpl::~RdbServiceImpl() DumpManager::GetInstance().RemoveHandler("FEATURE_INFO", uintptr_t(this)); } -int32_t RdbServiceImpl::NotifyDataChange(const RdbSyncerParam ¶m, const RdbChangedData &rdbChangedData) +int32_t RdbServiceImpl::NotifyDataChange(const RdbSyncerParam ¶m, const RdbChangedData &rdbChangedData, + const RdbNotifyConfig &rdbNotifyConfig) { XCollie xcollie(__FUNCTION__, HiviewDFX::XCOLLIE_FLAG_LOG | HiviewDFX::XCOLLIE_FLAG_RECOVERY); if (!CheckAccess(param.bundleName_, param.storeName_)) { @@ -1008,13 +1069,67 @@ int32_t RdbServiceImpl::NotifyDataChange(const RdbSyncerParam ¶m, const RdbC storeInfo.deviceId = DmAdapter::GetInstance().GetLocalDevice().uuid; DataChangeEvent::EventInfo eventInfo; + eventInfo.isFull = rdbNotifyConfig.isFull_; for (const auto& [key, value] : rdbChangedData.tableData) { DataChangeEvent::TableChangeProperties tableChangeProperties = {value.isTrackedDataChange}; eventInfo.tableProperties.insert_or_assign(key, std::move(tableChangeProperties)); } - auto evt = std::make_unique(std::move(storeInfo), std::move(eventInfo)); + bool postImmediately = false; + heartbeatTaskIds_.Compute(param.storeName_, [this, &postImmediately, &rdbNotifyConfig, &storeInfo, &eventInfo] + (const std::string &key, ExecutorPool::TaskId &value) { + if (rdbNotifyConfig.delay_ == 0) { + if (value != ExecutorPool::INVALID_TASK_ID && executors_ != nullptr) { + executors_->Remove(value); + } + postImmediately = true; + return false; + } + + if (executors_ != nullptr) { + auto task = [storeInfoInner = storeInfo, eventInfoInner = eventInfo]() { + auto evt = std::make_unique(std::move(storeInfoInner), std::move(eventInfoInner)); + EventCenter::GetInstance().PostEvent(std::move(evt)); + }; + if (value == ExecutorPool::INVALID_TASK_ID) { + value = executors_->Schedule(std::chrono::milliseconds(rdbNotifyConfig.delay_), task); + } else { + value = executors_->Reset(value, std::chrono::milliseconds(rdbNotifyConfig.delay_)); + } + } + return true; + }); + + if (postImmediately) { + auto evt = std::make_unique(std::move(storeInfo), std::move(eventInfo)); + EventCenter::GetInstance().PostEvent(std::move(evt)); + } + + return RDB_OK; +} + +int32_t RdbServiceImpl::SetSearchable(const RdbSyncerParam& param, bool isSearchable) +{ + XCollie xcollie(__FUNCTION__, HiviewDFX::XCOLLIE_FLAG_LOG | HiviewDFX::XCOLLIE_FLAG_RECOVERY); + if (!CheckAccess(param.bundleName_, param.storeName_)) { + ZLOGE("bundleName:%{public}s, storeName:%{public}s. Permission error", param.bundleName_.c_str(), + Anonymous::Change(param.storeName_).c_str()); + return RDB_ERROR; + } + StoreInfo storeInfo; + storeInfo.tokenId = IPCSkeleton::GetCallingTokenID(); + storeInfo.bundleName = param.bundleName_; + storeInfo.storeName = RemoveSuffix(param.storeName_); + auto [instanceId, user]= GetInstIndexAndUser(storeInfo.tokenId, param.bundleName_); + storeInfo.instanceId = instanceId; + storeInfo.user = user; + storeInfo.deviceId = DmAdapter::GetInstance().GetLocalDevice().uuid; + + SetSearchableEvent::EventInfo eventInfo; + eventInfo.isSearchable = isSearchable; + auto evt = std::make_unique(std::move(storeInfo), std::move(eventInfo)); EventCenter::GetInstance().PostEvent(std::move(evt)); + return RDB_OK; } @@ -1023,13 +1138,91 @@ int32_t RdbServiceImpl::Disable(const RdbSyncerParam& param) auto tokenId = IPCSkeleton::GetCallingTokenID(); auto storeId = RemoveSuffix(param.storeName_); AutoCache::GetInstance().Disable(tokenId, storeId); - return E_OK; + return RDB_OK; } + int32_t RdbServiceImpl::Enable(const RdbSyncerParam& param) { auto tokenId = IPCSkeleton::GetCallingTokenID(); auto storeId = RemoveSuffix(param.storeName_); AutoCache::GetInstance().Enable(tokenId, storeId); - return E_OK; + return RDB_OK; +} + +int32_t RdbServiceImpl::GetPassword(const RdbSyncerParam ¶m, std::vector &password) +{ + if (!CheckAccess(param.bundleName_, param.storeName_)) { + ZLOGE("bundleName:%{public}s, storeName:%{public}s. Permission error", param.bundleName_.c_str(), + Anonymous::Change(param.storeName_).c_str()); + return RDB_ERROR; + } + auto meta = GetStoreMetaData(param); + SecretKeyMetaData secretKey; + if (!MetaDataManager::GetInstance().LoadMeta(meta.GetSecretKey(), secretKey, true)) { + ZLOGE("bundleName:%{public}s, storeName:%{public}s. no meta", param.bundleName_.c_str(), + Anonymous::Change(param.storeName_).c_str()); + return RDB_NO_META; + } + + if (!CryptoManager::GetInstance().Decrypt(secretKey.sKey, password)) { + ZLOGE("bundleName:%{public}s, storeName:%{public}s. decrypt err", param.bundleName_.c_str(), + Anonymous::Change(param.storeName_).c_str()); + return RDB_ERROR; + } + return RDB_OK; +} + +StoreInfo RdbServiceImpl::GetStoreInfo(const RdbSyncerParam ¶m) +{ + StoreInfo storeInfo; + storeInfo.bundleName = param.bundleName_; + storeInfo.tokenId = IPCSkeleton::GetCallingTokenID(); + storeInfo.user = AccountDelegate::GetInstance()->GetUserByToken(storeInfo.tokenId); + storeInfo.storeName = RemoveSuffix(param.storeName_); + return storeInfo; +} + +std::pair RdbServiceImpl::LockCloudContainer(const RdbSyncerParam ¶m) +{ + std::pair result { RDB_ERROR, 0 }; + if (!CheckAccess(param.bundleName_, param.storeName_)) { + ZLOGE("bundleName:%{public}s, storeName:%{public}s. Permission error", param.bundleName_.c_str(), + Anonymous::Change(param.storeName_).c_str()); + return result; + } + ZLOGI("start to lock cloud db: bundleName:%{public}s, storeName:%{public}s", param.bundleName_.c_str(), + Anonymous::Change(param.storeName_).c_str()); + + auto storeInfo = GetStoreInfo(param); + + CloudLockEvent::Callback callback = [&result](int32_t status, uint32_t expiredTime) { + result.first = status; + result.second = expiredTime; + }; + auto evt = std::make_unique(CloudEvent::LOCK_CLOUD_CONTAINER, std::move(storeInfo), callback); + EventCenter::GetInstance().PostEvent(std::move(evt)); + return result; +} + +int32_t RdbServiceImpl::UnlockCloudContainer(const RdbSyncerParam ¶m) +{ + int32_t result = RDB_ERROR; + if (!CheckAccess(param.bundleName_, param.storeName_)) { + ZLOGE("bundleName:%{public}s, storeName:%{public}s. Permission error", param.bundleName_.c_str(), + Anonymous::Change(param.storeName_).c_str()); + return result; + } + ZLOGI("start to unlock cloud db: bundleName:%{public}s, storeName:%{public}s", param.bundleName_.c_str(), + Anonymous::Change(param.storeName_).c_str()); + + auto storeInfo = GetStoreInfo(param); + + CloudLockEvent::Callback callback = [&result](int32_t status, uint32_t expiredTime) { + (void)expiredTime; + result = status; + }; + auto evt = std::make_unique(CloudEvent::UNLOCK_CLOUD_CONTAINER, std::move(storeInfo), callback); + EventCenter::GetInstance().PostEvent(std::move(evt)); + return result; } } // namespace OHOS::DistributedRdb \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/rdb/rdb_service_impl.h b/datamgr_service/services/distributeddataservice/service/rdb/rdb_service_impl.h index 344bf3bf4a0efcc9936abcfea90ea981586b1b3b..c110a4d779dfc6a1061f03d63b7cf980f7bbc58c 100644 --- a/datamgr_service/services/distributeddataservice/service/rdb/rdb_service_impl.h +++ b/datamgr_service/services/distributeddataservice/service/rdb/rdb_service_impl.h @@ -85,7 +85,9 @@ public: int32_t OnInitialize() override; - int32_t NotifyDataChange(const RdbSyncerParam ¶m, const RdbChangedData &rdbChangedData) override; + int32_t NotifyDataChange(const RdbSyncerParam ¶m, const RdbChangedData &rdbChangedData, + const RdbNotifyConfig &rdbNotifyConfig) override; + int32_t SetSearchable(const RdbSyncerParam& param, bool isSearchable) override; int32_t Disable(const RdbSyncerParam& param) override; int32_t Enable(const RdbSyncerParam& param) override; @@ -93,20 +95,29 @@ public: int32_t AfterOpen(const RdbSyncerParam ¶m) override; + int32_t GetPassword(const RdbSyncerParam ¶m, std::vector &password) override; + + std::pair LockCloudContainer(const RdbSyncerParam ¶m) override; + + int32_t UnlockCloudContainer(const RdbSyncerParam ¶m) override; + private: using Watchers = DistributedData::AutoCache::Watchers; using StaticActs = DistributedData::StaticActs; + using DBStatus = DistributedDB::DBStatus; + using SyncResult = std::pair, std::map>; struct SyncAgent { - pid_t pid_ = 0; + SyncAgent() = default; + explicit SyncAgent(const std::string &bundleName); int32_t count_ = 0; std::map callBackStores_; std::string bundleName_; sptr notifier_ = nullptr; std::shared_ptr watcher_ = nullptr; - void ReInit(pid_t pid, const std::string &bundleName); void SetNotifier(sptr notifier); void SetWatcher(std::shared_ptr watcher); }; + using SyncAgents = std::map; class RdbStatic : public StaticActs { public: @@ -154,7 +165,7 @@ private: std::shared_ptr GetStore(const RdbSyncerParam& param); - void OnAsyncComplete(uint32_t tokenId, uint32_t seqNum, Details &&result); + void OnAsyncComplete(uint32_t tokenId, pid_t pid, uint32_t seqNum, Details &&result); StoreMetaData GetStoreMetaData(const RdbSyncerParam ¶m); @@ -173,15 +184,22 @@ private: static std::pair GetInstIndexAndUser(uint32_t tokenId, const std::string &bundleName); - static bool GetPassword(const StoreMetaData &metaData, DistributedDB::CipherPassword &password); + static bool GetDBPassword(const StoreMetaData &metaData, DistributedDB::CipherPassword &password); void GetCloudSchema(const RdbSyncerParam ¶m); void SetReturnParam(StoreMetaData &metadata, RdbSyncerParam ¶m); + bool IsNeedMetaSync(const StoreMetaData &meta, const std::vector &uuids); + + SyncResult ProcessResult(const std::map &results); + + StoreInfo GetStoreInfo(const RdbSyncerParam ¶m); + static Factory factory_; - ConcurrentMap syncAgents_; + ConcurrentMap syncAgents_; std::shared_ptr executors_; + ConcurrentMap heartbeatTaskIds_; }; } // namespace OHOS::DistributedRdb #endif \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/rdb/rdb_service_stub.cpp b/datamgr_service/services/distributeddataservice/service/rdb/rdb_service_stub.cpp index 49274e8787d5d6ba899c4373ea893fabe3052321..a6736520dce8f3197ee0f2ae526ad28bf6da93b2 100644 --- a/datamgr_service/services/distributeddataservice/service/rdb/rdb_service_stub.cpp +++ b/datamgr_service/services/distributeddataservice/service/rdb/rdb_service_stub.cpp @@ -284,13 +284,32 @@ int32_t RdbServiceStub::OnRemoteNotifyDataChange(MessageParcel &data, MessagePar { RdbSyncerParam param; RdbChangedData rdbChangedData; - if (!ITypesUtil::Unmarshal(data, param, rdbChangedData)) { + RdbNotifyConfig rdbNotifyConfig; + if (!ITypesUtil::Unmarshal(data, param, rdbChangedData, rdbNotifyConfig)) { ZLOGE("Unmarshal bundleName_:%{public}s storeName_:%{public}s ", param.bundleName_.c_str(), Anonymous::Change(param.storeName_).c_str()); return IPC_STUB_INVALID_DATA_ERR; } - auto status = NotifyDataChange(param, rdbChangedData); + auto status = NotifyDataChange(param, rdbChangedData, rdbNotifyConfig); + if (!ITypesUtil::Marshal(reply, status)) { + ZLOGE("Marshal status:0x%{public}x", status); + return IPC_STUB_WRITE_PARCEL_ERR; + } + return RDB_OK; +} + +int32_t RdbServiceStub::OnRemoteSetSearchable(MessageParcel &data, MessageParcel &reply) +{ + RdbSyncerParam param; + bool isSearchable = true; + if (!ITypesUtil::Unmarshal(data, param, isSearchable)) { + ZLOGE("Unmarshal bundleName_:%{public}s storeName_:%{public}s ", param.bundleName_.c_str(), + Anonymous::Change(param.storeName_).c_str()); + return IPC_STUB_INVALID_DATA_ERR; + } + + auto status = SetSearchable(param, isSearchable); if (!ITypesUtil::Marshal(reply, status)) { ZLOGE("Marshal status:0x%{public}x", status); return IPC_STUB_WRITE_PARCEL_ERR; @@ -351,4 +370,53 @@ int32_t RdbServiceStub::OnEnable(MessageParcel& data, MessageParcel& reply) } return RDB_OK; } + +int32_t RdbServiceStub::OnGetPassword(MessageParcel &data, MessageParcel &reply) +{ + RdbSyncerParam param; + if (!ITypesUtil::Unmarshal(data, param)) { + ZLOGE("Unmarshal bundleName_:%{public}s storeName_:%{public}s", param.bundleName_.c_str(), + Anonymous::Change(param.storeName_).c_str()); + return IPC_STUB_INVALID_DATA_ERR; + } + + std::vector key; + auto status = GetPassword(param, key); + if (!ITypesUtil::Marshal(reply, status, key)) { + key.assign(key.size(), 0); + ZLOGE("Marshal status:0x%{public}x", status); + return IPC_STUB_WRITE_PARCEL_ERR; + } + key.assign(key.size(), 0); + return RDB_OK; +} + +int32_t RdbServiceStub::OnLockCloudContainer(MessageParcel &data, MessageParcel &reply) +{ + RdbSyncerParam param; + uint32_t expiredTime = 0; + if (!ITypesUtil::Unmarshal(data, param, expiredTime)) { + ZLOGE("Unmarshal failed"); + return IPC_STUB_INVALID_DATA_ERR; + } + + auto result = LockCloudContainer(param); + return ITypesUtil::Marshal(reply, result.first, result.second) ? RDB_OK : IPC_STUB_WRITE_PARCEL_ERR; +} + +int32_t RdbServiceStub::OnUnlockCloudContainer(MessageParcel &data, MessageParcel &reply) +{ + RdbSyncerParam param; + if (!ITypesUtil::Unmarshal(data, param)) { + ZLOGE("Unmarshal failed"); + return IPC_STUB_INVALID_DATA_ERR; + } + + auto status = UnlockCloudContainer(param); + if (!ITypesUtil::Marshal(reply, status)) { + ZLOGE("Marshal status:0x%{public}x", status); + return IPC_STUB_WRITE_PARCEL_ERR; + } + return RDB_OK; +} } // namespace OHOS::DistributedRdb diff --git a/datamgr_service/services/distributeddataservice/service/rdb/rdb_service_stub.h b/datamgr_service/services/distributeddataservice/service/rdb/rdb_service_stub.h index eef8b94d62d833c8143aa73ebe154619751be247..a8ac6b9bc9298c25c109b674ed9ff86b86113765 100644 --- a/datamgr_service/services/distributeddataservice/service/rdb/rdb_service_stub.h +++ b/datamgr_service/services/distributeddataservice/service/rdb/rdb_service_stub.h @@ -56,6 +56,8 @@ private: int32_t OnRemoteNotifyDataChange(MessageParcel& data, MessageParcel& reply); + int32_t OnRemoteSetSearchable(MessageParcel& data, MessageParcel& reply); + int32_t OnRemoteQuerySharingResource(MessageParcel& data, MessageParcel& reply); int32_t OnBeforeOpen(MessageParcel& data, MessageParcel& reply); @@ -65,6 +67,12 @@ private: int32_t OnDisable(MessageParcel& data, MessageParcel& reply); int32_t OnEnable(MessageParcel& data, MessageParcel& reply); + + int32_t OnGetPassword(MessageParcel& data, MessageParcel& reply); + + int32_t OnLockCloudContainer(MessageParcel& data, MessageParcel& reply); + + int32_t OnUnlockCloudContainer(MessageParcel& data, MessageParcel& reply); using RequestHandle = int (RdbServiceStub::*)(MessageParcel &, MessageParcel &); static constexpr RequestHandle HANDLERS[static_cast(RdbServiceCode::RDB_SERVICE_CMD_MAX)] = { @@ -85,12 +93,19 @@ private: &RdbServiceStub::OnRemoteUnregisterDetailProgressObserver, [static_cast(RdbServiceCode::RDB_SERVICE_CMD_NOTIFY_DATA_CHANGE)] = &RdbServiceStub::OnRemoteNotifyDataChange, + [static_cast(RdbServiceCode::RDB_SERVICE_CMD_SET_SEARCHABLE)] = + &RdbServiceStub::OnRemoteSetSearchable, [static_cast(RdbServiceCode::RDB_SERVICE_CMD_QUERY_SHARING_RESOURCE)] = &RdbServiceStub::OnRemoteQuerySharingResource, [static_cast(RdbServiceCode::RDB_SERVICE_CMD_DISABLE)] = &RdbServiceStub::OnDisable, [static_cast(RdbServiceCode::RDB_SERVICE_CMD_ENABLE)] = &RdbServiceStub::OnEnable, [static_cast(RdbServiceCode::RDB_SERVICE_CMD_BEFORE_OPEN)] = &RdbServiceStub::OnBeforeOpen, - [static_cast(RdbServiceCode::RDB_SERVICE_CMD_AFTER_OPEN)] = &RdbServiceStub::OnAfterOpen + [static_cast(RdbServiceCode::RDB_SERVICE_CMD_AFTER_OPEN)] = &RdbServiceStub::OnAfterOpen, + [static_cast(RdbServiceCode::RDB_SERVICE_CMD_GET_PASSWORD)] = &RdbServiceStub::OnGetPassword, + [static_cast(RdbServiceCode::RDB_SERVICE_CMD_LOCK_CLOUD_CONTAINER)] = + &RdbServiceStub::OnLockCloudContainer, + [static_cast(RdbServiceCode::RDB_SERVICE_CMD_UNLOCK_CLOUD_CONTAINER)] = + &RdbServiceStub::OnUnlockCloudContainer }; }; } // namespace OHOS::DistributedRdb diff --git a/datamgr_service/services/distributeddataservice/service/test/BUILD.gn b/datamgr_service/services/distributeddataservice/service/test/BUILD.gn index 5aac474e418fe2d977fb2ff0a0ea9b872875d216..6e351661a65a1f083e7012c1d1f25f5053cbb519 100644 --- a/datamgr_service/services/distributeddataservice/service/test/BUILD.gn +++ b/datamgr_service/services/distributeddataservice/service/test/BUILD.gn @@ -46,6 +46,8 @@ config("module_private_config") { "${data_service_path}/service/waterversion", "${dataobject_path}/interfaces/innerkits", "${dataobject_path}/frameworks/innerkitsimpl/include", + "${kv_store_distributeddb_path}/interfaces/include/", + "${kv_store_distributeddb_path}/include/", "${relational_store_path}/interfaces/inner_api/cloud_data/include", "${relational_store_path}/interfaces/inner_api/common_type/include", ] @@ -76,6 +78,7 @@ ohos_unittest("CloudDataTest") { "${data_service_path}/service/common/value_proxy.cpp", "${data_service_path}/service/common/xcollie.cpp", "${data_service_path}/service/config/src/config_factory.cpp", + "${data_service_path}/service/config/src/model/app_id_mapping_config.cpp", "${data_service_path}/service/config/src/model/backup_config.cpp", "${data_service_path}/service/config/src/model/checker_config.cpp", "${data_service_path}/service/config/src/model/cloud_config.cpp", @@ -129,6 +132,94 @@ ohos_unittest("CloudDataTest") { "mock:distributeddata_mock_static", "//third_party/googletest:gtest_main", ] + + cflags = [ + "-fno-access-control", # Ignore Private Member Access Control + ] + + cflags_cc = cflags +} + +ohos_unittest("CloudServiceImplTest") { + sanitize = { + cfi = true + cfi_cross_dso = true + debug = false + } + module_out_path = module_output_path + sources = [ + "${data_service_path}/service/backup/src/backup_manager.cpp", + "${data_service_path}/service/bootstrap/src/bootstrap.cpp", + "${data_service_path}/service/cloud/cloud_service_impl.cpp", + "${data_service_path}/service/cloud/cloud_service_stub.cpp", + "${data_service_path}/service/cloud/cloud_types_util.cpp", + "${data_service_path}/service/cloud/cloud_value_util.cpp", + "${data_service_path}/service/cloud/sync_manager.cpp", + "${data_service_path}/service/cloud/sync_strategies/network_sync_strategy.cpp", + "${data_service_path}/service/common/common_types_utils.cpp", + "${data_service_path}/service/common/value_proxy.cpp", + "${data_service_path}/service/common/xcollie.cpp", + "${data_service_path}/service/config/src/config_factory.cpp", + "${data_service_path}/service/config/src/model/app_id_mapping_config.cpp", + "${data_service_path}/service/config/src/model/backup_config.cpp", + "${data_service_path}/service/config/src/model/checker_config.cpp", + "${data_service_path}/service/config/src/model/cloud_config.cpp", + "${data_service_path}/service/config/src/model/component_config.cpp", + "${data_service_path}/service/config/src/model/directory_config.cpp", + "${data_service_path}/service/config/src/model/global_config.cpp", + "${data_service_path}/service/config/src/model/network_config.cpp", + "${data_service_path}/service/config/src/model/protocol_config.cpp", + "${data_service_path}/service/crypto/src/crypto_manager.cpp", + "${data_service_path}/service/matrix/src/device_matrix.cpp", + "${data_service_path}/service/matrix/src/matrix_event.cpp", + "${data_service_path}/service/rdb/cache_cursor.cpp", + "${data_service_path}/service/rdb/rdb_asset_loader.cpp", + "${data_service_path}/service/rdb/rdb_cloud.cpp", + "${data_service_path}/service/rdb/rdb_cloud_data_translate.cpp", + "${data_service_path}/service/rdb/rdb_cursor.cpp", + "${data_service_path}/service/rdb/rdb_general_store.cpp", + "${data_service_path}/service/rdb/rdb_notifier_proxy.cpp", + "${data_service_path}/service/rdb/rdb_query.cpp", + "${data_service_path}/service/rdb/rdb_result_set_impl.cpp", + "${data_service_path}/service/rdb/rdb_result_set_stub.cpp", + "${data_service_path}/service/rdb/rdb_service_impl.cpp", + "${data_service_path}/service/rdb/rdb_service_stub.cpp", + "${data_service_path}/service/rdb/rdb_watcher.cpp", + "${data_service_path}/service/test/mock/checker_mock.cpp", + "${data_service_path}/service/waterversion/water_version_manager.cpp", + "cloud_service_impl_test.cpp", + ] + + configs = [ ":module_private_config" ] + + external_deps = [ + "ability_base:base", + "ability_base:want", + "access_token:libaccesstoken_sdk", + "access_token:libtoken_setproc", + "access_token:libtokenid_sdk", + "c_utils:utils", + "hicollie:libhicollie", + "hilog:libhilog", + "huks:libhukssdk", + "ipc:ipc_core", + "kv_store:distributeddata_inner", + "kv_store:distributeddb", + "relational_store:native_rdb", + ] + + deps = [ + "../../adapter:distributeddata_adapter", + "../../framework:distributeddatasvcfwk", + "mock:distributeddata_mock_static", + "//third_party/googletest:gtest_main", + ] + + cflags = [ + "-fno-access-control", # Ignore Private Member Access Control + ] + + cflags_cc = cflags } ohos_unittest("CloudTest") { @@ -156,7 +247,7 @@ ohos_unittest("CloudTest") { ] } -ohos_unittest("ValueProxyTest") { +ohos_unittest("ValueProxyServiceTest") { module_out_path = module_output_path sources = [ "../common/value_proxy.cpp", @@ -170,6 +261,13 @@ ohos_unittest("ValueProxyTest") { configs = [ ":module_private_config" ] + cflags = [ + "-Dprivate=public", + "-Dprotected=public", + "-Wno-multichar", + "-Wno-c99-designator", + ] + external_deps = [ "ability_base:base", "ability_base:want", @@ -294,45 +392,6 @@ ohos_unittest("DeviceMatrixTest") { ] } -ohos_unittest("AutoSyncMatrixTest") { - module_out_path = module_output_path - sources = [ - "${data_service_path}/app/src/kvstore_meta_manager.cpp", - "auto_sync_matrix_test.cpp", - ] - - include_dirs = [ - "${data_service_path}/app/src", - "${data_service_path}/service/kvdb", - "${data_service_path}/adapter/include/account", - "${kv_store_path}/frameworks/innerkitsimpl/kvdb/include", - "${kv_store_path}/frameworks/innerkitsimpl/distributeddatafwk/include", - "${kv_store_path}/frameworks/innerkitsimpl/distributeddatasvc/include", - ] - - configs = [ ":module_private_config" ] - - external_deps = [ - "access_token:libaccesstoken_sdk", - "access_token:libnativetoken", - "access_token:libtoken_setproc", - "c_utils:utils", - "dataclassification:data_transit_mgr", - "hilog:libhilog", - "hisysevent:libhisysevent", - "ipc:ipc_core", - "kv_store:distributeddata_inner", - ] - - deps = [ - "${data_service_path}/adapter:distributeddata_adapter", - "${data_service_path}/framework:distributeddatasvcfwk", - "${data_service_path}/service:distributeddatasvc", - "${kv_store_distributeddb_path}:distributeddb", - "//third_party/googletest:gtest_main", - ] -} - ohos_unittest("KVDBGeneralStoreTest") { module_out_path = module_output_path sources = [ @@ -344,6 +403,8 @@ ohos_unittest("KVDBGeneralStoreTest") { "kvdb_general_store_test.cpp", "mock/db_change_data_mock.cpp", "mock/db_store_mock.cpp", + "mock/general_watcher_mock.cpp", + "mock/kv_store_nb_delegate_mock.cpp", ] include_dirs = [ @@ -357,6 +418,11 @@ ohos_unittest("KVDBGeneralStoreTest") { configs = [ ":module_private_config" ] + cflags = [ + "-Dprivate=public", + "-Dprotected=public", + ] + external_deps = [ "ability_base:base", "ability_base:want", @@ -437,7 +503,9 @@ ohos_unittest("RdbServiceTest") { "${data_service_path}/service/rdb/rdb_query.cpp", "${data_service_path}/service/rdb/rdb_result_set_impl.cpp", "${data_service_path}/service/rdb/rdb_result_set_stub.cpp", + "${data_service_path}/service/rdb/rdb_watcher.cpp", "cache_cursor_test.cpp", + "mock/general_watcher_mock.cpp", "rdb_asset_loader_test.cpp", "rdb_cloud_test.cpp", "rdb_cursor_test.cpp", @@ -484,6 +552,46 @@ ohos_unittest("RdbServiceTest") { ] } +ohos_unittest("ObjectAssetLoaderTest") { + module_out_path = module_output_path + sources = [ + "../object/object_asset_loader.cpp", + "../object/object_asset_machine.cpp", + "../object/object_snapshot.cpp", + "object_asset_loader_test.cpp", + ] + + include_dirs = [ + "${dataobject_path}/frameworks/innerkitsimpl/include/common", + "${dataobject_path}/interfaces/innerkits", + "${relational_store_path}/interfaces/inner_api/common_type/include", + ] + + configs = [ ":module_private_config" ] + + external_deps = [ + "c_utils:utils", + "dfs_service:cloudsync_asset_kit_inner", + "dfs_service:distributed_file_daemon_kit_inner", + "hilog:libhilog", + "hisysevent:libhisysevent", + "ipc:ipc_core", + "kv_store:distributeddata_inner", + ] + + deps = [ + "${data_service_path}/adapter:distributeddata_adapter", + "${data_service_path}/framework:distributeddatasvcfwk", + "${data_service_path}/service:distributeddatasvc", + "//third_party/googletest:gtest_main", + ] + + cflags = [ + "-Dprivate=public", + "-Dprotected=public", + ] +} + ohos_unittest("ObjectAssetMachineTest") { module_out_path = module_output_path sources = [ @@ -518,6 +626,91 @@ ohos_unittest("ObjectAssetMachineTest") { ] } +ohos_unittest("ObjectManagerTest") { + module_out_path = module_output_path + sources = [ + "${data_service_path}/service/common/value_proxy.cpp", + "../object/object_asset_loader.cpp", + "../object/object_asset_machine.cpp", + "../object/object_callback_proxy.cpp", + "../object/object_data_listener.cpp", + "../object/object_manager.cpp", + "../object/object_snapshot.cpp", + "mock/kv_store_nb_delegate_mock.cpp", + "object_manager_test.cpp", + ] + + include_dirs = [ + "${dataobject_path}/frameworks/innerkitsimpl/include", + "${data_service_path}/service/common", + "${dataobject_path}/frameworks/innerkitsimpl/include/common", + "${dataobject_path}/interfaces/innerkits", + ] + + configs = [ ":module_private_config" ] + + external_deps = [ + "access_token:libaccesstoken_sdk", + "access_token:libtokenid_sdk", + "c_utils:utils", + "dfs_service:cloudsync_asset_kit_inner", + "dfs_service:distributed_file_daemon_kit_inner", + "hilog:libhilog", + "hisysevent:libhisysevent", + "ipc:ipc_core", + "kv_store:distributeddata_inner", + "kv_store:distributeddb", + "relational_store:native_rdb", + ] + + deps = [ + "${data_service_path}/adapter:distributeddata_adapter", + "${data_service_path}/framework:distributeddatasvcfwk", + "${data_service_path}/service:distributeddatasvc", + "//third_party/googletest:gtest_main", + ] + + cflags = [ + "-Dprivate=public", + "-Dprotected=public", + ] +} + +ohos_unittest("ObjectSnapshotTest") { + module_out_path = module_output_path + sources = [ + "../object/object_asset_loader.cpp", + "../object/object_asset_machine.cpp", + "../object/object_snapshot.cpp", + "object_snapshot_test.cpp", + ] + + include_dirs = [ + "${dataobject_path}/frameworks/innerkitsimpl/include/common", + "${dataobject_path}/interfaces/innerkits", + "${relational_store_path}/interfaces/inner_api/common_type/include", + ] + + configs = [ ":module_private_config" ] + + external_deps = [ + "c_utils:utils", + "dfs_service:cloudsync_asset_kit_inner", + "dfs_service:distributed_file_daemon_kit_inner", + "hilog:libhilog", + "hisysevent:libhisysevent", + "ipc:ipc_core", + "kv_store:distributeddata_inner", + ] + + deps = [ + "${data_service_path}/adapter:distributeddata_adapter", + "${data_service_path}/framework:distributeddatasvcfwk", + "${data_service_path}/service:distributeddatasvc", + "//third_party/googletest:gtest_main", + ] +} + ohos_unittest("MetaDataTest") { module_out_path = module_output_path sources = [ @@ -623,6 +816,7 @@ ohos_unittest("WaterVersionManagerTest") { "${data_service_path}/service/backup/src/backup_manager.cpp", "${data_service_path}/service/bootstrap/src/bootstrap.cpp", "${data_service_path}/service/config/src/config_factory.cpp", + "${data_service_path}/service/config/src/model/app_id_mapping_config.cpp", "${data_service_path}/service/config/src/model/backup_config.cpp", "${data_service_path}/service/config/src/model/checker_config.cpp", "${data_service_path}/service/config/src/model/cloud_config.cpp", @@ -804,7 +998,19 @@ ohos_unittest("KvdbServiceImplTest") { module_out_path = module_output_path sources = [ "${data_service_path}/app/src/kvstore_meta_manager.cpp", + "${data_service_path}/service/common/value_proxy.cpp", + "${data_service_path}/service/kvdb/auth_delegate.cpp", + "${data_service_path}/service/kvdb/kvdb_general_store.cpp", + "${data_service_path}/service/kvdb/kvdb_notifier_proxy.cpp", + "${data_service_path}/service/kvdb/kvdb_watcher.cpp", + "${data_service_path}/service/kvdb/query_helper.cpp", + "${data_service_path}/service/kvdb/upgrade.cpp", + "${data_service_path}/service/kvdb/user_delegate.cpp", + "${data_service_path}/service/rdb/rdb_cloud.cpp", + "${data_service_path}/service/rdb/rdb_query.cpp", + "${data_service_path}/service/waterversion/water_version_manager.cpp", "kvdb_service_impl_test.cpp", + "kvdb_service_test.cpp", ] include_dirs = [ @@ -818,16 +1024,23 @@ ohos_unittest("KvdbServiceImplTest") { configs = [ ":module_private_config" ] + cflags = [ + "-Dprivate=public", + "-Dprotected=public", + ] + external_deps = [ "access_token:libaccesstoken_sdk", "access_token:libnativetoken", "access_token:libtoken_setproc", "c_utils:utils", "dataclassification:data_transit_mgr", + "device_auth:deviceauth_sdk", "hilog:libhilog", "hisysevent:libhisysevent", "ipc:ipc_core", "kv_store:distributeddata_inner", + "relational_store:native_rdb", ] deps = [ @@ -839,6 +1052,37 @@ ohos_unittest("KvdbServiceImplTest") { ] } +ohos_unittest("DumpHelperTest") { + module_out_path = module_output_path + sources = [ + "${data_service_path}/service/dumper/src/dump_helper.cpp", + "dump_helper_test.cpp", + ] + + include_dirs = [ "${data_service_path}/service/dumper/include" ] + + configs = [ ":module_private_config" ] + + cflags = [ + "-Dprivate=public", + "-Dprotected=public", + ] + + external_deps = [ + "c_utils:utils", + "hilog:libhilog", + "kv_store:distributeddata_inner", + "kv_store:distributeddb", + "relational_store:native_rdb", + ] + + deps = [ + "${data_service_path}/framework:distributeddatasvcfwk", + "${data_service_path}/service:distributeddatasvc", + "//third_party/googletest:gtest_main", + ] +} + ############################################################################### group("unittest") { testonly = true @@ -850,21 +1094,25 @@ group("unittest") { } deps += [ - ":AutoSyncMatrixTest", ":CloudDataTest", + ":CloudServiceImplTest", ":CloudTest", ":CryptoManagerTest", ":DataShareServiceImplTest", ":DeviceMatrixTest", ":DirectoryManagerTest", + ":DumpHelperTest", ":KVDBGeneralStoreTest", ":KvdbServiceImplTest", ":MetaDataTest", + ":ObjectAssetLoaderTest", ":ObjectAssetMachineTest", + ":ObjectManagerTest", + ":ObjectSnapshotTest", ":RdbResultSetImplTest", ":RdbServiceTest", ":UdmfRunTimeStoreTest", - ":ValueProxyTest", + ":ValueProxyServiceTest", ":WaterVersionManagerTest", ] } diff --git a/datamgr_service/services/distributeddataservice/service/test/auto_sync_matrix_test.cpp b/datamgr_service/services/distributeddataservice/service/test/auto_sync_matrix_test.cpp deleted file mode 100644 index adc5022205b978765bbaf9e8ddd86314828b046e..0000000000000000000000000000000000000000 --- a/datamgr_service/services/distributeddataservice/service/test/auto_sync_matrix_test.cpp +++ /dev/null @@ -1,230 +0,0 @@ -/* - * Copyright (c) 2024 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -#include "auto_sync_matrix.h" - -#include -#include "block_data.h" -#include "bootstrap.h" -#include "device_manager_adapter.h" -#include "eventcenter/event_center.h" -#include "executor_pool.h" -#include "feature/feature_system.h" -#include "gtest/gtest.h" -#include "ipc_skeleton.h" -#include "kvstore_meta_manager.h" -#include "matrix_event.h" -#include "metadata/meta_data_manager.h" -#include "metadata/store_meta_data.h" -#include "types.h" -using namespace testing::ext; -using namespace OHOS::DistributedData; -using DMAdapter = DeviceManagerAdapter; -using namespace DistributedDB; -namespace OHOS::Test { -namespace DistributedDataTest { -class AutoSyncMatrixTest : public testing::Test { -public: - static void SetUpTestCase(void); - static void TearDownTestCase(void); - void SetUp(); - void TearDown(); - -protected: - static constexpr const char *TEST_DEVICE = "14a0a92a428005db27c40bad46bf145fede38ec37effe0347cd990fcb031f320"; - static constexpr const char *TEST_BUNDLE = "auto_sync_matrix_test"; - static constexpr const char *TEST_STORE = "auto_sync_matrix_store"; - static constexpr const char *TEST_USER = "0"; - void InitMetaData(); - - StoreMetaData metaData_; -}; - -void AutoSyncMatrixTest::SetUpTestCase(void) -{ - auto executors = std::make_shared(12, 5); - Bootstrap::GetInstance().LoadComponents(); - Bootstrap::GetInstance().LoadDirectory(); - Bootstrap::GetInstance().LoadCheckers(); - DMAdapter::GetInstance().Init(executors); - DistributedKv::KvStoreMetaManager::GetInstance().BindExecutor(executors); - DistributedKv::KvStoreMetaManager::GetInstance().InitMetaParameter(); - DistributedKv::KvStoreMetaManager::GetInstance().InitMetaListener(); - StoreMetaData meta; - meta.deviceId = DMAdapter::GetInstance().GetLocalDevice().uuid; - meta.appId = TEST_BUNDLE; - meta.bundleName = TEST_BUNDLE; - meta.user = TEST_USER; - meta.area = DistributedKv::EL1; - meta.tokenId = IPCSkeleton::GetCallingTokenID(); - meta.instanceId = 0; - meta.isAutoSync = true; - meta.storeType = 1; - meta.storeId = "auto_sync_matrix_default_store"; - meta.dataType = 1; - MetaDataManager::GetInstance().SaveMeta(meta.GetKey(), meta); - AutoSyncMatrix::GetInstance().Initialize(); -} - -void AutoSyncMatrixTest::TearDownTestCase(void) -{ -} - -void AutoSyncMatrixTest::SetUp() -{ - InitMetaData(); -} - -void AutoSyncMatrixTest::TearDown() -{ -} - -void AutoSyncMatrixTest::InitMetaData() -{ - metaData_.deviceId = DMAdapter::GetInstance().GetLocalDevice().uuid; - metaData_.appId = TEST_BUNDLE; - metaData_.bundleName = TEST_BUNDLE; - metaData_.user = TEST_USER; - metaData_.area = DistributedKv::EL1; - metaData_.tokenId = IPCSkeleton::GetCallingTokenID(); - metaData_.instanceId = 0; - metaData_.isAutoSync = true; - metaData_.storeType = 1; - metaData_.storeId = TEST_STORE; - metaData_.dataType = 1; -} - -/** -* @tc.name: GetChangedStore -* @tc.desc: get changed store on init. -* @tc.type: FUNC -* @tc.require: -* @tc.author: zuojiangjiang -*/ -HWTEST_F(AutoSyncMatrixTest, GetChangedStore, TestSize.Level0) -{ - auto metas = AutoSyncMatrix::GetInstance().GetChangedStore(""); - ASSERT_EQ(metas.size(), 0); - metas = AutoSyncMatrix::GetInstance().GetChangedStore(TEST_DEVICE); - ASSERT_EQ(metas.size(), 0); -} - -/** -* @tc.name: AutoSyncMatrixOnline -* @tc.desc: auto sync matrix online. -* @tc.type: FUNC -* @tc.require: -* @tc.author: zuojiangjiang -*/ -HWTEST_F(AutoSyncMatrixTest, AutoSyncMatrixOnline, TestSize.Level0) -{ - AutoSyncMatrix::GetInstance().Online(""); - auto metas = AutoSyncMatrix::GetInstance().GetChangedStore(TEST_DEVICE); - ASSERT_EQ(metas.size(), 0); - AutoSyncMatrix::GetInstance().Online(TEST_DEVICE); - metas = AutoSyncMatrix::GetInstance().GetChangedStore(TEST_DEVICE); - ASSERT_GE(metas.size(), 0); - AutoSyncMatrix::GetInstance().Offline(TEST_DEVICE); - metas = AutoSyncMatrix::GetInstance().GetChangedStore(TEST_DEVICE); - ASSERT_EQ(metas.size(), 0); -} - -/** -* @tc.name: AutoSyncMatrixOffline -* @tc.desc: auto sync matrix offline. -* @tc.type: FUNC -* @tc.require: -* @tc.author: zuojiangjiang -*/ -HWTEST_F(AutoSyncMatrixTest, AutoSyncMatrixOffline, TestSize.Level0) -{ - AutoSyncMatrix::GetInstance().Online(TEST_DEVICE); - auto before = AutoSyncMatrix::GetInstance().GetChangedStore(TEST_DEVICE); - ASSERT_GE(before.size(), 0); - MetaDataManager::GetInstance().SaveMeta(metaData_.GetKey(), metaData_); - std::this_thread::sleep_for(std::chrono::milliseconds(100)); - auto after = AutoSyncMatrix::GetInstance().GetChangedStore(TEST_DEVICE); - ASSERT_GE(after.size(), before.size()); - AutoSyncMatrix::GetInstance().Offline(TEST_DEVICE); - auto metas = AutoSyncMatrix::GetInstance().GetChangedStore(TEST_DEVICE); - ASSERT_EQ(metas.size(), 0); -} - -/** -* @tc.name: AutoSyncMatrixOnChanged -* @tc.desc: auto sync matrix on changed. -* @tc.type: FUNC -* @tc.require: -* @tc.author: zuojiangjiang -*/ -HWTEST_F(AutoSyncMatrixTest, AutoSyncMatrixOnChanged, TestSize.Level0) -{ - AutoSyncMatrix::GetInstance().Online(TEST_DEVICE); - auto metas = AutoSyncMatrix::GetInstance().GetChangedStore(TEST_DEVICE); - ASSERT_GE(metas.size(), 0); - AutoSyncMatrix::GetInstance().OnChanged(metaData_); - metas = AutoSyncMatrix::GetInstance().GetChangedStore(TEST_DEVICE); - ASSERT_GE(metas.size(), 0); - AutoSyncMatrix::GetInstance().Offline(TEST_DEVICE); - metas = AutoSyncMatrix::GetInstance().GetChangedStore(TEST_DEVICE); - ASSERT_EQ(metas.size(), 0); -} - -/** -* @tc.name: AutoSyncMatrixOnExchanged -* @tc.desc: auto sync matrix on exchanged. -* @tc.type: FUNC -* @tc.require: -* @tc.author: zuojiangjiang -*/ -HWTEST_F(AutoSyncMatrixTest, AutoSyncMatrixOnExchanged, TestSize.Level0) -{ - AutoSyncMatrix::GetInstance().Online(TEST_DEVICE); - auto metas1 = AutoSyncMatrix::GetInstance().GetChangedStore(TEST_DEVICE); - ASSERT_GE(metas1.size(), 0); - AutoSyncMatrix::GetInstance().OnExchanged(TEST_DEVICE, metaData_); - auto metas2 = AutoSyncMatrix::GetInstance().GetChangedStore(TEST_DEVICE); - ASSERT_EQ(metas2.size(), metas1.size() - 1); - AutoSyncMatrix::GetInstance().Offline(TEST_DEVICE); - AutoSyncMatrix::GetInstance().OnChanged(metaData_); - auto metas3 = AutoSyncMatrix::GetInstance().GetChangedStore(TEST_DEVICE); - ASSERT_EQ(metas3.size(), 0); - AutoSyncMatrix::GetInstance().Online(TEST_DEVICE); - auto metas4 = AutoSyncMatrix::GetInstance().GetChangedStore(TEST_DEVICE); - ASSERT_GE(metas4.size(), metas1.size()); -} - -/** -* @tc.name: AutoSyncMatrixDeleteMeta -* @tc.desc: auto sync matrix on delete Meta. -* @tc.type: FUNC -* @tc.require: -* @tc.author: zuojiangjiang -*/ -HWTEST_F(AutoSyncMatrixTest, AutoSyncMatrixDeleteMeta, TestSize.Level0) -{ - AutoSyncMatrix::GetInstance().Online(TEST_DEVICE); - AutoSyncMatrix::GetInstance().OnChanged(metaData_); - auto metas1 = AutoSyncMatrix::GetInstance().GetChangedStore(TEST_DEVICE); - ASSERT_GE(metas1.size(), 0); - MetaDataManager::GetInstance().DelMeta(metaData_.GetKey()); - std::this_thread::sleep_for(std::chrono::milliseconds(100)); - auto metas2 = AutoSyncMatrix::GetInstance().GetChangedStore(TEST_DEVICE); - ASSERT_GE(metas2.size(), metas1.size() -1); - for (auto meta : metas2) { - ASSERT_NE(metaData_.GetKey(), meta.GetKey()); - } -} -} // namespace DistributedDataTest -} // namespace OHOS::Test \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/test/cloud_data_test.cpp b/datamgr_service/services/distributeddataservice/service/test/cloud_data_test.cpp index 010d99940e6feda4008ae73227c2aa9445b13492..be76bb4d20bf46c5c8bd6358ce699c66c42c0fd4 100644 --- a/datamgr_service/services/distributeddataservice/service/test/cloud_data_test.cpp +++ b/datamgr_service/services/distributeddataservice/service/test/cloud_data_test.cpp @@ -23,9 +23,13 @@ #include "cloud/change_event.h" #include "cloud/cloud_event.h" #include "cloud/cloud_server.h" +#include "cloud/cloud_share_event.h" +#include "cloud/make_query_event.h" #include "cloud/schema_meta.h" #include "cloud_service_impl.h" #include "cloud_types.h" +#include "cloud_types_util.h" +#include "cloud_value_util.h" #include "communicator/device_manager_adapter.h" #include "device_matrix.h" #include "eventcenter/event_center.h" @@ -51,7 +55,11 @@ using namespace OHOS::Security::AccessToken; using DmAdapter = OHOS::DistributedData::DeviceManagerAdapter; using Querykey = OHOS::CloudData::QueryKey; using CloudSyncInfo = OHOS::CloudData::CloudSyncInfo; - +using SharingCfm = OHOS::CloudData::SharingUtil::SharingCfm; +using Confirmation = OHOS::CloudData::Confirmation; +using CenterCode = OHOS::DistributedData::SharingCenter::SharingCode; +using Status = OHOS::CloudData::CloudService::Status; +using GenErr = OHOS::DistributedData::GeneralError; uint64_t g_selfTokenID = 0; void AllocHapToken(const HapPolicyParams &policy) @@ -75,6 +83,32 @@ static constexpr const char *TEST_CLOUD_STORE = "test_cloud_store"; static constexpr const char *TEST_CLOUD_ID = "test_cloud_id"; static constexpr const char *TEST_CLOUD_DATABASE_ALIAS_1 = "test_cloud_database_alias_1"; static constexpr const char *TEST_CLOUD_DATABASE_ALIAS_2 = "test_cloud_database_alias_2"; +static constexpr const char *PERMISSION_CLOUDDATA_CONFIG = "ohos.permission.CLOUDDATA_CONFIG"; +static constexpr const char *PERMISSION_GET_NETWORK_INFO = "ohos.permission.GET_NETWORK_INFO"; +static constexpr const char *PERMISSION_DISTRIBUTED_DATASYNC = "ohos.permission.DISTRIBUTED_DATASYNC"; +static constexpr const char *PERMISSION_ACCESS_SERVICE_DM = "ohos.permission.ACCESS_SERVICE_DM"; +PermissionDef GetPermissionDef(const std::string &permission) +{ + PermissionDef def = { .permissionName = permission, + .bundleName = "test_cloud_bundleName", + .grantMode = 1, + .availableLevel = APL_SYSTEM_BASIC, + .label = "label", + .labelId = 1, + .description = "test_cloud_bundleName", + .descriptionId = 1 }; + return def; +} + +PermissionStateFull GetPermissionStateFull(const std::string &permission) +{ + PermissionStateFull stateFull = { .permissionName = permission, + .isGeneral = true, + .resDeviceID = { "local" }, + .grantStatus = { PermissionState::PERMISSION_GRANTED }, + .grantFlags = { 1 } }; + return stateFull; +} class CloudDataTest : public testing::Test { public: static void SetUpTestCase(void); @@ -102,6 +136,7 @@ public: virtual ~CloudServerMock() = default; static constexpr uint64_t REMAINSPACE = 1000; static constexpr uint64_t TATALSPACE = 2000; + static constexpr int32_t INVALID_USER_ID = -1; }; CloudInfo CloudServerMock::GetServerInfo(int32_t userId, bool needSpaceInfo) @@ -125,6 +160,14 @@ CloudInfo CloudServerMock::GetServerInfo(int32_t userId, bool needSpaceInfo) std::pair CloudServerMock::GetAppSchema(int32_t userId, const std::string &bundleName) { + if (userId == INVALID_USER_ID) { + return { E_ERROR, CloudDataTest::schemaMeta_ }; + } + + if (bundleName.empty()) { + SchemaMeta schemaMeta; + return { E_OK, schemaMeta }; + } return { E_OK, CloudDataTest::schemaMeta_ }; } @@ -202,46 +245,29 @@ void CloudDataTest::SetUpTestCase(void) auto cloudServerMock = new CloudServerMock(); CloudServer::RegisterCloudInstance(cloudServerMock); - HapPolicyParams policy = { .apl = APL_SYSTEM_BASIC, .domain = "test.domain", - .permList = { - { - .permissionName = "ohos.permission.CLOUDDATA_CONFIG", - .bundleName = "test_cloud_bundleName", - .grantMode = 1, - .availableLevel = APL_SYSTEM_BASIC, - .label = "label", - .labelId = 1, - .description = "test_cloud_bundleName", - .descriptionId = 1 - } - }, - .permStateList = { - { - .permissionName = "ohos.permission.CLOUDDATA_CONFIG", - .isGeneral = true, - .resDeviceID = { "local" }, - .grantStatus = { PermissionState::PERMISSION_GRANTED }, - .grantFlags = { 1 } - } - } - }; + .permList = { GetPermissionDef(PERMISSION_CLOUDDATA_CONFIG), GetPermissionDef(PERMISSION_GET_NETWORK_INFO), + GetPermissionDef(PERMISSION_DISTRIBUTED_DATASYNC), GetPermissionDef(PERMISSION_ACCESS_SERVICE_DM) }, + .permStateList = { GetPermissionStateFull(PERMISSION_CLOUDDATA_CONFIG), + GetPermissionStateFull(PERMISSION_GET_NETWORK_INFO), + GetPermissionStateFull(PERMISSION_DISTRIBUTED_DATASYNC), + GetPermissionStateFull(PERMISSION_ACCESS_SERVICE_DM) } }; g_selfTokenID = GetSelfTokenID(); AllocHapToken(policy); - - InitCloudInfo(); - InitMetaData(); - InitSchemaMeta(); - size_t max = 12; size_t min = 5; auto executor = std::make_shared(max, min); cloudServiceImpl_->OnBind( { "CloudDataTest", static_cast(IPCSkeleton::GetSelfTokenID()), std::move(executor) }); - Bootstrap::GetInstance().LoadCheckers(); + auto dmExecutor = std::make_shared(max, min); + DeviceManagerAdapter::GetInstance().Init(dmExecutor); + InitCloudInfo(); + InitMetaData(); + InitSchemaMeta(); + DeviceManagerAdapter::GetInstance().SetNet(DeviceManagerAdapter::WIFI); } void CloudDataTest::TearDownTestCase() @@ -282,7 +308,8 @@ HWTEST_F(CloudDataTest, GetSchema, TestSize.Level0) StoreInfo storeInfo{ OHOS::IPCSkeleton::GetCallingTokenID(), TEST_CLOUD_BUNDLE, TEST_CLOUD_STORE, 0 }; auto event = std::make_unique(CloudEvent::GET_SCHEMA, storeInfo); EventCenter::GetInstance().PostEvent(std::move(event)); - ASSERT_FALSE(MetaDataManager::GetInstance().LoadMeta(cloudInfo.GetSchemaKey(TEST_CLOUD_BUNDLE), schemaMeta, true)); + auto ret = MetaDataManager::GetInstance().LoadMeta(cloudInfo.GetSchemaKey(TEST_CLOUD_BUNDLE), schemaMeta, true); + ASSERT_TRUE(ret); } /** @@ -455,17 +482,7 @@ HWTEST_F(CloudDataTest, QueryLastSyncInfo004, TestSize.Level0) ZLOGI("CloudDataTest QueryLastSyncInfo004 start"); auto ret = cloudServiceImpl_->DisableCloud(TEST_CLOUD_ID); EXPECT_EQ(ret, CloudData::CloudService::SUCCESS); - - auto rdbServiceImpl = std::make_shared(); - DistributedRdb::RdbSyncerParam param; - param.bundleName_ = TEST_CLOUD_BUNDLE; - param.storeName_ = TEST_CLOUD_DATABASE_ALIAS_1; - DistributedRdb::RdbService::Option option; - option.mode = DistributedRdb::SyncMode::CLOUD_FIRST; - option.isAutoSync = true; - option.isAsync = false; - DistributedRdb::PredicatesMemo memo; - rdbServiceImpl->Sync(param, option, memo, nullptr); + cloudServiceImpl_->OnReady(DeviceManagerAdapter::CLOUD_DEVICE_UUID); sleep(1); @@ -487,23 +504,11 @@ HWTEST_F(CloudDataTest, QueryLastSyncInfo005, TestSize.Level0) ZLOGI("CloudDataTest QueryLastSyncInfo005 start"); std::map switches; switches.emplace(TEST_CLOUD_ID, true); - auto ret = cloudServiceImpl_->EnableCloud(TEST_CLOUD_ID, switches); - EXPECT_EQ(ret, CloudData::CloudService::SUCCESS); - - ret = cloudServiceImpl_->ChangeAppSwitch(TEST_CLOUD_ID, TEST_CLOUD_BUNDLE, false); - EXPECT_EQ(ret, CloudData::CloudService::SUCCESS); - - auto rdbServiceImpl = std::make_shared(); - DistributedRdb::RdbSyncerParam param; - param.bundleName_ = TEST_CLOUD_BUNDLE; - param.storeName_ = TEST_CLOUD_DATABASE_ALIAS_1; - DistributedRdb::RdbService::Option option; - option.mode = DistributedRdb::SyncMode::CLOUD_FIRST; - option.isAutoSync = true; - option.isAsync = false; - DistributedRdb::PredicatesMemo memo; - rdbServiceImpl->Sync(param, option, memo, nullptr); - + CloudInfo info; + MetaDataManager::GetInstance().LoadMeta(cloudInfo_.GetKey(), info, true); + info.apps[TEST_CLOUD_BUNDLE].cloudSwitch = false; + MetaDataManager::GetInstance().SaveMeta(info.GetKey(), info, true); + cloudServiceImpl_->OnReady(DeviceManagerAdapter::CLOUD_DEVICE_UUID); sleep(1); auto [status, result] = @@ -512,5 +517,1458 @@ HWTEST_F(CloudDataTest, QueryLastSyncInfo005, TestSize.Level0) EXPECT_TRUE(!result.empty()); EXPECT_TRUE(result[TEST_CLOUD_DATABASE_ALIAS_1].code = E_CLOUD_DISABLED); } + +/** +* @tc.name: QueryLastSyncInfo006 +* @tc.desc: The query last sync info interface failed when schema is invalid. +* @tc.type: FUNC +* @tc.require: + */ +HWTEST_F(CloudDataTest, QueryLastSyncInfo006, TestSize.Level0) +{ + ZLOGI("CloudDataTest QueryLastSyncInfo006 start"); + MetaDataManager::GetInstance().DelMeta(cloudInfo_.GetSchemaKey(TEST_CLOUD_BUNDLE), true); + auto [status, result] = + cloudServiceImpl_->QueryLastSyncInfo(TEST_CLOUD_ID, TEST_CLOUD_BUNDLE, TEST_CLOUD_DATABASE_ALIAS_1); + EXPECT_EQ(status, CloudData::CloudService::ERROR); + EXPECT_TRUE(result.empty()); + SchemaMeta meta; + meta.bundleName = "test"; + MetaDataManager::GetInstance().SaveMeta(cloudInfo_.GetSchemaKey(TEST_CLOUD_BUNDLE), meta, true); + std::tie(status, result) = + cloudServiceImpl_->QueryLastSyncInfo(TEST_CLOUD_ID, TEST_CLOUD_BUNDLE, TEST_CLOUD_DATABASE_ALIAS_1); + EXPECT_EQ(status, CloudData::CloudService::SUCCESS); + EXPECT_TRUE(result.empty()); +} + +/** +* @tc.name: Share +* @tc.desc: +* @tc.type: FUNC +* @tc.require: + */ +HWTEST_F(CloudDataTest, Share001, TestSize.Level0) +{ + std::string sharingRes = ""; + CloudData::Participants participants{}; + CloudData::Results results; + auto ret = cloudServiceImpl_->Share(sharingRes, participants, results); + EXPECT_EQ(ret, CloudData::CloudService::NOT_SUPPORT); +} + +/** +* @tc.name: Unshare +* @tc.desc: +* @tc.type: FUNC +* @tc.require: + */ +HWTEST_F(CloudDataTest, Unshare001, TestSize.Level0) +{ + std::string sharingRes = ""; + CloudData::Participants participants{}; + CloudData::Results results; + auto ret = cloudServiceImpl_->Unshare(sharingRes, participants, results); + EXPECT_EQ(ret, CloudData::CloudService::NOT_SUPPORT); +} + +/** +* @tc.name: ChangePrivilege +* @tc.desc: +* @tc.type: FUNC +* @tc.require: + */ +HWTEST_F(CloudDataTest, ChangePrivilege001, TestSize.Level0) +{ + std::string sharingRes = ""; + CloudData::Participants participants{}; + CloudData::Results results; + auto ret = cloudServiceImpl_->ChangePrivilege(sharingRes, participants, results); + EXPECT_EQ(ret, CloudData::CloudService::NOT_SUPPORT); +} + +/** +* @tc.name: ChangeConfirmation +* @tc.desc: +* @tc.type: FUNC +* @tc.require: + */ +HWTEST_F(CloudDataTest, ChangeConfirmation001, TestSize.Level0) +{ + std::string sharingRes = ""; + int32_t confirmation = 0; + std::pair result; + auto ret = cloudServiceImpl_->ChangeConfirmation(sharingRes, confirmation, result); + EXPECT_EQ(ret, CloudData::CloudService::NOT_SUPPORT); +} + +/** +* @tc.name: ConfirmInvitation +* @tc.desc: +* @tc.type: FUNC +* @tc.require: + */ +HWTEST_F(CloudDataTest, ConfirmInvitation001, TestSize.Level0) +{ + std::string sharingRes = ""; + int32_t confirmation = 0; + std::tuple result; + auto ret = cloudServiceImpl_->ConfirmInvitation(sharingRes, confirmation, result); + EXPECT_EQ(ret, CloudData::CloudService::NOT_SUPPORT); +} + +/** +* @tc.name: Exit +* @tc.desc: +* @tc.type: FUNC +* @tc.require: + */ +HWTEST_F(CloudDataTest, Exit001, TestSize.Level0) +{ + std::string sharingRes = ""; + std::pair result; + auto ret = cloudServiceImpl_->Exit(sharingRes, result); + EXPECT_EQ(ret, CloudData::CloudService::NOT_SUPPORT); +} + +/** +* @tc.name: Query +* @tc.desc: +* @tc.type: FUNC +* @tc.require: + */ +HWTEST_F(CloudDataTest, Query001, TestSize.Level0) +{ + std::string sharingRes = ""; + CloudData::QueryResults result; + auto ret = cloudServiceImpl_->Query(sharingRes, result); + EXPECT_EQ(ret, CloudData::CloudService::NOT_SUPPORT); +} + +/** +* @tc.name: QueryByInvitation +* @tc.desc: +* @tc.type: FUNC +* @tc.require: + */ +HWTEST_F(CloudDataTest, QueryByInvitation001, TestSize.Level0) +{ + std::string invitation = ""; + CloudData::QueryResults result; + auto ret = cloudServiceImpl_->QueryByInvitation(invitation, result); + EXPECT_EQ(ret, CloudData::CloudService::NOT_SUPPORT); +} + +/** +* @tc.name: AllocResourceAndShare +* @tc.desc: +* @tc.type: FUNC +* @tc.require: + */ +HWTEST_F(CloudDataTest, AllocResourceAndShare001, TestSize.Level0) +{ + DistributedRdb::PredicatesMemo predicates; + predicates.tables_.push_back(TEST_CLOUD_BUNDLE); + std::vector columns; + CloudData::Participants participants; + auto [ret, _] = cloudServiceImpl_->AllocResourceAndShare(TEST_CLOUD_STORE, predicates, columns, participants); + EXPECT_EQ(ret, E_ERROR); + EventCenter::GetInstance().Subscribe(CloudEvent::MAKE_QUERY, [](const Event& event) { + auto& evt = static_cast(event); + auto callback = evt.GetCallback(); + if (!callback) { + return; + } + auto predicate = evt.GetPredicates(); + auto rdbQuery = std::make_shared(); + rdbQuery->MakeQuery(*predicate); + rdbQuery->SetColumns(evt.GetColumns()); + callback(rdbQuery); + }); + std::tie(ret, _) = cloudServiceImpl_->AllocResourceAndShare(TEST_CLOUD_STORE, predicates, columns, participants); + EXPECT_EQ(ret, E_ERROR); +} + +/** +* @tc.name: SetGlobalCloudStrategy +* @tc.desc: +* @tc.type: FUNC +* @tc.require: + */ +HWTEST_F(CloudDataTest, SetGlobalCloudStrategy001, TestSize.Level0) +{ + std::vector values; + values.push_back(CloudData::NetWorkStrategy::WIFI); + CloudData::Strategy strategy = CloudData::Strategy::STRATEGY_BUTT; + auto ret = cloudServiceImpl_->SetGlobalCloudStrategy(strategy, values); + EXPECT_EQ(ret, CloudData::CloudService::INVALID_ARGUMENT); + strategy = CloudData::Strategy::STRATEGY_NETWORK; + ret = cloudServiceImpl_->SetGlobalCloudStrategy(strategy, values); + EXPECT_EQ(ret, CloudData::CloudService::SUCCESS); +} + +/** +* @tc.name: SetCloudStrategy +* @tc.desc: +* @tc.type: FUNC +* @tc.require: + */ +HWTEST_F(CloudDataTest, SetCloudStrategy001, TestSize.Level0) +{ + std::vector values; + values.push_back(CloudData::NetWorkStrategy::WIFI); + CloudData::Strategy strategy = CloudData::Strategy::STRATEGY_BUTT; + auto ret = cloudServiceImpl_->SetCloudStrategy(strategy, values); + EXPECT_EQ(ret, CloudData::CloudService::INVALID_ARGUMENT); + strategy = CloudData::Strategy::STRATEGY_NETWORK; + ret = cloudServiceImpl_->SetCloudStrategy(strategy, values); + EXPECT_EQ(ret, CloudData::CloudService::SUCCESS); +} + +/** +* @tc.name: Clean +* @tc.desc: +* @tc.type: FUNC +* @tc.require: + */ +HWTEST_F(CloudDataTest, Clean001, TestSize.Level0) +{ + std::map actions; + actions.insert_or_assign(TEST_CLOUD_BUNDLE, CloudData::CloudService::Action::CLEAR_CLOUD_BUTT); + std::string id = "testId"; + std::string bundleName = "testBundleName"; + auto ret = cloudServiceImpl_->Clean(id, actions); + EXPECT_EQ(ret, CloudData::CloudService::ERROR); + ret = cloudServiceImpl_->Clean(TEST_CLOUD_ID, actions); + EXPECT_EQ(ret, CloudData::CloudService::ERROR); + actions.insert_or_assign(TEST_CLOUD_BUNDLE, CloudData::CloudService::Action::CLEAR_CLOUD_INFO); + actions.insert_or_assign(bundleName, CloudData::CloudService::Action::CLEAR_CLOUD_DATA_AND_INFO); + ret = cloudServiceImpl_->Clean(TEST_CLOUD_ID, actions); + EXPECT_EQ(ret, CloudData::CloudService::SUCCESS); +} + +/** +* @tc.name: Clean +* @tc.desc: +* @tc.type: FUNC +* @tc.require: + */ +HWTEST_F(CloudDataTest, Clean002, TestSize.Level0) +{ + MetaDataManager::GetInstance().DelMeta(metaData_.GetKey(), true); + std::map actions; + actions.insert_or_assign(TEST_CLOUD_BUNDLE, CloudData::CloudService::Action::CLEAR_CLOUD_INFO); + auto ret = cloudServiceImpl_->Clean(TEST_CLOUD_ID, actions); + EXPECT_EQ(ret, CloudData::CloudService::SUCCESS); + StoreMetaDataLocal localMeta; + localMeta.isPublic = false; + MetaDataManager::GetInstance().SaveMeta(metaData_.GetKeyLocal(), localMeta, true); + ret = cloudServiceImpl_->Clean(TEST_CLOUD_ID, actions); + EXPECT_EQ(ret, CloudData::CloudService::SUCCESS); + localMeta.isPublic = true; + MetaDataManager::GetInstance().SaveMeta(metaData_.GetKeyLocal(), localMeta, true); + ret = cloudServiceImpl_->Clean(TEST_CLOUD_ID, actions); + EXPECT_EQ(ret, CloudData::CloudService::SUCCESS); + metaData_.user = "0"; + MetaDataManager::GetInstance().SaveMeta(metaData_.GetKey(), metaData_, true); + ret = cloudServiceImpl_->Clean(TEST_CLOUD_ID, actions); + EXPECT_EQ(ret, CloudData::CloudService::SUCCESS); + MetaDataManager::GetInstance().DelMeta(metaData_.GetKey(), true); + metaData_.user = std::to_string(DistributedKv::AccountDelegate::GetInstance()->GetUserByToken(metaData_.tokenId)); + MetaDataManager::GetInstance().DelMeta(metaData_.GetKeyLocal(), true); +} + +/** +* @tc.name: NotifyDataChange +* @tc.desc: +* @tc.type: FUNC +* @tc.require: + */ +HWTEST_F(CloudDataTest, NotifyDataChange001, TestSize.Level0) +{ + auto ret = cloudServiceImpl_->NotifyDataChange(TEST_CLOUD_ID, TEST_CLOUD_BUNDLE); + EXPECT_EQ(ret, CloudData::CloudService::SUCCESS); +} + +/** +* @tc.name: NotifyDataChange +* @tc.desc: +* @tc.type: FUNC +* @tc.require: + */ +HWTEST_F(CloudDataTest, NotifyDataChange002, TestSize.Level0) +{ + constexpr const int32_t invalidUserId = -1; + std::string extraData; + auto ret = cloudServiceImpl_->NotifyDataChange("", extraData, invalidUserId); + EXPECT_EQ(ret, CloudData::CloudService::INVALID_ARGUMENT); + ret = cloudServiceImpl_->NotifyDataChange(CloudData::DATA_CHANGE_EVENT_ID, extraData, invalidUserId); + EXPECT_EQ(ret, CloudData::CloudService::INVALID_ARGUMENT); + extraData = "{data:test}"; + ret = cloudServiceImpl_->NotifyDataChange(CloudData::DATA_CHANGE_EVENT_ID, extraData, invalidUserId); + EXPECT_EQ(ret, CloudData::CloudService::INVALID_ARGUMENT); + extraData = "{\"data\":\"{\\\"accountId\\\":\\\"id\\\",\\\"bundleName\\\":\\\"test_cloud_" + "bundleName\\\",\\\"containerName\\\":\\\"test_cloud_database_alias_1\\\", \\\"databaseScopes\\\": " + "\\\"[\\\\\\\"private\\\\\\\", " + "\\\\\\\"shared\\\\\\\"]\\\",\\\"recordTypes\\\":\\\"[\\\\\\\"test_cloud_table_alias\\\\\\\"]\\\"}\"}"; + ret = cloudServiceImpl_->NotifyDataChange(CloudData::DATA_CHANGE_EVENT_ID, extraData, invalidUserId); + EXPECT_EQ(ret, CloudData::CloudService::INVALID_ARGUMENT); + extraData = "{\"data\":\"{\\\"accountId\\\":\\\"test_cloud_id\\\",\\\"bundleName\\\":\\\"cloud_" + "bundleName_test\\\",\\\"containerName\\\":\\\"test_cloud_database_alias_1\\\", " + "\\\"databaseScopes\\\": " + "\\\"[\\\\\\\"private\\\\\\\", " + "\\\\\\\"shared\\\\\\\"]\\\",\\\"recordTypes\\\":\\\"[\\\\\\\"test_cloud_table_alias\\\\\\\"]\\\"}\"}"; + ret = cloudServiceImpl_->NotifyDataChange(CloudData::DATA_CHANGE_EVENT_ID, extraData, invalidUserId); + EXPECT_EQ(ret, CloudData::CloudService::INVALID_ARGUMENT); +} + +/** +* @tc.name: NotifyDataChange +* @tc.desc: +* @tc.type: FUNC +* @tc.require: + */ +HWTEST_F(CloudDataTest, NotifyDataChange003, TestSize.Level0) +{ + constexpr const int32_t userId = 100; + constexpr const int32_t defaultUserId = 0; + std::string extraData = "{\"data\":\"{\\\"accountId\\\":\\\"test_cloud_id\\\",\\\"bundleName\\\":\\\"test_cloud_" + "bundleName\\\",\\\"containerName\\\":\\\"test_cloud_database_alias_1\\\", " + "\\\"databaseScopes\\\": " + "\\\"[\\\\\\\"private\\\\\\\", " + "\\\\\\\"shared\\\\\\\"]\\\",\\\"recordTypes\\\":\\\"[\\\\\\\"\\\\\\\"]\\\"}\"}"; + auto ret = cloudServiceImpl_->NotifyDataChange(CloudData::DATA_CHANGE_EVENT_ID, extraData, defaultUserId); + EXPECT_EQ(ret, CloudData::CloudService::SUCCESS); + extraData = "{\"data\":\"{\\\"accountId\\\":\\\"test_cloud_id\\\",\\\"bundleName\\\":\\\"test_cloud_" + "bundleName\\\",\\\"containerName\\\":\\\"test_cloud_database_alias_1\\\", \\\"databaseScopes\\\": " + "\\\"[\\\\\\\"private\\\\\\\", " + "\\\\\\\"shared\\\\\\\"]\\\",\\\"recordTypes\\\":\\\"[\\\\\\\"test_cloud_table_alias\\\\\\\"]\\\"}\"}"; + ret = cloudServiceImpl_->NotifyDataChange(CloudData::DATA_CHANGE_EVENT_ID, extraData, userId); + EXPECT_EQ(ret, CloudData::CloudService::SUCCESS); +} + +/** +* @tc.name: OnReady +* @tc.desc: +* @tc.type: FUNC +* @tc.require: + */ +HWTEST_F(CloudDataTest, OnReady001, TestSize.Level0) +{ + std::string device = "test"; + auto ret = cloudServiceImpl_->OnReady(device); + EXPECT_EQ(ret, CloudData::CloudService::SUCCESS); + ret = cloudServiceImpl_->OnReady(DeviceManagerAdapter::CLOUD_DEVICE_UUID); + EXPECT_EQ(ret, CloudData::CloudService::SUCCESS); +} + +/** +* @tc.name: Offline +* @tc.desc: +* @tc.type: FUNC +* @tc.require: + */ +HWTEST_F(CloudDataTest, Offline001, TestSize.Level0) +{ + std::string device = "test"; + auto ret = cloudServiceImpl_->Offline(device); + EXPECT_EQ(ret, CloudData::CloudService::SUCCESS); + ret = cloudServiceImpl_->Offline(DeviceManagerAdapter::CLOUD_DEVICE_UUID); + EXPECT_EQ(ret, CloudData::CloudService::SUCCESS); +} + +/** +* @tc.name: CloudShare +* @tc.desc: +* @tc.type: FUNC +* @tc.require: + */ +HWTEST_F(CloudDataTest, CloudShare001, TestSize.Level0) +{ + ZLOGI("weisx CloudShare start"); + StoreInfo storeInfo{ OHOS::IPCSkeleton::GetCallingTokenID(), TEST_CLOUD_BUNDLE, TEST_CLOUD_STORE, 0 }; + std::pair> result; + CloudShareEvent::Callback asyncCallback = [&result](int32_t status, std::shared_ptr cursor) { + result.first = status; + result.second = cursor; + }; + auto event = std::make_unique(storeInfo, nullptr, nullptr); + EventCenter::GetInstance().PostEvent(std::move(event)); + auto event1 = std::make_unique(storeInfo, nullptr, asyncCallback); + EventCenter::GetInstance().PostEvent(std::move(event1)); + EXPECT_EQ(result.first, GeneralError::E_ERROR); + auto rdbQuery = std::make_shared(); + auto event2 = std::make_unique(storeInfo, rdbQuery, nullptr); + EventCenter::GetInstance().PostEvent(std::move(event2)); + auto event3 = std::make_unique(storeInfo, rdbQuery, asyncCallback); + EventCenter::GetInstance().PostEvent(std::move(event3)); + EXPECT_EQ(result.first, GeneralError::E_ERROR); +} + +/** +* @tc.name: OnUserChange +* @tc.desc: +* @tc.type: FUNC +* @tc.require: + */ +HWTEST_F(CloudDataTest, OnUserChange001, TestSize.Level0) +{ + constexpr const uint32_t ACCOUNT_DEFAULT = 2; + constexpr const uint32_t ACCOUNT_DELETE = 3; + constexpr const uint32_t ACCOUNT_SWITCHED = 4; + constexpr const uint32_t ACCOUNT_UNLOCKED = 5; + auto ret = cloudServiceImpl_->OnUserChange(ACCOUNT_DEFAULT, "0", "test"); + EXPECT_EQ(ret, GeneralError::E_OK); + ret = cloudServiceImpl_->OnUserChange(ACCOUNT_DELETE, "0", "test"); + EXPECT_EQ(ret, GeneralError::E_OK); + ret = cloudServiceImpl_->OnUserChange(ACCOUNT_SWITCHED, "0", "test"); + EXPECT_EQ(ret, GeneralError::E_OK); + ret = cloudServiceImpl_->OnUserChange(ACCOUNT_UNLOCKED, "0", "test"); + EXPECT_EQ(ret, GeneralError::E_OK); +} + +/** +* @tc.name: DisableCloud +* @tc.desc: +* @tc.type: FUNC +* @tc.require: + */ +HWTEST_F(CloudDataTest, DisableCloud001, TestSize.Level0) +{ + auto ret = cloudServiceImpl_->DisableCloud("test"); + EXPECT_EQ(ret, CloudData::CloudService::INVALID_ARGUMENT); + ret = cloudServiceImpl_->DisableCloud(TEST_CLOUD_ID); + EXPECT_EQ(ret, CloudData::CloudService::SUCCESS); +} + +/** +* @tc.name: ChangeAppSwitch +* @tc.desc: +* @tc.type: FUNC +* @tc.require: + */ +HWTEST_F(CloudDataTest, ChangeAppSwitch, TestSize.Level0) +{ + std::string id = "testId"; + std::string bundleName = "testName"; + auto ret = cloudServiceImpl_->ChangeAppSwitch(id, bundleName, CloudData::CloudService::SWITCH_ON); + EXPECT_EQ(ret, CloudData::CloudService::INVALID_ARGUMENT); + ret = cloudServiceImpl_->ChangeAppSwitch(TEST_CLOUD_ID, bundleName, CloudData::CloudService::SWITCH_ON); + EXPECT_EQ(ret, CloudData::CloudService::INVALID_ARGUMENT); + ret = cloudServiceImpl_->ChangeAppSwitch(TEST_CLOUD_ID, TEST_CLOUD_BUNDLE, CloudData::CloudService::SWITCH_OFF); + EXPECT_EQ(ret, CloudData::CloudService::SUCCESS); +} + +/** +* @tc.name: EnableCloud +* @tc.desc: +* @tc.type: FUNC +* @tc.require: + */ +HWTEST_F(CloudDataTest, EnableCloud, TestSize.Level0) +{ + std::string bundleName = "testName"; + std::map switches; + switches.insert_or_assign(TEST_CLOUD_BUNDLE, CloudData::CloudService::SWITCH_ON); + switches.insert_or_assign(bundleName, CloudData::CloudService::SWITCH_ON); + auto ret = cloudServiceImpl_->EnableCloud(TEST_CLOUD_ID, switches); + EXPECT_EQ(ret, CloudData::CloudService::SUCCESS); +} + +/** +* @tc.name: OnEnableCloud +* @tc.desc: +* @tc.type: FUNC +* @tc.require: + */ +HWTEST_F(CloudDataTest, OnEnableCloud, TestSize.Level0) +{ + MessageParcel reply; + MessageParcel data; + data.WriteInterfaceToken(cloudServiceImpl_->GetDescriptor()); + auto ret = cloudServiceImpl_->OnRemoteRequest(CloudData::CloudService::TRANS_ENABLE_CLOUD, data, reply); + EXPECT_EQ(ret, IPC_STUB_INVALID_DATA_ERR); + data.WriteInterfaceToken(cloudServiceImpl_->GetDescriptor()); + std::string id = "testId"; + std::map switches; + ITypesUtil::Marshal(data, id, switches); + ret = cloudServiceImpl_->OnRemoteRequest(CloudData::CloudService::TRANS_ENABLE_CLOUD, data, reply); + EXPECT_EQ(ret, ERR_NONE); +} + +/** +* @tc.name: OnDisableCloud +* @tc.desc: +* @tc.type: FUNC +* @tc.require: + */ +HWTEST_F(CloudDataTest, OnDisableCloud, TestSize.Level0) +{ + MessageParcel reply; + MessageParcel data; + data.WriteInterfaceToken(cloudServiceImpl_->GetDescriptor()); + auto ret = cloudServiceImpl_->OnRemoteRequest(CloudData::CloudService::TRANS_DISABLE_CLOUD, data, reply); + EXPECT_EQ(ret, IPC_STUB_INVALID_DATA_ERR); + data.WriteInterfaceToken(cloudServiceImpl_->GetDescriptor()); + data.WriteString(TEST_CLOUD_ID); + ret = cloudServiceImpl_->OnRemoteRequest(CloudData::CloudService::TRANS_DISABLE_CLOUD, data, reply); + EXPECT_EQ(ret, ERR_NONE); +} + +/** +* @tc.name: OnChangeAppSwitch +* @tc.desc: +* @tc.type: FUNC +* @tc.require: + */ +HWTEST_F(CloudDataTest, OnChangeAppSwitch, TestSize.Level0) +{ + MessageParcel reply; + MessageParcel data; + data.WriteInterfaceToken(cloudServiceImpl_->GetDescriptor()); + auto ret = cloudServiceImpl_->OnRemoteRequest(CloudData::CloudService::TRANS_CHANGE_APP_SWITCH, data, reply); + EXPECT_EQ(ret, IPC_STUB_INVALID_DATA_ERR); + data.WriteInterfaceToken(cloudServiceImpl_->GetDescriptor()); + data.WriteString(TEST_CLOUD_ID); + data.WriteString(TEST_CLOUD_BUNDLE); + data.WriteInt32(CloudData::CloudService::SWITCH_ON); + ret = cloudServiceImpl_->OnRemoteRequest(CloudData::CloudService::TRANS_CHANGE_APP_SWITCH, data, reply); + EXPECT_EQ(ret, ERR_NONE); +} + +/** +* @tc.name: OnClean +* @tc.desc: +* @tc.type: FUNC +* @tc.require: + */ +HWTEST_F(CloudDataTest, OnClean, TestSize.Level0) +{ + MessageParcel reply; + MessageParcel data; + data.WriteInterfaceToken(cloudServiceImpl_->GetDescriptor()); + auto ret = cloudServiceImpl_->OnRemoteRequest(CloudData::CloudService::TRANS_CLEAN, data, reply); + EXPECT_EQ(ret, IPC_STUB_INVALID_DATA_ERR); + data.WriteInterfaceToken(cloudServiceImpl_->GetDescriptor()); + std::string id = TEST_CLOUD_ID; + std::map actions; + ITypesUtil::Marshal(data, id, actions); + ret = cloudServiceImpl_->OnRemoteRequest(CloudData::CloudService::TRANS_CLEAN, data, reply); + EXPECT_EQ(ret, ERR_NONE); +} + +/** +* @tc.name: OnNotifyDataChange +* @tc.desc: +* @tc.type: FUNC +* @tc.require: + */ +HWTEST_F(CloudDataTest, OnNotifyDataChange, TestSize.Level0) +{ + MessageParcel reply; + MessageParcel data; + data.WriteInterfaceToken(cloudServiceImpl_->GetDescriptor()); + auto ret = cloudServiceImpl_->OnRemoteRequest(CloudData::CloudService::TRANS_NOTIFY_DATA_CHANGE, data, reply); + EXPECT_EQ(ret, IPC_STUB_INVALID_DATA_ERR); + data.WriteInterfaceToken(cloudServiceImpl_->GetDescriptor()); + data.WriteString(TEST_CLOUD_ID); + data.WriteString(TEST_CLOUD_BUNDLE); + ret = cloudServiceImpl_->OnRemoteRequest(CloudData::CloudService::TRANS_NOTIFY_DATA_CHANGE, data, reply); + EXPECT_EQ(ret, ERR_NONE); +} + +/** +* @tc.name: OnNotifyChange +* @tc.desc: +* @tc.type: FUNC +* @tc.require: + */ +HWTEST_F(CloudDataTest, OnNotifyChange, TestSize.Level0) +{ + MessageParcel reply; + MessageParcel data; + data.WriteInterfaceToken(cloudServiceImpl_->GetDescriptor()); + auto ret = cloudServiceImpl_->OnRemoteRequest(CloudData::CloudService::TRANS_NOTIFY_DATA_CHANGE_EXT, data, reply); + EXPECT_EQ(ret, IPC_STUB_INVALID_DATA_ERR); + data.WriteInterfaceToken(cloudServiceImpl_->GetDescriptor()); + data.WriteString(TEST_CLOUD_ID); + data.WriteString(TEST_CLOUD_BUNDLE); + int32_t userId = 100; + data.WriteInt32(userId); + ret = cloudServiceImpl_->OnRemoteRequest(CloudData::CloudService::TRANS_NOTIFY_DATA_CHANGE_EXT, data, reply); + EXPECT_EQ(ret, ERR_NONE); +} + +/** +* @tc.name: OnQueryStatistics +* @tc.desc: +* @tc.type: FUNC +* @tc.require: + */ +HWTEST_F(CloudDataTest, OnQueryStatistics, TestSize.Level0) +{ + MessageParcel reply; + MessageParcel data; + data.WriteInterfaceToken(cloudServiceImpl_->GetDescriptor()); + auto ret = cloudServiceImpl_->OnRemoteRequest(CloudData::CloudService::TRANS_QUERY_STATISTICS, data, reply); + EXPECT_EQ(ret, IPC_STUB_INVALID_DATA_ERR); + data.WriteInterfaceToken(cloudServiceImpl_->GetDescriptor()); + data.WriteString(TEST_CLOUD_ID); + data.WriteString(TEST_CLOUD_BUNDLE); + data.WriteString(TEST_CLOUD_STORE); + ret = cloudServiceImpl_->OnRemoteRequest(CloudData::CloudService::TRANS_QUERY_STATISTICS, data, reply); + EXPECT_EQ(ret, ERR_NONE); +} + +/** +* @tc.name: OnQueryLastSyncInfo +* @tc.desc: +* @tc.type: FUNC +* @tc.require: + */ +HWTEST_F(CloudDataTest, OnQueryLastSyncInfo, TestSize.Level0) +{ + MessageParcel reply; + MessageParcel data; + data.WriteInterfaceToken(cloudServiceImpl_->GetDescriptor()); + auto ret = cloudServiceImpl_->OnRemoteRequest(CloudData::CloudService::TRANS_QUERY_LAST_SYNC_INFO, data, reply); + EXPECT_EQ(ret, IPC_STUB_INVALID_DATA_ERR); + data.WriteInterfaceToken(cloudServiceImpl_->GetDescriptor()); + data.WriteString(TEST_CLOUD_ID); + data.WriteString(TEST_CLOUD_BUNDLE); + data.WriteString(TEST_CLOUD_STORE); + ret = cloudServiceImpl_->OnRemoteRequest(CloudData::CloudService::TRANS_QUERY_LAST_SYNC_INFO, data, reply); + EXPECT_EQ(ret, ERR_NONE); +} + +/** +* @tc.name: OnSetGlobalCloudStrategy +* @tc.desc: +* @tc.type: FUNC +* @tc.require: + */ +HWTEST_F(CloudDataTest, OnSetGlobalCloudStrategy, TestSize.Level0) +{ + MessageParcel reply; + MessageParcel data; + data.WriteInterfaceToken(cloudServiceImpl_->GetDescriptor()); + auto ret = + cloudServiceImpl_->OnRemoteRequest(CloudData::CloudService::TRANS_SET_GLOBAL_CLOUD_STRATEGY, data, reply); + EXPECT_EQ(ret, IPC_STUB_INVALID_DATA_ERR); + data.WriteInterfaceToken(cloudServiceImpl_->GetDescriptor()); + uint32_t strategy = 0; + std::vector values; + ITypesUtil::Marshal(data, strategy, values); + ret = cloudServiceImpl_->OnRemoteRequest(CloudData::CloudService::TRANS_SET_GLOBAL_CLOUD_STRATEGY, data, reply); + EXPECT_EQ(ret, ERR_NONE); +} + +/** +* @tc.name: OnAllocResourceAndShare +* @tc.desc: +* @tc.type: FUNC +* @tc.require: + */ +HWTEST_F(CloudDataTest, OnAllocResourceAndShare, TestSize.Level0) +{ + MessageParcel reply; + MessageParcel data; + data.WriteInterfaceToken(cloudServiceImpl_->GetDescriptor()); + auto ret = cloudServiceImpl_->OnRemoteRequest(CloudData::CloudService::TRANS_ALLOC_RESOURCE_AND_SHARE, data, reply); + EXPECT_EQ(ret, IPC_STUB_INVALID_DATA_ERR); + data.WriteInterfaceToken(cloudServiceImpl_->GetDescriptor()); + std::string storeId = "storeId"; + DistributedRdb::PredicatesMemo predicates; + std::vector columns; + std::vector participants; + ITypesUtil::Marshal(data, storeId, predicates, columns, participants); + ret = cloudServiceImpl_->OnRemoteRequest(CloudData::CloudService::TRANS_ALLOC_RESOURCE_AND_SHARE, data, reply); + EXPECT_EQ(ret, ERR_NONE); +} + +/** +* @tc.name: OnShare +* @tc.desc: +* @tc.type: FUNC +* @tc.require: + */ +HWTEST_F(CloudDataTest, OnShare, TestSize.Level0) +{ + MessageParcel reply; + MessageParcel data; + data.WriteInterfaceToken(cloudServiceImpl_->GetDescriptor()); + auto ret = cloudServiceImpl_->OnRemoteRequest(CloudData::CloudService::TRANS_SHARE, data, reply); + EXPECT_EQ(ret, IPC_STUB_INVALID_DATA_ERR); + data.WriteInterfaceToken(cloudServiceImpl_->GetDescriptor()); + std::string sharingRes; + CloudData::Participants participants; + CloudData::Results results; + ITypesUtil::Marshal(data, sharingRes, participants, results); + ret = cloudServiceImpl_->OnRemoteRequest(CloudData::CloudService::TRANS_SHARE, data, reply); + EXPECT_EQ(ret, ERR_NONE); +} + +/** +* @tc.name: OnUnshare +* @tc.desc: +* @tc.type: FUNC +* @tc.require: + */ +HWTEST_F(CloudDataTest, OnUnshare, TestSize.Level0) +{ + MessageParcel reply; + MessageParcel data; + data.WriteInterfaceToken(cloudServiceImpl_->GetDescriptor()); + auto ret = cloudServiceImpl_->OnRemoteRequest(CloudData::CloudService::TRANS_UNSHARE, data, reply); + EXPECT_EQ(ret, IPC_STUB_INVALID_DATA_ERR); + data.WriteInterfaceToken(cloudServiceImpl_->GetDescriptor()); + std::string sharingRes; + CloudData::Participants participants; + CloudData::Results results; + ITypesUtil::Marshal(data, sharingRes, participants, results); + ret = cloudServiceImpl_->OnRemoteRequest(CloudData::CloudService::TRANS_UNSHARE, data, reply); + EXPECT_EQ(ret, ERR_NONE); +} + +/** +* @tc.name: OnExit +* @tc.desc: +* @tc.type: FUNC +* @tc.require: + */ +HWTEST_F(CloudDataTest, OnExit, TestSize.Level0) +{ + MessageParcel reply; + MessageParcel data; + data.WriteInterfaceToken(cloudServiceImpl_->GetDescriptor()); + auto ret = cloudServiceImpl_->OnRemoteRequest(CloudData::CloudService::TRANS_EXIT, data, reply); + EXPECT_EQ(ret, IPC_STUB_INVALID_DATA_ERR); + data.WriteInterfaceToken(cloudServiceImpl_->GetDescriptor()); + std::string sharingRes; + std::pair result; + ITypesUtil::Marshal(data, sharingRes, result); + ret = cloudServiceImpl_->OnRemoteRequest(CloudData::CloudService::TRANS_EXIT, data, reply); + EXPECT_EQ(ret, ERR_NONE); +} + +/** +* @tc.name: OnChangePrivilege +* @tc.desc: +* @tc.type: FUNC +* @tc.require: + */ +HWTEST_F(CloudDataTest, OnChangePrivilege, TestSize.Level0) +{ + MessageParcel reply; + MessageParcel data; + data.WriteInterfaceToken(cloudServiceImpl_->GetDescriptor()); + auto ret = cloudServiceImpl_->OnRemoteRequest(CloudData::CloudService::TRANS_CHANGE_PRIVILEGE, data, reply); + EXPECT_EQ(ret, IPC_STUB_INVALID_DATA_ERR); + data.WriteInterfaceToken(cloudServiceImpl_->GetDescriptor()); + std::string sharingRes; + CloudData::Participants participants; + CloudData::Results results; + ITypesUtil::Marshal(data, sharingRes, participants, results); + ret = cloudServiceImpl_->OnRemoteRequest(CloudData::CloudService::TRANS_CHANGE_PRIVILEGE, data, reply); + EXPECT_EQ(ret, ERR_NONE); +} + +/** +* @tc.name: OnQuery +* @tc.desc: +* @tc.type: FUNC +* @tc.require: + */ +HWTEST_F(CloudDataTest, OnQuery, TestSize.Level0) +{ + MessageParcel reply; + MessageParcel data; + data.WriteInterfaceToken(cloudServiceImpl_->GetDescriptor()); + auto ret = cloudServiceImpl_->OnRemoteRequest(CloudData::CloudService::TRANS_QUERY, data, reply); + EXPECT_EQ(ret, IPC_STUB_INVALID_DATA_ERR); + data.WriteInterfaceToken(cloudServiceImpl_->GetDescriptor()); + std::string sharingRes; + CloudData::QueryResults results; + ITypesUtil::Marshal(data, sharingRes, results); + ret = cloudServiceImpl_->OnRemoteRequest(CloudData::CloudService::TRANS_QUERY, data, reply); + EXPECT_EQ(ret, ERR_NONE); +} + +/** +* @tc.name: OnQueryByInvitation +* @tc.desc: +* @tc.type: FUNC +* @tc.require: + */ +HWTEST_F(CloudDataTest, OnQueryByInvitation, TestSize.Level0) +{ + MessageParcel reply; + MessageParcel data; + data.WriteInterfaceToken(cloudServiceImpl_->GetDescriptor()); + auto ret = cloudServiceImpl_->OnRemoteRequest(CloudData::CloudService::TRANS_QUERY_BY_INVITATION, data, reply); + EXPECT_EQ(ret, IPC_STUB_INVALID_DATA_ERR); + data.WriteInterfaceToken(cloudServiceImpl_->GetDescriptor()); + std::string invitation; + CloudData::QueryResults results; + ITypesUtil::Marshal(data, invitation, results); + ret = cloudServiceImpl_->OnRemoteRequest(CloudData::CloudService::TRANS_QUERY_BY_INVITATION, data, reply); + EXPECT_EQ(ret, ERR_NONE); +} + +/** +* @tc.name: OnConfirmInvitation +* @tc.desc: +* @tc.type: FUNC +* @tc.require: + */ +HWTEST_F(CloudDataTest, OnConfirmInvitation, TestSize.Level0) +{ + MessageParcel reply; + MessageParcel data; + data.WriteInterfaceToken(cloudServiceImpl_->GetDescriptor()); + auto ret = cloudServiceImpl_->OnRemoteRequest(CloudData::CloudService::TRANS_CONFIRM_INVITATION, data, reply); + EXPECT_EQ(ret, IPC_STUB_INVALID_DATA_ERR); + data.WriteInterfaceToken(cloudServiceImpl_->GetDescriptor()); + std::string invitation; + int32_t confirmation = 0; + std::tuple result; + ITypesUtil::Marshal(data, invitation, confirmation, result); + ret = cloudServiceImpl_->OnRemoteRequest(CloudData::CloudService::TRANS_CONFIRM_INVITATION, data, reply); + EXPECT_EQ(ret, ERR_NONE); +} + +/** +* @tc.name: OnChangeConfirmation +* @tc.desc: +* @tc.type: FUNC +* @tc.require: + */ +HWTEST_F(CloudDataTest, OnChangeConfirmation, TestSize.Level0) +{ + MessageParcel reply; + MessageParcel data; + data.WriteInterfaceToken(cloudServiceImpl_->GetDescriptor()); + auto ret = cloudServiceImpl_->OnRemoteRequest(CloudData::CloudService::TRANS_CHANGE_CONFIRMATION, data, reply); + EXPECT_EQ(ret, IPC_STUB_INVALID_DATA_ERR); + data.WriteInterfaceToken(cloudServiceImpl_->GetDescriptor()); + std::string sharingRes; + int32_t confirmation = 0; + std::pair result; + ITypesUtil::Marshal(data, sharingRes, confirmation, result); + ret = cloudServiceImpl_->OnRemoteRequest(CloudData::CloudService::TRANS_CHANGE_CONFIRMATION, data, reply); + EXPECT_EQ(ret, ERR_NONE); +} + +/** +* @tc.name: OnSetCloudStrategy +* @tc.desc: +* @tc.type: FUNC +* @tc.require: + */ +HWTEST_F(CloudDataTest, OnSetCloudStrategy, TestSize.Level0) +{ + MessageParcel reply; + MessageParcel data; + data.WriteInterfaceToken(cloudServiceImpl_->GetDescriptor()); + auto ret = cloudServiceImpl_->OnRemoteRequest(CloudData::CloudService::TRANS_SET_CLOUD_STRATEGY, data, reply); + EXPECT_EQ(ret, IPC_STUB_INVALID_DATA_ERR); + data.WriteInterfaceToken(cloudServiceImpl_->GetDescriptor()); + uint32_t strategy = 0; + std::vector values; + ITypesUtil::Marshal(data, strategy, values); + ret = cloudServiceImpl_->OnRemoteRequest(CloudData::CloudService::TRANS_SET_CLOUD_STRATEGY, data, reply); + EXPECT_EQ(ret, ERR_NONE); +} + +/** +* @tc.name: SharingUtil001 +* @tc.desc: +* @tc.type: FUNC +* @tc.require: + */ +HWTEST_F(CloudDataTest, SharingUtil001, TestSize.Level0) +{ + auto cfm = CloudData::SharingUtil::Convert(Confirmation::CFM_UNKNOWN); + EXPECT_EQ(cfm, SharingCfm::CFM_UNKNOWN); + cfm = CloudData::SharingUtil::Convert(Confirmation::CFM_ACCEPTED); + EXPECT_EQ(cfm, SharingCfm::CFM_ACCEPTED); + cfm = CloudData::SharingUtil::Convert(Confirmation::CFM_REJECTED); + EXPECT_EQ(cfm, SharingCfm::CFM_REJECTED); + cfm = CloudData::SharingUtil::Convert(Confirmation::CFM_SUSPENDED); + EXPECT_EQ(cfm, SharingCfm::CFM_SUSPENDED); + cfm = CloudData::SharingUtil::Convert(Confirmation::CFM_UNAVAILABLE); + EXPECT_EQ(cfm, SharingCfm::CFM_UNAVAILABLE); + cfm = CloudData::SharingUtil::Convert(Confirmation::CFM_BUTT); + EXPECT_EQ(cfm, SharingCfm::CFM_UNKNOWN); +} + +/** +* @tc.name: SharingUtil002 +* @tc.desc: +* @tc.type: FUNC +* @tc.require: + */ +HWTEST_F(CloudDataTest, SharingUtil002, TestSize.Level0) +{ + auto cfm = CloudData::SharingUtil::Convert(SharingCfm::CFM_UNKNOWN); + EXPECT_EQ(cfm, Confirmation::CFM_UNKNOWN); + cfm = CloudData::SharingUtil::Convert(SharingCfm::CFM_ACCEPTED); + EXPECT_EQ(cfm, Confirmation::CFM_ACCEPTED); + cfm = CloudData::SharingUtil::Convert(SharingCfm::CFM_REJECTED); + EXPECT_EQ(cfm, Confirmation::CFM_REJECTED); + cfm = CloudData::SharingUtil::Convert(SharingCfm::CFM_SUSPENDED); + EXPECT_EQ(cfm, Confirmation::CFM_SUSPENDED); + cfm = CloudData::SharingUtil::Convert(SharingCfm::CFM_UNAVAILABLE); + EXPECT_EQ(cfm, Confirmation::CFM_UNAVAILABLE); + cfm = CloudData::SharingUtil::Convert(SharingCfm::CFM_BUTT); + EXPECT_EQ(cfm, Confirmation::CFM_UNKNOWN); +} + +/** +* @tc.name: SharingUtil003 +* @tc.desc: +* @tc.type: FUNC +* @tc.require: + */ +HWTEST_F(CloudDataTest, SharingUtil003, TestSize.Level0) +{ + auto status = CloudData::SharingUtil::Convert(CenterCode::IPC_ERROR); + EXPECT_EQ(status, Status::IPC_ERROR); + status = CloudData::SharingUtil::Convert(CenterCode::NOT_SUPPORT); + EXPECT_EQ(status, Status::SUCCESS); +} + +/** +* @tc.name: SharingUtil004 +* @tc.desc: +* @tc.type: FUNC +* @tc.require: + */ +HWTEST_F(CloudDataTest, SharingUtil004, TestSize.Level0) +{ + auto status = CloudData::SharingUtil::Convert(GenErr::E_OK); + EXPECT_EQ(status, Status::SUCCESS); + status = CloudData::SharingUtil::Convert(GenErr::E_ERROR); + EXPECT_EQ(status, Status::ERROR); + status = CloudData::SharingUtil::Convert(GenErr::E_INVALID_ARGS); + EXPECT_EQ(status, Status::INVALID_ARGUMENT); + status = CloudData::SharingUtil::Convert(GenErr::E_BLOCKED_BY_NETWORK_STRATEGY); + EXPECT_EQ(status, Status::STRATEGY_BLOCKING); + status = CloudData::SharingUtil::Convert(GenErr::E_CLOUD_DISABLED); + EXPECT_EQ(status, Status::CLOUD_DISABLE); + status = CloudData::SharingUtil::Convert(GenErr::E_NETWORK_ERROR); + EXPECT_EQ(status, Status::NETWORK_ERROR); + status = CloudData::SharingUtil::Convert(GenErr::E_BUSY); + EXPECT_EQ(status, Status::ERROR); +} + +/** +* @tc.name: DoCloudSync +* @tc.desc: Test the executor_ uninitialized and initialized scenarios +* @tc.type: FUNC +* @tc.require: + */ +HWTEST_F(CloudDataTest, DoCloudSync, TestSize.Level0) +{ + int32_t user = 100; + CloudData::SyncManager sync; + CloudData::SyncManager::SyncInfo info(user); + auto ret = sync.DoCloudSync(info); + EXPECT_EQ(ret, GenErr::E_NOT_INIT); + ret = sync.StopCloudSync(user); + EXPECT_EQ(ret, GenErr::E_NOT_INIT); + size_t max = 12; + size_t min = 5; + sync.executor_ = std::make_shared(max, min); + ret = sync.DoCloudSync(info); + EXPECT_EQ(ret, GenErr::E_OK); + int32_t invalidUser = -1; + sync.StopCloudSync(invalidUser); + ret = sync.StopCloudSync(user); + EXPECT_EQ(ret, GenErr::E_OK); +} + +/** +* @tc.name: GetPostEventTask +* @tc.desc: Test the interface to verify the package name and table name +* @tc.type: FUNC +* @tc.require: + */ +HWTEST_F(CloudDataTest, GetPostEventTask, TestSize.Level0) +{ + std::vector schemas; + schemaMeta_.databases[0].name = "test"; + schemas.push_back(schemaMeta_); + schemaMeta_.bundleName = "test"; + schemas.push_back(schemaMeta_); + + int32_t user = 100; + CloudData::SyncManager::SyncInfo info(user); + std::vector value; + info.tables_.insert_or_assign(TEST_CLOUD_STORE, value); + + CloudData::SyncManager sync; + auto task = sync.GetPostEventTask(schemas, cloudInfo_, info, true); + auto ret = task(); + EXPECT_TRUE(ret); +} + +/** +* @tc.name: GetRetryer +* @tc.desc: Test the input parameters of different interfaces +* @tc.type: FUNC +* @tc.require: + */ +HWTEST_F(CloudDataTest, GetRetryer, TestSize.Level0) +{ + int32_t user = 100; + CloudData::SyncManager::SyncInfo info(user); + CloudData::SyncManager sync; + CloudData::SyncManager::Duration duration; + auto ret = sync.GetRetryer(CloudData::SyncManager::RETRY_TIMES, info)(duration, E_OK, E_OK); + EXPECT_TRUE(ret); + ret = sync.GetRetryer(CloudData::SyncManager::RETRY_TIMES, info)(duration, E_SYNC_TASK_MERGED, E_SYNC_TASK_MERGED); + EXPECT_TRUE(ret); + ret = sync.GetRetryer(0, info)(duration, E_OK, E_OK); + EXPECT_TRUE(ret); + ret = sync.GetRetryer(0, info)(duration, E_SYNC_TASK_MERGED, E_SYNC_TASK_MERGED); + EXPECT_TRUE(ret); +} + +/** +* @tc.name: GetCallback +* @tc.desc: Test the processing logic of different progress callbacks +* @tc.type: FUNC +* @tc.require: + */ +HWTEST_F(CloudDataTest, GetCallback, TestSize.Level0) +{ + int32_t user = 100; + CloudData::SyncManager::SyncInfo info(user); + CloudData::SyncManager sync; + DistributedData::GenDetails result; + StoreInfo storeInfo; + storeInfo.user = user; + storeInfo.bundleName = "testBundleName"; + int32_t triggerMode = MODE_DEFAULT; + GenAsync async = nullptr; + sync.GetCallback(async, storeInfo, triggerMode)(result); + int32_t process = 0; + async = [&process](const GenDetails &details) { process = details.begin()->second.progress; }; + GenProgressDetail detail; + detail.progress = GenProgress::SYNC_IN_PROGRESS; + result.insert_or_assign("test", detail); + sync.GetCallback(async, storeInfo, triggerMode)(result); + EXPECT_EQ(process, GenProgress::SYNC_IN_PROGRESS); + detail.progress = GenProgress::SYNC_FINISH; + result.insert_or_assign("test", detail); + storeInfo.user = -1; + sync.GetCallback(async, storeInfo, triggerMode)(result); + storeInfo.user = user; + sync.GetCallback(async, storeInfo, triggerMode)(result); + EXPECT_EQ(process, GenProgress::SYNC_FINISH); +} + +/** +* @tc.name: GetInterval +* @tc.desc: Test the Interval transformation logic of the interface +* @tc.type: FUNC +* @tc.require: + */ +HWTEST_F(CloudDataTest, GetInterval, TestSize.Level0) +{ + CloudData::SyncManager sync; + + auto ret = sync.GetInterval(E_LOCKED_BY_OTHERS); + EXPECT_EQ(ret, CloudData::SyncManager::LOCKED_INTERVAL); + ret = sync.GetInterval(E_BUSY); + EXPECT_EQ(ret, CloudData::SyncManager::BUSY_INTERVAL); + ret = sync.GetInterval(E_OK); + EXPECT_EQ(ret, CloudData::SyncManager::RETRY_INTERVAL); +} + +/** +* @tc.name: GetCloudSyncInfo +* @tc.desc: Test get cloudInfo +* @tc.type: FUNC +* @tc.require: + */ +HWTEST_F(CloudDataTest, GetCloudSyncInfo, TestSize.Level0) +{ + CloudData::SyncManager sync; + CloudInfo cloud; + cloud.user = cloudInfo_.user; + cloud.enableCloud = false; + CloudData::SyncManager::SyncInfo info(cloudInfo_.user); + MetaDataManager::GetInstance().DelMeta(cloudInfo_.GetKey(), true); + info.bundleName_ = "test"; + auto ret = sync.GetCloudSyncInfo(info, cloud); + EXPECT_TRUE(!ret.empty()); +} + +/** +* @tc.name: RetryCallback +* @tc.desc: Test the retry logic +* @tc.type: FUNC +* @tc.require: + */ +HWTEST_F(CloudDataTest, RetryCallback, TestSize.Level0) +{ + CloudData::SyncManager sync; + StoreInfo storeInfo; + int32_t retCode = -1; + CloudData::SyncManager::Retryer retry = [&retCode](CloudData::SyncManager::Duration interval, int32_t code, + int32_t dbCode) { + retCode = code; + return true; + }; + DistributedData::GenDetails result; + auto task = sync.RetryCallback(storeInfo, retry, MODE_DEFAULT); + task(result); + GenProgressDetail detail; + detail.progress = GenProgress::SYNC_IN_PROGRESS; + detail.code = 100; + result.insert_or_assign("test", detail); + task = sync.RetryCallback(storeInfo, retry, MODE_DEFAULT); + task(result); + EXPECT_EQ(retCode, detail.code); +} + +/** +* @tc.name: UpdateCloudInfoFromServer +* @tc.desc: Test updating cloudinfo from the server +* @tc.type: FUNC +* @tc.require: + */ +HWTEST_F(CloudDataTest, UpdateCloudInfoFromServer, TestSize.Level0) +{ + auto ret = cloudServiceImpl_->UpdateCloudInfoFromServer(cloudInfo_.user); + EXPECT_EQ(ret, E_OK); +} + +/** +* @tc.name: GetCloudInfo +* @tc.desc: Test get cloudInfo +* @tc.type: FUNC +* @tc.require: + */ +HWTEST_F(CloudDataTest, GetCloudInfo, TestSize.Level0) +{ + MetaDataManager::GetInstance().DelMeta(cloudInfo_.GetKey(), true); + auto ret = cloudServiceImpl_->GetCloudInfo(cloudInfo_.user); + EXPECT_EQ(ret.first, CloudData::SUCCESS); +} + +/** +* @tc.name: SubTask +* @tc.desc: Test the subtask execution logic +* @tc.type: FUNC +* @tc.require: + */ +HWTEST_F(CloudDataTest, SubTask, TestSize.Level0) +{ + DistributedData::Subscription sub; + cloudServiceImpl_->InitSubTask(sub, 0); + MetaDataManager::GetInstance().LoadMeta(Subscription::GetKey(cloudInfo_.user), sub, true); + cloudServiceImpl_->InitSubTask(sub, 0); + int32_t userId = 0; + CloudData::CloudServiceImpl::Task task = [&userId]() { userId = cloudInfo_.user; }; + cloudServiceImpl_->GenSubTask(task, cloudInfo_.user)(); + EXPECT_EQ(userId, cloudInfo_.user); +} + +/** +* @tc.name: ConvertCursor +* @tc.desc: Test the cursor conversion logic when the ResultSet is empty and non-null +* @tc.type: FUNC +* @tc.require: + */ +HWTEST_F(CloudDataTest, ConvertCursor, TestSize.Level0) +{ + std::map entry; + entry.insert_or_assign("test", "entry"); + auto resultSet = std::make_shared(1, entry); + auto cursor = std::make_shared(resultSet); + auto result = cloudServiceImpl_->ConvertCursor(cursor); + EXPECT_TRUE(!result.empty()); + auto resultSet1 = std::make_shared(); + auto cursor1 = std::make_shared(resultSet1); + auto result1 = cloudServiceImpl_->ConvertCursor(cursor1); + EXPECT_TRUE(result1.empty()); +} + +/** +* @tc.name: GetDbInfoFromExtraData +* @tc.desc: Test the GetDbInfoFromExtraData function input parameters of different parameters +* @tc.type: FUNC +* @tc.require: + */ +HWTEST_F(CloudDataTest, GetDbInfoFromExtraData, TestSize.Level0) +{ + SchemaMeta::Database database; + database.name = TEST_CLOUD_STORE; + database.alias = TEST_CLOUD_DATABASE_ALIAS_1; + + SchemaMeta schemaMeta; + schemaMeta.databases.push_back(database); + + SchemaMeta::Table table; + table.name = "test_cloud_table_name"; + table.alias = "test_cloud_table_alias"; + database.tables.push_back(table); + SchemaMeta::Table table1; + table1.name = "test_cloud_table_name1"; + table1.alias = "test_cloud_table_alias1"; + table1.sharedTableName = "test_share_table_name1"; + database.tables.emplace_back(table1); + + database.alias = TEST_CLOUD_DATABASE_ALIAS_2; + schemaMeta.databases.push_back(database); + + ExtraData extraData; + extraData.info.containerName = TEST_CLOUD_DATABASE_ALIAS_2; + auto result = cloudServiceImpl_->GetDbInfoFromExtraData(extraData, schemaMeta); + EXPECT_EQ(result.begin()->first, TEST_CLOUD_STORE); + + std::string tableName = "test_cloud_table_alias2"; + extraData.info.tables.emplace_back(tableName); + result = cloudServiceImpl_->GetDbInfoFromExtraData(extraData, schemaMeta); + EXPECT_EQ(result.begin()->first, TEST_CLOUD_STORE); + + std::string tableName1 = "test_cloud_table_alias1"; + extraData.info.tables.emplace_back(tableName1); + extraData.info.scopes.emplace_back(DistributedData::ExtraData::SHARED_TABLE); + result = cloudServiceImpl_->GetDbInfoFromExtraData(extraData, schemaMeta); + EXPECT_EQ(result.begin()->first, TEST_CLOUD_STORE); +} + +/** +* @tc.name: QueryTableStatistic +* @tc.desc: Test the QueryTableStatistic function input parameters of different parameters +* @tc.type: FUNC +* @tc.require: + */ +HWTEST_F(CloudDataTest, QueryTableStatistic, TestSize.Level0) +{ + auto store = std::make_shared(); + if (store != nullptr) { + std::map entry = { { "inserted", "TEST" }, { "updated", "TEST" }, { "normal", "TEST" } }; + store->MakeCursor(entry); + } + auto [ret, result] = cloudServiceImpl_->QueryTableStatistic("test", store); + EXPECT_TRUE(ret); + if (store != nullptr) { + std::map entry = { { "Test", 1 } }; + store->MakeCursor(entry); + } + std::tie(ret, result) = cloudServiceImpl_->QueryTableStatistic("test", store); + EXPECT_TRUE(ret); + + if (store != nullptr) { + store->cursor_ = nullptr; + } + std::tie(ret, result) = cloudServiceImpl_->QueryTableStatistic("test", store); + EXPECT_FALSE(ret); +} + +/** +* @tc.name: GetSchemaMeta +* @tc.desc: Test the GetSchemaMeta function input parameters of different parameters +* @tc.type: FUNC +* @tc.require: + */ +HWTEST_F(CloudDataTest, GetSchemaMeta, TestSize.Level0) +{ + int32_t userId = 101; + int32_t instanceId = 0; + CloudInfo cloudInfo; + cloudInfo.user = userId; + cloudInfo.id = TEST_CLOUD_ID; + cloudInfo.enableCloud = true; + + CloudInfo::AppInfo appInfo; + appInfo.bundleName = TEST_CLOUD_BUNDLE; + appInfo.appId = TEST_CLOUD_APPID; + appInfo.version = 1; + appInfo.cloudSwitch = true; + + cloudInfo.apps[TEST_CLOUD_BUNDLE] = std::move(appInfo); + MetaDataManager::GetInstance().SaveMeta(cloudInfo.GetKey(), cloudInfo, true); + std::string bundleName = "testName"; + auto [status, meta] = cloudServiceImpl_->GetSchemaMeta(userId, bundleName, instanceId); + EXPECT_EQ(status, CloudData::CloudService::ERROR); + bundleName = TEST_CLOUD_BUNDLE; + DistributedData::SchemaMeta schemeMeta; + schemeMeta.bundleName = TEST_CLOUD_BUNDLE; + schemeMeta.metaVersion = DistributedData::SchemaMeta::CURRENT_VERSION + 1; + MetaDataManager::GetInstance().SaveMeta(cloudInfo.GetSchemaKey(TEST_CLOUD_BUNDLE, instanceId), schemeMeta, true); + std::tie(status, meta) = cloudServiceImpl_->GetSchemaMeta(userId, bundleName, instanceId); + EXPECT_EQ(status, CloudData::CloudService::ERROR); + schemeMeta.metaVersion = DistributedData::SchemaMeta::CURRENT_VERSION; + MetaDataManager::GetInstance().SaveMeta(cloudInfo.GetSchemaKey(TEST_CLOUD_BUNDLE, instanceId), schemeMeta, true); + std::tie(status, meta) = cloudServiceImpl_->GetSchemaMeta(userId, bundleName, instanceId); + EXPECT_EQ(status, CloudData::CloudService::SUCCESS); + EXPECT_EQ(meta.metaVersion, DistributedData::SchemaMeta::CURRENT_VERSION); + MetaDataManager::GetInstance().DelMeta(cloudInfo.GetSchemaKey(TEST_CLOUD_BUNDLE, instanceId), true); + MetaDataManager::GetInstance().DelMeta(cloudInfo.GetKey(), true); +} + +/** +* @tc.name: GetAppSchemaFromServer +* @tc.desc: Test the GetAppSchemaFromServer function input parameters of different parameters +* @tc.type: FUNC +* @tc.require: + */ +HWTEST_F(CloudDataTest, GetAppSchemaFromServer, TestSize.Level0) +{ + int32_t userId = CloudServerMock::INVALID_USER_ID; + std::string bundleName; + DeviceManagerAdapter::GetInstance().SetNet(DeviceManagerAdapter::NONE); + DeviceManagerAdapter::GetInstance().expireTime_ = + std::chrono::duration_cast(std::chrono::steady_clock::now().time_since_epoch()) + .count() + + 1000; + auto [status, meta] = cloudServiceImpl_->GetAppSchemaFromServer(userId, bundleName); + EXPECT_EQ(status, CloudData::CloudService::NETWORK_ERROR); + DeviceManagerAdapter::GetInstance().SetNet(DeviceManagerAdapter::WIFI); + std::tie(status, meta) = cloudServiceImpl_->GetAppSchemaFromServer(userId, bundleName); + EXPECT_EQ(status, CloudData::CloudService::SCHEMA_INVALID); + userId = 100; + std::tie(status, meta) = cloudServiceImpl_->GetAppSchemaFromServer(userId, bundleName); + EXPECT_EQ(status, CloudData::CloudService::SCHEMA_INVALID); + bundleName = TEST_CLOUD_BUNDLE; + std::tie(status, meta) = cloudServiceImpl_->GetAppSchemaFromServer(userId, bundleName); + EXPECT_EQ(status, CloudData::CloudService::SUCCESS); + EXPECT_EQ(meta.bundleName, schemaMeta_.bundleName); +} + +/** +* @tc.name: OnAppUninstall +* @tc.desc: Test the OnAppUninstall function delete the subscription data +* @tc.type: FUNC +* @tc.require: + */ +HWTEST_F(CloudDataTest, OnAppUninstall, TestSize.Level0) +{ + ZLOGI("weisx test OnAppUninstall 111"); + CloudData::CloudServiceImpl::CloudStatic cloudStatic; + int32_t userId = 1001; + Subscription sub; + sub.expiresTime.insert_or_assign(TEST_CLOUD_BUNDLE, 0); + MetaDataManager::GetInstance().SaveMeta(Subscription::GetKey(userId), sub, true); + CloudInfo cloudInfo; + cloudInfo.user = userId; + CloudInfo::AppInfo appInfo; + cloudInfo.apps.insert_or_assign(TEST_CLOUD_BUNDLE, appInfo); + MetaDataManager::GetInstance().SaveMeta(cloudInfo.GetKey(), cloudInfo, true); + int32_t index = 1; + auto ret = cloudStatic.OnAppUninstall(TEST_CLOUD_BUNDLE, userId, index); + EXPECT_EQ(ret, E_OK); + Subscription sub1; + EXPECT_TRUE(MetaDataManager::GetInstance().LoadMeta(Subscription::GetKey(userId), sub1, true)); + EXPECT_EQ(sub1.expiresTime.size(), 0); +} + +/** +* @tc.name: GetCloudInfo +* @tc.desc: Test the GetCloudInfo with invalid parameters +* @tc.type: FUNC +* @tc.require: + */ +HWTEST_F(CloudDataTest, GetCloudInfo001, TestSize.Level0) +{ + ZLOGI("weisx test OnAppUninstall 111"); + int32_t userId = 1000; + auto [status, cloudInfo] = cloudServiceImpl_->GetCloudInfo(userId); + EXPECT_EQ(status, CloudData::CloudService::ERROR); + DeviceManagerAdapter::GetInstance().SetNet(DeviceManagerAdapter::NONE); + DeviceManagerAdapter::GetInstance().expireTime_ = + std::chrono::duration_cast(std::chrono::steady_clock::now().time_since_epoch()) + .count() + + 1000; + MetaDataManager::GetInstance().DelMeta(cloudInfo_.GetKey(), true); + std::tie(status, cloudInfo) = cloudServiceImpl_->GetCloudInfo(cloudInfo_.user); + EXPECT_EQ(status, CloudData::CloudService::NETWORK_ERROR); + DeviceManagerAdapter::GetInstance().SetNet(DeviceManagerAdapter::WIFI); +} + +/** +* @tc.name: PreShare +* @tc.desc: Test the PreShare with invalid parameters +* @tc.type: FUNC +* @tc.require: + */ +HWTEST_F(CloudDataTest, PreShare, TestSize.Level0) +{ + int32_t userId = 1000; + StoreInfo info; + info.instanceId = 0; + info.bundleName = TEST_CLOUD_BUNDLE; + info.storeName = TEST_CLOUD_BUNDLE; + info.user = userId; + StoreMetaData meta(info); + meta.deviceId = DmAdapter::GetInstance().GetLocalDevice().uuid; + MetaDataManager::GetInstance().SaveMeta(meta.GetKey(), meta, true); + DistributedRdb::RdbQuery query; + auto [status, cursor] = cloudServiceImpl_->PreShare(info, query); + EXPECT_EQ(status, GeneralError::E_ERROR); +} + +/** +* @tc.name: InitSubTask +* @tc.desc: Test the InitSubTask with invalid parameters +* @tc.type: FUNC +* @tc.require: + */ +HWTEST_F(CloudDataTest, InitSubTask, TestSize.Level0) +{ + uint64_t minInterval = 0; + uint64_t expire = 24 * 60 * 60 * 1000; // 24hours, ms + ExecutorPool::TaskId taskId = 100; + Subscription sub; + sub.expiresTime.insert_or_assign(TEST_CLOUD_BUNDLE, expire); + std::shared_ptr executor = std::move(cloudServiceImpl_->executor_); + cloudServiceImpl_->executor_ = nullptr; + cloudServiceImpl_->InitSubTask(sub, minInterval); + EXPECT_EQ(sub.GetMinExpireTime(), expire); + cloudServiceImpl_->executor_ = std::move(executor); + cloudServiceImpl_->subTask_ = taskId; + cloudServiceImpl_->InitSubTask(sub, minInterval); + EXPECT_NE(cloudServiceImpl_->subTask_, taskId); + cloudServiceImpl_->subTask_ = taskId; + cloudServiceImpl_->expireTime_ = 0; + cloudServiceImpl_->InitSubTask(sub, minInterval); + EXPECT_EQ(cloudServiceImpl_->subTask_, taskId); + cloudServiceImpl_->subTask_ = ExecutorPool::INVALID_TASK_ID; + cloudServiceImpl_->InitSubTask(sub, minInterval); + EXPECT_NE(cloudServiceImpl_->subTask_, ExecutorPool::INVALID_TASK_ID); +} + +/** +* @tc.name: DoSubscribe +* @tc.desc: Test DoSubscribe functions with invalid parameter. +* @tc.type: FUNC +* @tc.require: + */ +HWTEST_F(CloudDataTest, DoSubscribe, TestSize.Level0) +{ + ZLOGI("CloudServiceImplTest DoSubscribe start"); + Subscription sub; + sub.userId = cloudInfo_.user; + MetaDataManager::GetInstance().SaveMeta(sub.GetKey(), sub, true); + int user = cloudInfo_.user; + auto status = cloudServiceImpl_->DoSubscribe(user); + EXPECT_FALSE(status); + sub.id = "testId"; + MetaDataManager::GetInstance().SaveMeta(sub.GetKey(), sub, true); + status = cloudServiceImpl_->DoSubscribe(user); + EXPECT_FALSE(status); + sub.id = TEST_CLOUD_APPID; + MetaDataManager::GetInstance().SaveMeta(sub.GetKey(), sub, true); + status = cloudServiceImpl_->DoSubscribe(user); + EXPECT_FALSE(status); + MetaDataManager::GetInstance().DelMeta(cloudInfo_.GetKey(), true); + status = cloudServiceImpl_->DoSubscribe(user); + EXPECT_FALSE(status); +} } // namespace DistributedDataTest } // namespace OHOS::Test \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/test/cloud_service_impl_test.cpp b/datamgr_service/services/distributeddataservice/service/test/cloud_service_impl_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..16c3bc7a1499af99c1ebe2c451b0f038f0fb8d2b --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/test/cloud_service_impl_test.cpp @@ -0,0 +1,488 @@ +/* +* Copyright (c) 2024 Huawei Device Co., Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +#define LOG_TAG "CloudServiceImplTest" +#include "cloud_service_impl.h" + +#include +#include + +#include "accesstoken_kit.h" +#include "account/account_delegate.h" +#include "bootstrap.h" +#include "checker_mock.h" +#include "cloud/change_event.h" +#include "cloud/cloud_event.h" +#include "cloud/cloud_server.h" +#include "cloud/cloud_share_event.h" +#include "cloud/schema_meta.h" +#include "cloud_types.h" +#include "cloud_types_util.h" +#include "cloud_value_util.h" +#include "communicator/device_manager_adapter.h" +#include "device_matrix.h" +#include "eventcenter/event_center.h" +#include "feature/feature_system.h" +#include "ipc_skeleton.h" +#include "log_print.h" +#include "metadata/meta_data_manager.h" +#include "metadata/store_meta_data.h" +#include "metadata/store_meta_data_local.h" +#include "mock/db_store_mock.h" +#include "mock/general_store_mock.h" +#include "rdb_query.h" +#include "rdb_service.h" +#include "rdb_service_impl.h" +#include "rdb_types.h" +#include "store/auto_cache.h" +#include "store/store_info.h" +#include "token_setproc.h" + +using namespace testing::ext; +using namespace OHOS::DistributedData; +using namespace OHOS::Security::AccessToken; +using Confirmation = OHOS::CloudData::Confirmation; +using Status = OHOS::CloudData::CloudService::Status; + +namespace OHOS::Test { +namespace DistributedDataTest { +static constexpr const char *TEST_CLOUD_BUNDLE = "test_cloud_bundleName"; +static constexpr const char *TEST_CLOUD_APPID = "test_cloud_appid"; +static constexpr const char *TEST_CLOUD_STORE = "test_cloud_store"; +static constexpr const char *TEST_CLOUD_DATABASE_ALIAS_1 = "test_cloud_database_alias_1"; +class CloudServiceImplTest : public testing::Test { +public: + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); + + static std::shared_ptr cloudServiceImpl_; +}; +std::shared_ptr CloudServiceImplTest::cloudServiceImpl_ = + std::make_shared(); + +void CloudServiceImplTest::SetUpTestCase(void) +{ + size_t max = 12; + size_t min = 5; + auto executor = std::make_shared(max, min); + DeviceManagerAdapter::GetInstance().Init(executor); +} + +void CloudServiceImplTest::TearDownTestCase() +{ +} + +void CloudServiceImplTest::SetUp() +{ +} + +void CloudServiceImplTest::TearDown() +{ +} + +/** +* @tc.name: EnableCloud001 +* @tc.desc: Test EnableCloud functions with user is invalid. +* @tc.type: FUNC +* @tc.require: + */ +HWTEST_F(CloudServiceImplTest, EnableCloud001, TestSize.Level0) +{ + ZLOGI("CloudServiceImplTest EnableCloud001 start"); + std::map switches; + switches.insert_or_assign(TEST_CLOUD_BUNDLE, CloudData::CloudService::SWITCH_ON); + auto status = cloudServiceImpl_->EnableCloud(TEST_CLOUD_APPID, switches); + EXPECT_EQ(status, CloudData::CloudService::ERROR); +} + +/** +* @tc.name: DisableCloud001 +* @tc.desc: Test DisableCloud functions with user is invalid. +* @tc.type: FUNC +* @tc.require: + */ +HWTEST_F(CloudServiceImplTest, DisableCloud001, TestSize.Level0) +{ + ZLOGI("CloudServiceImplTest DisableCloud001 start"); + auto status = cloudServiceImpl_->DisableCloud(TEST_CLOUD_APPID); + EXPECT_EQ(status, CloudData::CloudService::ERROR); +} + +/** +* @tc.name: ChangeAppSwitch001 +* @tc.desc: Test ChangeAppSwitch functions with user is invalid. +* @tc.type: FUNC +* @tc.require: + */ +HWTEST_F(CloudServiceImplTest, ChangeAppSwitch001, TestSize.Level0) +{ + ZLOGI("CloudServiceImplTest ChangeAppSwitch001 start"); + auto status = + cloudServiceImpl_->ChangeAppSwitch(TEST_CLOUD_APPID, TEST_CLOUD_BUNDLE, CloudData::CloudService::SWITCH_ON); + EXPECT_EQ(status, CloudData::CloudService::ERROR); +} + +/** +* @tc.name: Clean001 +* @tc.desc: Test Clean functions with user is invalid. +* @tc.type: FUNC +* @tc.require: + */ +HWTEST_F(CloudServiceImplTest, Clean001, TestSize.Level0) +{ + ZLOGI("CloudServiceImplTest Clean001 start"); + std::map actions; + actions.insert_or_assign(TEST_CLOUD_BUNDLE, CloudData::CloudService::SWITCH_ON); + auto status = cloudServiceImpl_->Clean(TEST_CLOUD_APPID, actions); + EXPECT_EQ(status, CloudData::CloudService::ERROR); +} + +/** +* @tc.name: NotifyDataChange001 +* @tc.desc: Test the EnableCloud function in case it doesn't get cloudInfo. +* @tc.type: FUNC +* @tc.require: + */ +HWTEST_F(CloudServiceImplTest, NotifyDataChange001, TestSize.Level0) +{ + ZLOGI("CloudServiceImplTest NotifyDataChange001 start"); + auto status = cloudServiceImpl_->NotifyDataChange(TEST_CLOUD_APPID, TEST_CLOUD_BUNDLE); + EXPECT_EQ(status, CloudData::CloudService::INVALID_ARGUMENT); +} + +/** +* @tc.name: ExecuteStatistics001 +* @tc.desc: Test the ExecuteStatistics function if the package name does not support CloudSync. +* @tc.type: FUNC +* @tc.require: + */ +HWTEST_F(CloudServiceImplTest, ExecuteStatistics001, TestSize.Level0) +{ + ZLOGI("CloudServiceImplTest ExecuteStatistics001 start"); + CloudInfo cloudInfo; + CloudInfo::AppInfo appInfo; + appInfo.bundleName = TEST_CLOUD_BUNDLE; + cloudInfo.apps[TEST_CLOUD_BUNDLE] = std::move(appInfo); + SchemaMeta::Database database; + database.name = TEST_CLOUD_STORE; + database.alias = TEST_CLOUD_DATABASE_ALIAS_1; + SchemaMeta schemaMeta; + schemaMeta.bundleName = "testBundle"; + schemaMeta.databases.emplace_back(database); + auto result = cloudServiceImpl_->ExecuteStatistics("", cloudInfo, schemaMeta); + EXPECT_TRUE(result.empty()); +} + +/** +* @tc.name: QueryStatistics001 +* @tc.desc: When metadata is not supported store test the QueryStatistics function. +* @tc.type: FUNC +* @tc.require: + */ +HWTEST_F(CloudServiceImplTest, QueryStatistics001, TestSize.Level0) +{ + ZLOGI("CloudServiceImplTest QueryStatistics start"); + StoreMetaData metaData; + metaData.storeType = -1; + DistributedData::Database database; + auto result = cloudServiceImpl_->QueryStatistics(metaData, database); + EXPECT_TRUE(result.empty()); +} + +/** +* @tc.name: QueryLastSyncInfo001 +* @tc.desc: Test QueryLastSyncInfo functions with invalid parameter. +* @tc.type: FUNC +* @tc.require: + */ +HWTEST_F(CloudServiceImplTest, QueryLastSyncInfo001, TestSize.Level0) +{ + ZLOGI("CloudServiceImplTest QueryLastSyncInfo start"); + auto [status, result] = cloudServiceImpl_->QueryLastSyncInfo(TEST_CLOUD_APPID, TEST_CLOUD_BUNDLE, TEST_CLOUD_STORE); + EXPECT_EQ(status, CloudData::CloudService::ERROR); + EXPECT_TRUE(result.empty()); +} + +/** +* @tc.name: OnBind001 +* @tc.desc: Test OnBind functions with invalid parameter. +* @tc.type: FUNC +* @tc.require: + */ +HWTEST_F(CloudServiceImplTest, OnBind001, TestSize.Level0) +{ + ZLOGI("CloudServiceImplTest OnBind001 start"); + auto status = cloudServiceImpl_->OnBind({}); + EXPECT_EQ(status, GeneralError::E_INVALID_ARGS); +} + +/** +* @tc.name: UpdateSchema001 +* @tc.desc: Test UpdateSchema001 functions with invalid parameter. +* @tc.type: FUNC +* @tc.require: + */ +HWTEST_F(CloudServiceImplTest, UpdateSchema001, TestSize.Level0) +{ + ZLOGI("CloudServiceImplTest UpdateSchema001 start"); + int user = -1; + auto status = cloudServiceImpl_->UpdateSchema(user); + EXPECT_FALSE(status); +} + +/** +* @tc.name: GetAppSchemaFromServer001 +* @tc.desc: Test GetAppSchemaFromServer functions not support CloudService. +* @tc.type: FUNC +* @tc.require: + */ +HWTEST_F(CloudServiceImplTest, GetAppSchemaFromServer001, TestSize.Level0) +{ + ZLOGI("CloudServiceImplTest GetAppSchemaFromServer001 start"); + DeviceManagerAdapter::GetInstance().SetNet(DeviceManagerAdapter::WIFI); + int user = -1; + auto [status, result] = cloudServiceImpl_->GetAppSchemaFromServer(user, TEST_CLOUD_BUNDLE); + EXPECT_EQ(status, CloudData::CloudService::SERVER_UNAVAILABLE); +} + +/** +* @tc.name: GetCloudInfoFromServer001 +* @tc.desc: Test GetCloudInfoFromServer functions not support CloudService. +* @tc.type: FUNC +* @tc.require: + */ +HWTEST_F(CloudServiceImplTest, GetCloudInfoFromServer001, TestSize.Level0) +{ + ZLOGI("CloudServiceImplTest GetCloudInfoFromServer001 start"); + DeviceManagerAdapter::GetInstance().SetNet(DeviceManagerAdapter::WIFI); + int user = -1; + auto [status, result] = cloudServiceImpl_->GetCloudInfoFromServer(user); + EXPECT_EQ(status, CloudData::CloudService::SERVER_UNAVAILABLE); +} + +/** +* @tc.name: ReleaseUserInfo001 +* @tc.desc: Test ReleaseUserInfo functions with invalid parameter. +* @tc.type: FUNC +* @tc.require: + */ +HWTEST_F(CloudServiceImplTest, ReleaseUserInfo001, TestSize.Level0) +{ + ZLOGI("CloudServiceImplTest ReleaseUserInfo001 start"); + int user = 100; + auto status = cloudServiceImpl_->ReleaseUserInfo(user); + EXPECT_TRUE(status); +} + +/** +* @tc.name: DoSubscribe +* @tc.desc: Test the DoSubscribe with not support CloudService +* @tc.type: FUNC +* @tc.require: + */ +HWTEST_F(CloudServiceImplTest, DoSubscribe, TestSize.Level0) +{ + int32_t user = 100; + auto status = cloudServiceImpl_->DoSubscribe(user); + EXPECT_TRUE(status); +} + +/** +* @tc.name: Share001 +* @tc.desc: Test the Share with invalid parameters +* @tc.type: FUNC +* @tc.require: + */ +HWTEST_F(CloudServiceImplTest, Share001, TestSize.Level0) +{ + std::string sharingRes; + CloudData::Participants participants; + CloudData::Results results; + auto status = cloudServiceImpl_->Share(sharingRes, participants, results); + EXPECT_EQ(status, GeneralError::E_ERROR); +} + +/** +* @tc.name: Unshare001 +* @tc.desc: Test the Unshare with invalid parameters +* @tc.type: FUNC +* @tc.require: + */ +HWTEST_F(CloudServiceImplTest, Unshare001, TestSize.Level0) +{ + std::string sharingRes; + CloudData::Participants participants; + CloudData::Results results; + auto status = cloudServiceImpl_->Unshare(sharingRes, participants, results); + EXPECT_EQ(status, GeneralError::E_ERROR); +} + +/** +* @tc.name: Exit001 +* @tc.desc: Test the Exit with invalid parameters +* @tc.type: FUNC +* @tc.require: + */ +HWTEST_F(CloudServiceImplTest, Exit001, TestSize.Level0) +{ + std::string sharingRes; + std::pair result; + auto status = cloudServiceImpl_->Exit(sharingRes, result); + EXPECT_EQ(status, GeneralError::E_ERROR); +} + +/** +* @tc.name: ChangePrivilege001 +* @tc.desc: Test the ChangePrivilege with invalid parameters +* @tc.type: FUNC +* @tc.require: + */ +HWTEST_F(CloudServiceImplTest, ChangePrivilege001, TestSize.Level0) +{ + std::string sharingRes; + CloudData::Participants participants; + CloudData::Results results; + auto status = cloudServiceImpl_->ChangePrivilege(sharingRes, participants, results); + EXPECT_EQ(status, GeneralError::E_ERROR); +} + +/** +* @tc.name: Query001 +* @tc.desc: Test the Query with invalid parameters +* @tc.type: FUNC +* @tc.require: + */ +HWTEST_F(CloudServiceImplTest, Query001, TestSize.Level0) +{ + std::string sharingRes; + CloudData::QueryResults results; + auto status = cloudServiceImpl_->Query(sharingRes, results); + EXPECT_EQ(status, GeneralError::E_ERROR); +} + +/** +* @tc.name: QueryByInvitation001 +* @tc.desc: Test the QueryByInvitation with invalid parameters +* @tc.type: FUNC +* @tc.require: + */ +HWTEST_F(CloudServiceImplTest, QueryByInvitation001, TestSize.Level0) +{ + std::string invitation; + CloudData::QueryResults results; + auto status = cloudServiceImpl_->QueryByInvitation(invitation, results); + EXPECT_EQ(status, GeneralError::E_ERROR); +} + +/** +* @tc.name: ConfirmInvitation001 +* @tc.desc: Test the ConfirmInvitation with invalid parameters +* @tc.type: FUNC +* @tc.require: + */ +HWTEST_F(CloudServiceImplTest, ConfirmInvitation001, TestSize.Level0) +{ + int32_t confirmation = 0; + std::tuple result{ 0, "", "" }; + std::string invitation; + auto status = cloudServiceImpl_->ConfirmInvitation(invitation, confirmation, result); + EXPECT_EQ(status, GeneralError::E_ERROR); +} + +/** +* @tc.name: ChangeConfirmation001 +* @tc.desc: Test the ChangeConfirmation with invalid parameters +* @tc.type: FUNC +* @tc.require: + */ +HWTEST_F(CloudServiceImplTest, ChangeConfirmation001, TestSize.Level0) +{ + int32_t confirmation = 0; + std::string sharingRes; + std::pair result; + auto status = cloudServiceImpl_->ChangeConfirmation(sharingRes, confirmation, result); + EXPECT_EQ(status, GeneralError::E_ERROR); +} + +/** +* @tc.name: GetSharingHandle001 +* @tc.desc: Test the GetSharingHandle with invalid parameters +* @tc.type: FUNC +* @tc.require: + */ +HWTEST_F(CloudServiceImplTest, GetSharingHandle001, TestSize.Level0) +{ + CloudData::CloudServiceImpl::HapInfo hapInfo; + auto status = cloudServiceImpl_->GetSharingHandle(hapInfo); + EXPECT_EQ(status, nullptr); +} + +/** +* @tc.name: SetCloudStrategy001 +* @tc.desc: Test the SetCloudStrategy with get hapInfo failed +* @tc.type: FUNC +* @tc.require: + */ +HWTEST_F(CloudServiceImplTest, SetCloudStrategy001, TestSize.Level0) +{ + CloudData::Strategy strategy = CloudData::Strategy::STRATEGY_NETWORK; + std::vector values; + values.push_back(CloudData::NetWorkStrategy::WIFI); + + auto status = cloudServiceImpl_->SetCloudStrategy(strategy, values); + EXPECT_EQ(status, CloudData::CloudService::ERROR); +} + +/** +* @tc.name: SetGlobalCloudStrategy001 +* @tc.desc: Test the SetGlobalCloudStrategy with get hapInfo failed +* @tc.type: FUNC +* @tc.require: + */ +HWTEST_F(CloudServiceImplTest, SetGlobalCloudStrategy001, TestSize.Level0) +{ + CloudData::Strategy strategy = CloudData::Strategy::STRATEGY_NETWORK; + std::vector values; + values.push_back(CloudData::NetWorkStrategy::WIFI); + + auto status = cloudServiceImpl_->SetGlobalCloudStrategy(strategy, values); + EXPECT_EQ(status, CloudData::CloudService::ERROR); +} + +/** +* @tc.name: CheckNotifyConditions001 +* @tc.desc: Test the CheckNotifyConditions with invalid parameters +* @tc.type: FUNC +* @tc.require: + */ +HWTEST_F(CloudServiceImplTest, CheckNotifyConditions, TestSize.Level0) +{ + CloudInfo cloudInfo; + cloudInfo.enableCloud = false; + cloudInfo.id = TEST_CLOUD_APPID; + + auto status = cloudServiceImpl_->CheckNotifyConditions(TEST_CLOUD_APPID, TEST_CLOUD_BUNDLE, cloudInfo); + EXPECT_EQ(status, CloudData::CloudService::CLOUD_DISABLE); + cloudInfo.enableCloud = true; + CloudInfo::AppInfo appInfo; + appInfo.bundleName = TEST_CLOUD_BUNDLE; + appInfo.cloudSwitch = false; + cloudInfo.apps.insert_or_assign(TEST_CLOUD_BUNDLE, appInfo); + status = cloudServiceImpl_->CheckNotifyConditions(TEST_CLOUD_APPID, TEST_CLOUD_BUNDLE, cloudInfo); + EXPECT_EQ(status, CloudData::CloudService::CLOUD_DISABLE_SWITCH); +} +} // namespace DistributedDataTest +} // namespace OHOS::Test \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/test/cloud_test.cpp b/datamgr_service/services/distributeddataservice/service/test/cloud_test.cpp index 607179ab752c8f5ffca90d50e80653381ebd4197..e49c66ca9570cc4e9c025a2300896774cdb90e1f 100644 --- a/datamgr_service/services/distributeddataservice/service/test/cloud_test.cpp +++ b/datamgr_service/services/distributeddataservice/service/test/cloud_test.cpp @@ -35,8 +35,8 @@ public: void TearDown(){}; protected: - static constexpr const char* testCloudBundle = "test_cloud_bundleName"; - static constexpr const char* testCloudStore = "test_cloud_database_name"; + static constexpr const char* TEST_CLOUD_BUNDLE = "test_cloud_bundleName"; + static constexpr const char* TEST_CLOUD_STORE = "test_cloud_database_name"; static std::shared_ptr dbStoreMock_; }; std::shared_ptr CloudTest::dbStoreMock_ = std::make_shared(); @@ -65,7 +65,7 @@ HWTEST_F(CloudTest, EventInfo, TestSize.Level1) SyncEvent::EventInfo eventInfo1(mode, wait, retry, query, async); SyncEvent::EventInfo eventInfo2(std::move(eventInfo1)); SyncEvent::EventInfo eventInfo3 = std::move(eventInfo2); - StoreInfo storeInfo{ IPCSkeleton::GetCallingTokenID(), testCloudBundle, testCloudStore, 0 }; + StoreInfo storeInfo{ IPCSkeleton::GetCallingTokenID(), TEST_CLOUD_BUNDLE, TEST_CLOUD_STORE, 0 }; SyncEvent evt(storeInfo, eventInfo3); EXPECT_EQ(evt.GetMode(), mode); EXPECT_EQ(evt.GetWait(), wait); @@ -88,11 +88,11 @@ HWTEST_F(CloudTest, Serializable_Marshal, TestSize.Level1) EXPECT_EQ(false, ret); SchemaMeta::Database database; - database.name = testCloudStore; + database.name = TEST_CLOUD_STORE; database.alias = "database_alias_test"; schemaMeta.version = 1; - schemaMeta.bundleName = testCloudBundle; + schemaMeta.bundleName = TEST_CLOUD_BUNDLE; schemaMeta.databases.emplace_back(database); ret = schemaMeta.IsValid(); EXPECT_EQ(true, ret); @@ -103,8 +103,12 @@ HWTEST_F(CloudTest, Serializable_Marshal, TestSize.Level1) EXPECT_EQ(schemaMeta.version, schemaMeta2.version); EXPECT_EQ(schemaMeta.bundleName, schemaMeta2.bundleName); - Database database2 = schemaMeta2.GetDataBase(testCloudStore); + Database database2 = schemaMeta2.GetDataBase(TEST_CLOUD_STORE); EXPECT_EQ(database.alias, database2.alias); + + std::string storeId = "storeId"; + Database database3 = schemaMeta2.GetDataBase(storeId); + EXPECT_NE(database.alias, database3.alias); } /** @@ -149,7 +153,7 @@ HWTEST_F(CloudTest, Database_Marshal, TestSize.Level1) table2.alias = "test_cloud_table_alias2"; SchemaMeta::Database database1; - database1.name = testCloudStore; + database1.name = TEST_CLOUD_STORE; database1.alias = "test_cloud_database_alias"; database1.tables.emplace_back(table1); database1.tables.emplace_back(table2); @@ -177,8 +181,9 @@ HWTEST_F(CloudTest, Database_Marshal, TestSize.Level1) */ HWTEST_F(CloudTest, CloudInfoUpgrade, TestSize.Level0) { + int32_t defaultUser = 100; CloudInfo oldInfo; - auto user = DistributedKv::AccountDelegate::GetInstance()->GetUserByToken(OHOS::IPCSkeleton::GetCallingTokenID()); + auto user = defaultUser; oldInfo.user = user; EXPECT_NE(oldInfo.maxNumber, CloudInfo::DEFAULT_BATCH_NUMBER); EXPECT_NE(oldInfo.maxSize, CloudInfo::DEFAULT_BATCH_SIZE); diff --git a/datamgr_service/services/distributeddataservice/service/test/data_share_profile_config_test.cpp b/datamgr_service/services/distributeddataservice/service/test/data_share_profile_config_test.cpp index 3c2ec549af5267aa48ca65c15b546d37dc3d0ea1..c8454845ddd875261ec074303e7433ccdd88296a 100644 --- a/datamgr_service/services/distributeddataservice/service/test/data_share_profile_config_test.cpp +++ b/datamgr_service/services/distributeddataservice/service/test/data_share_profile_config_test.cpp @@ -17,8 +17,6 @@ #include #include -#define private public -#include "data_share_profile_config.h" #include "datashare_errno.h" #include "data_share_db_config.h" #include "data_share_profile_config.h" @@ -49,18 +47,19 @@ public: HWTEST_F(DataShareProfileConfigTest, GetDbConfig, TestSize.Level1) { DataShareDbConfig dbConfig; - auto result = dbConfig.GetDbConfig("", false, "", "", 0); + DataShareDbConfig::DbConfig config {"", "", "", "", "", 0, false}; + auto result = dbConfig.GetDbConfig(config); EXPECT_EQ(std::get<0>(result), NativeRdb::E_DB_NOT_EXIST); - bool hasExtension = true; - result = dbConfig.GetDbConfig("", hasExtension, "", "", 0); + config.hasExtension = true; + result = dbConfig.GetDbConfig(config); EXPECT_EQ(std::get<0>(result), NativeRdb::E_DB_NOT_EXIST); - std::string uri = DATA_SHARE_URI; - std::string bundleName = "bundleName"; - std::string storeName = "storeName"; - int32_t userId = USER_TEST; - result = dbConfig.GetDbConfig(uri, hasExtension, bundleName, storeName, userId); + config.uri = DATA_SHARE_URI; + config.bundleName = "bundleName"; + config.storeName = "storeName"; + config.userId = USER_TEST; + result = dbConfig.GetDbConfig(config); EXPECT_NE(std::get<0>(result), DataShare::E_OK); } diff --git a/datamgr_service/services/distributeddataservice/service/test/data_share_service_impl_test.cpp b/datamgr_service/services/distributeddataservice/service/test/data_share_service_impl_test.cpp index d86bd4aaa36b0307e03b0415014e6c7ae1469806..9d7648f9361bd661dcc43d4e6c48775b9d5273ce 100644 --- a/datamgr_service/services/distributeddataservice/service/test/data_share_service_impl_test.cpp +++ b/datamgr_service/services/distributeddataservice/service/test/data_share_service_impl_test.cpp @@ -16,7 +16,6 @@ #include #include -#define private public #include "log_print.h" #include "ipc_skeleton.h" #include "data_share_service_stub.h" @@ -95,7 +94,7 @@ void DataShareServiceImplTest::TearDown(void) /** * @tc.name: DataShareServiceImpl001 -* @tc.desc: test Insert Update Query Delete abnormal scene +* @tc.desc: test InsertEx UpdateEx Query DeleteEx abnormal scene * @tc.type: FUNC * @tc.require:SQL */ @@ -110,19 +109,19 @@ HWTEST_F(DataShareServiceImplTest, DataShareServiceImpl001, TestSize.Level1) DataShare::DataShareValuesBucket valuesBucket; std::string name0 = ""; valuesBucket.Put("", name0); - auto result = dataShareServiceImpl.Insert(uri, valuesBucket); - EXPECT_EQ((result > 0), true); + auto [errCode, result] = dataShareServiceImpl.InsertEx(uri, "", valuesBucket); + EXPECT_EQ((errCode != 0), true); DataShare::DataSharePredicates predicates; std::string selections = ""; predicates.SetWhereClause(selections); - result = dataShareServiceImpl.Update(uri, predicates, valuesBucket); - EXPECT_EQ((result > 0), true); + auto [errCode1, result1] = dataShareServiceImpl.UpdateEx(uri, "", predicates, valuesBucket); + EXPECT_EQ((errCode1 != 0), true); predicates.EqualTo("", ""); std::vector columns; - int errCode = 0; - auto resQuery = dataShareServiceImpl.Query(uri, predicates, columns, errCode); + int errVal = 0; + auto resQuery = dataShareServiceImpl.Query(uri, "", predicates, columns, errVal); int resultSet = 0; if (resQuery != nullptr) { resQuery->GetRowCount(resultSet); @@ -130,8 +129,8 @@ HWTEST_F(DataShareServiceImplTest, DataShareServiceImpl001, TestSize.Level1) EXPECT_EQ(resultSet, 0); predicates.SetWhereClause(selections); - result = dataShareServiceImpl.Delete(uri, predicates); - EXPECT_EQ((result > 0), true); + auto [errCode2, result2] = dataShareServiceImpl.DeleteEx(uri, "", predicates); + EXPECT_EQ((errCode2 != 0), true); } /** @@ -286,8 +285,8 @@ HWTEST_F(DataShareServiceImplTest, SubscribeRdbData001, TestSize.Level1) DataShare::DataShareValuesBucket valuesBucket1, valuesBucket2; std::string name0 = "wang"; valuesBucket1.Put(TBL_NAME0, name0); - auto result4 = dataShareServiceImpl.Insert(uri, valuesBucket1); - EXPECT_EQ((result4 > 0), true); + auto [errCode4, result4] = dataShareServiceImpl.InsertEx(uri, "", valuesBucket1); + EXPECT_EQ((errCode4 != 0), true); std::vector result5 = dataShareServiceImpl.UnsubscribeRdbData(uris, tplId); EXPECT_EQ(result5.size(), uris.size()); @@ -297,8 +296,8 @@ HWTEST_F(DataShareServiceImplTest, SubscribeRdbData001, TestSize.Level1) std::string name1 = "wu"; valuesBucket2.Put(TBL_NAME1, name1); - auto result6 = dataShareServiceImpl.Insert(uri, valuesBucket2); - EXPECT_EQ((result6 > 0), true); + auto [errCode6, result6] = dataShareServiceImpl.InsertEx(uri, "", valuesBucket2); + EXPECT_EQ((errCode6 != 0), true); std::vector result7 = dataShareServiceImpl.DisableRdbSubs(uris, tplId); for (auto const &operationResult : result7) { diff --git a/datamgr_service/services/distributeddataservice/service/test/data_share_service_stub_test.cpp b/datamgr_service/services/distributeddataservice/service/test/data_share_service_stub_test.cpp index 0adae040d183304777c2b0431c4fd51240d4741b..d006a70be73b307e22916d471ae3ca0ad7926224 100644 --- a/datamgr_service/services/distributeddataservice/service/test/data_share_service_stub_test.cpp +++ b/datamgr_service/services/distributeddataservice/service/test/data_share_service_stub_test.cpp @@ -16,7 +16,6 @@ #include #include -#define private public #include "log_print.h" #include "ipc_skeleton.h" #include "data_share_service_impl.h" @@ -59,7 +58,7 @@ HWTEST_F(DataShareServiceStubTest, OnRemoteRequest001, TestSize.Level1) request.RewindRead(0); MessageParcel reply; auto result = dataShareServiceStub->OnRemoteRequest(code, request, reply); - EXPECT_NE(result, IDataShareService::DATA_SHARE_ERROR); + EXPECT_EQ(result, IDataShareService::DATA_SHARE_ERROR); result = dataShareServiceStub->OnNotifyConnectDone(request, reply); EXPECT_EQ(result, IDataShareService::DATA_SHARE_OK); @@ -87,7 +86,7 @@ HWTEST_F(DataShareServiceStubTest, OnRemoteRequest002, TestSize.Level1) /** * @tc.name: OnInsert001 -* @tc.desc: test Insert Update Query Delete function of abnormal scene +* @tc.desc: test InsertEx UpdateEx Query DeleteEx function of abnormal scene * @tc.type: FUNC * @tc.require:SQL */ @@ -101,16 +100,16 @@ HWTEST_F(DataShareServiceStubTest, OnInsert001, TestSize.Level1) request.WriteBuffer(data, size); request.RewindRead(0); MessageParcel reply; - auto result = dataShareServiceStub->OnInsert(request, reply); + auto result = dataShareServiceStub->OnInsertEx(request, reply); EXPECT_EQ(result, IPC_STUB_INVALID_DATA_ERR); - result = dataShareServiceStub->OnUpdate(request, reply); + result = dataShareServiceStub->OnUpdateEx(request, reply); EXPECT_EQ(result, IPC_STUB_INVALID_DATA_ERR); result = dataShareServiceStub->OnQuery(request, reply); EXPECT_EQ(result, IPC_STUB_INVALID_DATA_ERR); - result = dataShareServiceStub->OnDelete(request, reply); + result = dataShareServiceStub->OnDeleteEx(request, reply); EXPECT_EQ(result, IPC_STUB_INVALID_DATA_ERR); } diff --git a/datamgr_service/services/distributeddataservice/service/test/data_share_subscriber_managers_test.cpp b/datamgr_service/services/distributeddataservice/service/test/data_share_subscriber_managers_test.cpp index bd34b243f73c87d98d5778a782b41dcee9a06f3f..eedf4ba159ec0143f6439b03e8a364b05a42a381 100644 --- a/datamgr_service/services/distributeddataservice/service/test/data_share_subscriber_managers_test.cpp +++ b/datamgr_service/services/distributeddataservice/service/test/data_share_subscriber_managers_test.cpp @@ -15,8 +15,8 @@ #define LOG_TAG "DataShareSubscriberManagersTest" #include +#include -#define private public #include "accesstoken_kit.h" #include "datashare_errno.h" #include "data_share_service_impl.h" diff --git a/datamgr_service/services/distributeddataservice/service/test/device_matrix_test.cpp b/datamgr_service/services/distributeddataservice/service/test/device_matrix_test.cpp index 975e45f01ef865bd157767501d19ac6d8485c5c3..f72ffc5676763092954985f00f6124aaf9e7b5ad 100644 --- a/datamgr_service/services/distributeddataservice/service/test/device_matrix_test.cpp +++ b/datamgr_service/services/distributeddataservice/service/test/device_matrix_test.cpp @@ -55,8 +55,8 @@ protected: static inline std::vector> staticStores_ = { { "bundle0", "store0" }, { "bundle1", "store0" } }; - static inline std::vector> dynamicStores_ = { - { "distributeddata", "service_meta" }, { "bundle0", "store1" }, { "bundle3", "store0" } }; + static inline std::vector> dynamicStores_ = { { "bundle0", "store1" }, + { "bundle3", "store0" } }; static BlockData isFinished_; static std::shared_ptr dbStoreMock_; static uint32_t selfToken_; @@ -89,38 +89,12 @@ void DeviceMatrixTest::SetUpTestCase(void) } Bootstrap::GetInstance().LoadCheckers(); DeviceMatrix::GetInstance().Initialize(selfToken_, "service_meta"); - EventCenter::GetInstance().Subscribe(DeviceMatrix::MATRIX_ONLINE, [](const Event &event) { - auto &evt = static_cast(event); - auto data = evt.GetMatrixData(); - auto deviceId = evt.GetDeviceId(); - if ((data.dynamic & DeviceMatrix::META_STORE_MASK) != 0) { - auto onComplete = [deviceId](const std::map &) { - DeviceMatrix::GetInstance().OnExchanged(deviceId, DeviceMatrix::META_STORE_MASK); - }; - dbStoreMock_->Sync({ deviceId }, SYNC_MODE_PUSH_PULL, onComplete, false); - } -#ifdef TEST_ON_DEVICE - auto finEvent = std::make_unique(DeviceMatrix::MATRIX_META_FINISHED, deviceId, data); - EventCenter::GetInstance().PostEvent(std::move(finEvent)); -#endif - }); - - EventCenter::GetInstance().Subscribe(DeviceMatrix::MATRIX_META_FINISHED, [](const Event &event) { - auto &evt = static_cast(event); - Result result; - result.deviceId_ = evt.GetDeviceId(); - result.mask_ = evt.GetMatrixData().dynamic; - isFinished_.SetValue(result); - }); - mkdir("/data/service/el1/public/database/matrix_test", (S_IRWXU | S_IRWXG | S_IRWXO)); mkdir("/data/service/el1/public/database/matrix_test/kvdb", (S_IRWXU | S_IRWXG | S_IRWXO)); } void DeviceMatrixTest::TearDownTestCase(void) { - EventCenter::GetInstance().Unsubscribe(DeviceMatrix::MATRIX_ONLINE); - EventCenter::GetInstance().Unsubscribe(DeviceMatrix::MATRIX_META_FINISHED); EventCenter::GetInstance().Unsubscribe(DeviceMatrix::MATRIX_BROADCAST); } @@ -171,86 +145,6 @@ void DeviceMatrixTest::InitMetaData() localMeta_.policies = { std::move(value) }; } -/** -* @tc.name: FirstOnline -* @tc.desc: the first online time; -* @tc.type: FUNC -* @tc.require: -* @tc.author: blue sky -*/ -HWTEST_F(DeviceMatrixTest, FirstOnline, TestSize.Level0) -{ - DeviceMatrix::GetInstance().Online(TEST_DEVICE); - auto result = isFinished_.GetValue(); - ASSERT_EQ(result.deviceId_, std::string(TEST_DEVICE)); - ASSERT_EQ(result.mask_, 0x7); -} - -/** -* @tc.name: OnlineAgainNoData -* @tc.desc: the second online with no data change; -* @tc.type: FUNC -* @tc.require: -* @tc.author: blue sky -*/ -HWTEST_F(DeviceMatrixTest, OnlineAgainNoData, TestSize.Level0) -{ - DeviceMatrix::GetInstance().Online(TEST_DEVICE); - auto result = isFinished_.GetValue(); - ASSERT_EQ(result.deviceId_, std::string(TEST_DEVICE)); - ASSERT_EQ(result.mask_, 0x7); - isFinished_.Clear(Result()); - DeviceMatrix::GetInstance().Offline(TEST_DEVICE); - DeviceMatrix::GetInstance().Online(TEST_DEVICE); - result = isFinished_.GetValue(); - ASSERT_EQ(result.deviceId_, std::string(TEST_DEVICE)); - ASSERT_EQ(result.mask_, 0x6); -} - -/** -* @tc.name: OnlineAgainWithData -* @tc.desc: the second online with sync data change; -* @tc.type: FUNC -* @tc.require: -* @tc.author: blue sky -*/ -HWTEST_F(DeviceMatrixTest, OnlineAgainWithData, TestSize.Level0) -{ - DeviceMatrix::GetInstance().Online(TEST_DEVICE); - auto result = isFinished_.GetValue(); - ASSERT_EQ(result.deviceId_, std::string(TEST_DEVICE)); - ASSERT_EQ(result.mask_, 0x7); - isFinished_.Clear(Result()); - DeviceMatrix::GetInstance().Offline(TEST_DEVICE); - MetaDataManager::GetInstance().SaveMeta(metaData_.GetKey(), metaData_); - DeviceMatrix::GetInstance().Online(TEST_DEVICE); - result = isFinished_.GetValue(); - ASSERT_EQ(result.deviceId_, std::string(TEST_DEVICE)); - ASSERT_EQ(result.mask_, 0x7); -} - -/** -* @tc.name: OnlineAgainWithLocal -* @tc.desc: the second online with local data change; -* @tc.type: FUNC -* @tc.require: -* @tc.author: blue sky -*/ -HWTEST_F(DeviceMatrixTest, OnlineAgainWithLocal, TestSize.Level0) -{ - DeviceMatrix::GetInstance().Online(TEST_DEVICE); - auto result = isFinished_.GetValue(); - ASSERT_EQ(result.deviceId_, std::string(TEST_DEVICE)); - ASSERT_EQ(result.mask_, 0x7); - isFinished_.Clear(Result()); - DeviceMatrix::GetInstance().Offline(TEST_DEVICE); - MetaDataManager::GetInstance().SaveMeta(metaData_.GetKeyLocal(), localMeta_, true); - DeviceMatrix::GetInstance().Online(TEST_DEVICE); - result = isFinished_.GetValue(); - ASSERT_EQ(result.deviceId_, std::string(TEST_DEVICE)); - ASSERT_EQ(result.mask_, 0x6); -} - /** * @tc.name: GetMetaStoreCode * @tc.desc: get the meta data store mask code; @@ -283,7 +177,7 @@ HWTEST_F(DeviceMatrixTest, GetAllCode, TestSize.Level0) for (size_t i = 0; i < dynamicStores_.size(); ++i) { meta.appId = dynamicStores_[i].first; meta.bundleName = dynamicStores_[i].first; - ASSERT_EQ(DeviceMatrix::GetInstance().GetCode(meta), 0x1 << i); + ASSERT_EQ(DeviceMatrix::GetInstance().GetCode(meta), 0x1 << (i + 1)); } } @@ -327,8 +221,8 @@ HWTEST_F(DeviceMatrixTest, BroadcastMeta, TestSize.Level0) HWTEST_F(DeviceMatrixTest, BroadcastFirst, TestSize.Level0) { StoreMetaData meta = metaData_; - meta.appId = dynamicStores_[1].first; - meta.bundleName = dynamicStores_[1].first; + meta.appId = dynamicStores_[0].first; + meta.bundleName = dynamicStores_[0].first; auto code = DeviceMatrix::GetInstance().GetCode(meta); ASSERT_EQ(code, 0x2); DeviceMatrix::DataLevel level = { @@ -371,13 +265,13 @@ HWTEST_F(DeviceMatrixTest, BroadcastAll, TestSize.Level0) auto mask = DeviceMatrix::GetInstance().OnBroadcast(TEST_DEVICE, level); ASSERT_EQ(mask.first, DeviceMatrix::META_STORE_MASK); StoreMetaData meta = metaData_; - for (size_t i = 1; i < dynamicStores_.size(); ++i) { + for (size_t i = 0; i < dynamicStores_.size(); ++i) { meta.appId = dynamicStores_[i].first; meta.bundleName = dynamicStores_[i].first; auto code = DeviceMatrix::GetInstance().GetCode(meta); level.dynamic = code; mask = DeviceMatrix::GetInstance().OnBroadcast(TEST_DEVICE, level); - ASSERT_EQ(mask.first, (0x1 << i) + 1); + ASSERT_EQ(mask.first, (0x1 << (i + 1)) + 1); DeviceMatrix::GetInstance().OnExchanged(TEST_DEVICE, code); } DeviceMatrix::GetInstance().OnExchanged(TEST_DEVICE, DeviceMatrix::META_STORE_MASK); @@ -405,7 +299,7 @@ HWTEST_F(DeviceMatrixTest, UpdateMatrixMeta, TestSize.Level0) metaData.dynamic = 0x1F; metaData.deviceId = TEST_DEVICE; metaData.origin = MatrixMetaData::Origin::REMOTE_RECEIVED; - metaData.dynamicInfo = { TEST_BUNDLE, dynamicStores_[1].first }; + metaData.dynamicInfo = { TEST_BUNDLE, dynamicStores_[0].first }; MetaDataManager::GetInstance().Subscribe(MatrixMetaData::GetPrefix({ TEST_DEVICE }), [](const std::string &, const std::string &value, int32_t flag) { if (flag != MetaDataManager::INSERT && flag != MetaDataManager::UPDATE) { diff --git a/datamgr_service/services/distributeddataservice/service/test/dump_helper_test.cpp b/datamgr_service/services/distributeddataservice/service/test/dump_helper_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..86ce2efb7db433e6e076b9eb81ff6b7dbeb8b2a2 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/test/dump_helper_test.cpp @@ -0,0 +1,99 @@ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#define LOG_TAG "DumpHelperTest " + +#include "gtest/gtest.h" +#include "log_print.h" +#include "dump_helper.h" +#include "dump/dump_manager.h" +#include "types.h" + +using namespace OHOS; +using namespace testing; +using namespace testing::ext; +using namespace OHOS::DistributedData; +namespace OHOS::Test { +namespace DistributedDataTest { +class DumpHelperTest : public testing::Test { +public: + static void SetUpTestCase(void){}; + static void TearDownTestCase(void){}; + void SetUp(); + void TearDown(){}; +}; + +void DumpHelperTest::SetUp(void) +{ + DumpManager &dumpManager = DumpManager::GetInstance(); + DumpManager::Config config; + config.dumpName = "test_dump"; + config.fullCmd = "test_full_cmd"; + config.abbrCmd = "test_abbr_cmd"; + config.countPrintf = 1; + config.infoName = "test_info"; + config.minParamsNum = 2; //minParamsNum is 2 + config.maxParamsNum = 5; //maxParamsNum is 5 + config.parentNode = "test_parent"; + config.childNode = "test_child"; + config.dumpCaption = {"test_caption1", "test_caption2"}; + + dumpManager.AddConfig("111", config); + dumpManager.GetHandler(config.infoName); + DumpManager::Config result = dumpManager.GetConfig("111"); + ASSERT_EQ(result.dumpName, config.dumpName); +} + +/** +* @tc.name: GetInstanceTest +* @tc.desc: GetInstance test. +* @tc.type: FUNC +* @tc.require: +* @tc.author: SQL +*/ +HWTEST_F(DumpHelperTest, GetInstanceTest, TestSize.Level0) +{ + DumpHelper &dumpHelper = DumpHelper::GetInstance(); + EXPECT_NE(&dumpHelper, nullptr); + + int fd = 1; + std::vector args; + EXPECT_TRUE(dumpHelper.Dump(fd, args)); + + args = {"COMMAND_A", "ARG_1", "ARG_2"}; + EXPECT_TRUE(dumpHelper.Dump(fd, args)); +} + +/** +* @tc.name: AddErrorInfoTest +* @tc.desc: AddErrorInfo test. +* @tc.type: FUNC +* @tc.require: +* @tc.author: SQL +*/ +HWTEST_F(DumpHelperTest, AddErrorInfoTest, TestSize.Level0) +{ + DumpHelper &dumpHelper = DumpHelper::GetInstance(); + EXPECT_NE(&dumpHelper, nullptr); + int32_t errorCode = 1001; + std::string errorInfo = "Test error information"; + + dumpHelper.AddErrorInfo(errorCode, errorInfo); + + const OHOS::DistributedData::DumpHelper::ErrorInfo& lastError = dumpHelper.errorInfo_.back(); + EXPECT_EQ(lastError.errorCode, errorCode); + EXPECT_EQ(lastError.errorInfo, errorInfo); +} +} // namespace DistributedDataTest +} // namespace OHOS::Test \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/test/fuzztest/cloudservicestub_fuzzer/BUILD.gn b/datamgr_service/services/distributeddataservice/service/test/fuzztest/cloudservicestub_fuzzer/BUILD.gn index 2007179cd6f0d852d467b542be5e1970056f20ab..4f44b6a128887890b0b18fa83a9248cd5b6ed6e4 100644 --- a/datamgr_service/services/distributeddataservice/service/test/fuzztest/cloudservicestub_fuzzer/BUILD.gn +++ b/datamgr_service/services/distributeddataservice/service/test/fuzztest/cloudservicestub_fuzzer/BUILD.gn @@ -75,6 +75,7 @@ ohos_fuzztest("CloudServiceStubFuzzTest") { "${data_service_path}/service/common/value_proxy.cpp", "${data_service_path}/service/common/xcollie.cpp", "${data_service_path}/service/config/src/config_factory.cpp", + "${data_service_path}/service/config/src/model/app_id_mapping_config.cpp", "${data_service_path}/service/config/src/model/backup_config.cpp", "${data_service_path}/service/config/src/model/checker_config.cpp", "${data_service_path}/service/config/src/model/cloud_config.cpp", diff --git a/datamgr_service/services/distributeddataservice/service/test/fuzztest/customutdinstaller_fuzzer/BUILD.gn b/datamgr_service/services/distributeddataservice/service/test/fuzztest/customutdinstaller_fuzzer/BUILD.gn index 485c816f6e2d887c8415f4b02f10db49ab13b02c..c495c98f2507352fc7be8f2af14896936221f078 100644 --- a/datamgr_service/services/distributeddataservice/service/test/fuzztest/customutdinstaller_fuzzer/BUILD.gn +++ b/datamgr_service/services/distributeddataservice/service/test/fuzztest/customutdinstaller_fuzzer/BUILD.gn @@ -99,6 +99,7 @@ ohos_fuzztest("CustomUtdInstallerFuzzTest") { "safwk:system_ability_fwk", "samgr:samgr_proxy", "udmf:udmf_client", + "udmf:utd_client", ] } diff --git a/datamgr_service/services/distributeddataservice/service/test/fuzztest/kvdbservicestub_fuzzer/BUILD.gn b/datamgr_service/services/distributeddataservice/service/test/fuzztest/kvdbservicestub_fuzzer/BUILD.gn index 7e0a82496eaab9618c39b0dfb816ef04b328fb91..83c0d39844230f6f731274e4f10e1087b397d133 100644 --- a/datamgr_service/services/distributeddataservice/service/test/fuzztest/kvdbservicestub_fuzzer/BUILD.gn +++ b/datamgr_service/services/distributeddataservice/service/test/fuzztest/kvdbservicestub_fuzzer/BUILD.gn @@ -63,6 +63,7 @@ ohos_fuzztest("KvdbServiceStubFuzzTest") { "${data_service_path}/service/bootstrap/src/bootstrap.cpp", "${data_service_path}/service/common/value_proxy.cpp", "${data_service_path}/service/config/src/config_factory.cpp", + "${data_service_path}/service/config/src/model/app_id_mapping_config.cpp", "${data_service_path}/service/config/src/model/backup_config.cpp", "${data_service_path}/service/config/src/model/checker_config.cpp", "${data_service_path}/service/config/src/model/cloud_config.cpp", @@ -83,7 +84,6 @@ ohos_fuzztest("KvdbServiceStubFuzzTest") { "${data_service_path}/service/kvdb/query_helper.cpp", "${data_service_path}/service/kvdb/upgrade.cpp", "${data_service_path}/service/kvdb/user_delegate.cpp", - "${data_service_path}/service/matrix/src/auto_sync_matrix.cpp", "${data_service_path}/service/matrix/src/device_matrix.cpp", "${data_service_path}/service/matrix/src/matrix_event.cpp", "${data_service_path}/service/permission/src/permit_delegate.cpp", diff --git a/datamgr_service/services/distributeddataservice/service/test/fuzztest/objectservicestub_fuzzer/BUILD.gn b/datamgr_service/services/distributeddataservice/service/test/fuzztest/objectservicestub_fuzzer/BUILD.gn index 9f31030817a47d99ddde2c4f3c688d080cb9d5fe..d268b6b6bde89c43efedd1a05a3de171d805069f 100644 --- a/datamgr_service/services/distributeddataservice/service/test/fuzztest/objectservicestub_fuzzer/BUILD.gn +++ b/datamgr_service/services/distributeddataservice/service/test/fuzztest/objectservicestub_fuzzer/BUILD.gn @@ -62,6 +62,7 @@ ohos_fuzztest("ObjectServiceStubFuzzTest") { "${data_service_path}/service/common/common_types_utils.cpp", "${data_service_path}/service/common/value_proxy.cpp", "${data_service_path}/service/config/src/config_factory.cpp", + "${data_service_path}/service/config/src/model/app_id_mapping_config.cpp", "${data_service_path}/service/config/src/model/backup_config.cpp", "${data_service_path}/service/config/src/model/checker_config.cpp", "${data_service_path}/service/config/src/model/cloud_config.cpp", diff --git a/datamgr_service/services/distributeddataservice/service/test/fuzztest/rdbservicestub_fuzzer/BUILD.gn b/datamgr_service/services/distributeddataservice/service/test/fuzztest/rdbservicestub_fuzzer/BUILD.gn index f45834eef869489f2f3413fb570e03baab800d97..a6ffe6bb80601d514d992035cc5f049921cc2111 100644 --- a/datamgr_service/services/distributeddataservice/service/test/fuzztest/rdbservicestub_fuzzer/BUILD.gn +++ b/datamgr_service/services/distributeddataservice/service/test/fuzztest/rdbservicestub_fuzzer/BUILD.gn @@ -69,6 +69,7 @@ ohos_fuzztest("RdbServiceStubFuzzTest") { "${data_service_path}/service/common/value_proxy.cpp", "${data_service_path}/service/common/xcollie.cpp", "${data_service_path}/service/config/src/config_factory.cpp", + "${data_service_path}/service/config/src/model/app_id_mapping_config.cpp", "${data_service_path}/service/config/src/model/backup_config.cpp", "${data_service_path}/service/config/src/model/checker_config.cpp", "${data_service_path}/service/config/src/model/cloud_config.cpp", diff --git a/datamgr_service/services/distributeddataservice/service/test/fuzztest/udmfservice_fuzzer/BUILD.gn b/datamgr_service/services/distributeddataservice/service/test/fuzztest/udmfservice_fuzzer/BUILD.gn index 2c399378cce589d21b55e9a00cef499667a97e7a..82fe2b8671d5cfd82742dcd3cc3e41dfa7f08362 100644 --- a/datamgr_service/services/distributeddataservice/service/test/fuzztest/udmfservice_fuzzer/BUILD.gn +++ b/datamgr_service/services/distributeddataservice/service/test/fuzztest/udmfservice_fuzzer/BUILD.gn @@ -56,7 +56,6 @@ ohos_fuzztest("UdmfServiceFuzzTest") { "bundle_framework:appexecfwk_core", "c_utils:utils", "hilog:libhilog", - "image_framework:image", "ipc:ipc_core", "kv_store:distributeddata_inner", "kv_store:distributeddata_mgr", diff --git a/datamgr_service/services/distributeddataservice/service/test/kvdb_general_store_test.cpp b/datamgr_service/services/distributeddataservice/service/test/kvdb_general_store_test.cpp index 23a555dd4ae0e94e5390aae56cf40b4a0139721c..557d62d531d7c233ed813ccee1939ddc04335d1b 100644 --- a/datamgr_service/services/distributeddataservice/service/test/kvdb_general_store_test.cpp +++ b/datamgr_service/services/distributeddataservice/service/test/kvdb_general_store_test.cpp @@ -18,30 +18,38 @@ #include #include +#include #include "bootstrap.h" +#include "cloud/schema_meta.h" +#include "cloud/asset_loader.h" +#include "cloud/cloud_db.h" #include "crypto_manager.h" #include "kvdb_query.h" +#include "kv_store_nb_delegate_mock.h" #include "log_print.h" #include "metadata/meta_data_manager.h" #include "metadata/secret_key_meta_data.h" #include "metadata/store_meta_data.h" #include "metadata/store_meta_data_local.h" #include "mock/db_store_mock.h" +#include "mock/general_watcher_mock.h" using namespace testing::ext; +using namespace DistributedDB; +using namespace OHOS::DistributedData; using DBStoreMock = OHOS::DistributedData::DBStoreMock; using StoreMetaData = OHOS::DistributedData::StoreMetaData; - -namespace OHOS { -namespace DistributedKv { +using SecurityLevel = OHOS::DistributedKv::SecurityLevel; +using KVDBGeneralStore = OHOS::DistributedKv::KVDBGeneralStore; +namespace OHOS::Test { +namespace DistributedDataTest { class KVDBGeneralStoreTest : public testing::Test { public: static void SetUpTestCase(void); static void TearDownTestCase(void); void SetUp(); void TearDown(); - protected: static constexpr const char *bundleName = "test_distributeddata"; static constexpr const char *storeName = "test_service_meta"; @@ -64,7 +72,7 @@ void KVDBGeneralStoreTest::InitMetaData() metaData_.area = OHOS::DistributedKv::EL1; metaData_.instanceId = 0; metaData_.isAutoSync = true; - metaData_.storeType = KvStoreType::SINGLE_VERSION; + metaData_.storeType = DistributedKv::KvStoreType::SINGLE_VERSION; metaData_.storeId = storeName; metaData_.dataDir = "/data/service/el1/public/database/" + std::string(bundleName) + "/kvdb"; metaData_.securityLevel = SecurityLevel::S2; @@ -95,6 +103,48 @@ void KVDBGeneralStoreTest::SetUp() void KVDBGeneralStoreTest::TearDown() {} +class MockGeneralWatcher : public DistributedData::GeneralWatcher { +public: + int32_t OnChange(const Origin &origin, const PRIFields &primaryFields, ChangeInfo &&values) override + { + return GeneralError::E_OK; + } + + int32_t OnChange(const Origin &origin, const Fields &fields, ChangeData &&datas) override + { + return GeneralError::E_OK; + } +}; + +class MockKvStoreChangedData : public DistributedDB::KvStoreChangedData { +public: + MockKvStoreChangedData() {} + virtual ~MockKvStoreChangedData() {} + std::list entriesInserted = {}; + std::list entriesUpdated = {}; + std::list entriesDeleted = {}; + bool isCleared = true; + const std::list& GetEntriesInserted() const override + { + return entriesInserted; + } + + const std::list& GetEntriesUpdated() const override + { + return entriesUpdated; + } + + const std::list& GetEntriesDeleted() const override + { + return entriesDeleted; + } + + bool IsCleared() const override + { + return isCleared; + } +}; + /** * @tc.name: GetDBPasswordTest_001 * @tc.desc: GetDBPassword from meta. @@ -177,6 +227,11 @@ HWTEST_F(KVDBGeneralStoreTest, GetDBSecurityTest, TestSize.Level0) dbSecurity = KVDBGeneralStore::GetDBSecurity(SecurityLevel::S4); EXPECT_EQ(dbSecurity.securityLabel, DistributedDB::S4); EXPECT_EQ(dbSecurity.securityFlag, DistributedDB::ECE); + + auto action = static_cast(SecurityLevel::S4 + 1); + dbSecurity = KVDBGeneralStore::GetDBSecurity(action); + EXPECT_EQ(dbSecurity.securityLabel, DistributedDB::NOT_SET); + EXPECT_EQ(dbSecurity.securityFlag, DistributedDB::ECE); } /** @@ -206,7 +261,7 @@ HWTEST_F(KVDBGeneralStoreTest, GetDBOptionTest, TestSize.Level0) /** * @tc.name: CloseTest -* @tc.desc: Close kvdb general store. +* @tc.desc: Close kvdb general store and test the functionality of different branches. * @tc.type: FUNC * @tc.require: * @tc.author: Hollokin @@ -217,6 +272,36 @@ HWTEST_F(KVDBGeneralStoreTest, CloseTest, TestSize.Level0) ASSERT_NE(store, nullptr); auto ret = store->Close(); EXPECT_EQ(ret, GeneralError::E_OK); + + KvStoreNbDelegateMock mockDelegate; + mockDelegate.taskCountMock_ = 1; + store->delegate_ = &mockDelegate; + EXPECT_NE(store->delegate_, nullptr); + ret = store->Close(); + EXPECT_EQ(ret, GeneralError::E_BUSY); +} + +/** +* @tc.name: Close +* @tc.desc: RdbGeneralStore Close test +* @tc.type: FUNC +* @tc.require: +* @tc.author: shaoyuanzhao +*/ +HWTEST_F(KVDBGeneralStoreTest, BusyClose, TestSize.Level0) +{ + auto store = std::make_shared(metaData_); + ASSERT_NE(store, nullptr); + std::thread thread([store]() { + std::unique_lockrwMutex_)> lock(store->rwMutex_); + std::this_thread::sleep_for(std::chrono::seconds(1)); + }); + std::this_thread::sleep_for(std::chrono::milliseconds(500)); + auto ret = store->Close(); + EXPECT_EQ(ret, GeneralError::E_BUSY); + thread.join(); + ret = store->Close(); + EXPECT_EQ(ret, GeneralError::E_OK); } /** @@ -237,7 +322,7 @@ HWTEST_F(KVDBGeneralStoreTest, SyncTest, TestSize.Level0) uint32_t highMode = GeneralStore::HighMode::MANUAL_SYNC_MODE; auto mixMode = GeneralStore::MixMode(syncMode, highMode); std::string kvQuery = ""; - KVDBQuery query(kvQuery); + DistributedKv::KVDBQuery query(kvQuery); SyncParam syncParam{}; syncParam.mode = mixMode; auto ret = store->Sync( @@ -246,5 +331,396 @@ HWTEST_F(KVDBGeneralStoreTest, SyncTest, TestSize.Level0) ret = store->Close(); EXPECT_EQ(ret, GeneralError::E_OK); } + +/** +* @tc.name: BindTest +* @tc.desc: Bind test the functionality of different branches. +* @tc.type: FUNC +* @tc.require: +* @tc.author: SQL +*/ +HWTEST_F(KVDBGeneralStoreTest, BindTest, TestSize.Level0) +{ + auto store = new (std::nothrow) KVDBGeneralStore(metaData_); + ASSERT_NE(store, nullptr); + DistributedData::Database database; + std::map bindInfos; + GeneralStore::CloudConfig config; + EXPECT_EQ(bindInfos.empty(), true); + auto ret = store->Bind(database, bindInfos, config); + EXPECT_EQ(ret, GeneralError::E_OK); + + std::shared_ptr db; + std::shared_ptr loader; + GeneralStore::BindInfo bindInfo1(db, loader); + uint32_t key = 1; + bindInfos[key] = bindInfo1; + ret = store->Bind(database, bindInfos, config); + EXPECT_EQ(ret, GeneralError::E_INVALID_ARGS); + std::shared_ptr dbs = std::make_shared(); + std::shared_ptr loaders = std::make_shared(); + GeneralStore::BindInfo bindInfo2(dbs, loaders); + bindInfos[key] = bindInfo2; + EXPECT_EQ(store->IsBound(), false); + ret = store->Bind(database, bindInfos, config); + EXPECT_EQ(ret, GeneralError::E_ALREADY_CLOSED); + + store->isBound_ = false; + KvStoreNbDelegateMock mockDelegate; + store->delegate_ = &mockDelegate; + EXPECT_NE(store->delegate_, nullptr); + EXPECT_EQ(store->IsBound(), false); + ret = store->Bind(database, bindInfos, config); + EXPECT_EQ(ret, GeneralError::E_OK); + + EXPECT_EQ(store->IsBound(), true); + ret = store->Bind(database, bindInfos, config); + EXPECT_EQ(ret, GeneralError::E_OK); +} + +/** +* @tc.name: GetDBSyncCompleteCB +* @tc.desc: GetDBSyncCompleteCB test the functionality of different branches. +* @tc.type: FUNC +* @tc.require: +* @tc.author: SQL +*/ +HWTEST_F(KVDBGeneralStoreTest, GetDBSyncCompleteCB, TestSize.Level0) +{ + auto store = new (std::nothrow) KVDBGeneralStore(metaData_); + ASSERT_NE(store, nullptr); + GeneralStore::DetailAsync async; + EXPECT_EQ(async, nullptr); + KVDBGeneralStore::DBSyncCallback ret = store->GetDBSyncCompleteCB(async); + EXPECT_NE(ret, nullptr); + auto asyncs = [](const GenDetails &result) {}; + EXPECT_NE(asyncs, nullptr); + ret = store->GetDBSyncCompleteCB(asyncs); + EXPECT_NE(ret, nullptr); +} + +/** +* @tc.name: CloudSync +* @tc.desc: CloudSync test the functionality of different branches. +* @tc.type: FUNC +* @tc.require: +* @tc.author: SQL +*/ +HWTEST_F(KVDBGeneralStoreTest, CloudSync, TestSize.Level0) +{ + auto store = new (std::nothrow) KVDBGeneralStore(metaData_); + ASSERT_NE(store, nullptr); + store->SetEqualIdentifier(bundleName, storeName); + KvStoreNbDelegateMock mockDelegate; + store->delegate_ = &mockDelegate; + std::vector devices = {"device1", "device2"}; + auto asyncs = [](const GenDetails &result) {}; + store->storeInfo_.user = 0; + auto cloudSyncMode = DistributedDB::SyncMode::SYNC_MODE_PUSH_ONLY; + store->SetEqualIdentifier(bundleName, storeName); + auto ret = store->CloudSync(devices, cloudSyncMode, asyncs, 0); + EXPECT_EQ(ret, DBStatus::OK); + + store->storeInfo_.user = 1; + cloudSyncMode = DistributedDB::SyncMode::SYNC_MODE_CLOUD_FORCE_PUSH; + ret = store->CloudSync(devices, cloudSyncMode, asyncs, 0); + EXPECT_EQ(ret, DBStatus::OK); +} + +/** +* @tc.name: Sync +* @tc.desc: Sync test the functionality of different branches. +* @tc.type: FUNC +* @tc.require: +* @tc.author: SQL +*/ +HWTEST_F(KVDBGeneralStoreTest, Sync, TestSize.Level0) +{ + mkdir(("/data/service/el1/public/database/" + std::string(bundleName)).c_str(), + (S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH)); + auto store = new (std::nothrow) KVDBGeneralStore(metaData_); + ASSERT_NE(store, nullptr); + uint32_t syncMode = GeneralStore::SyncMode::CLOUD_BEGIN; + uint32_t highMode = GeneralStore::HighMode::MANUAL_SYNC_MODE; + auto mixMode = GeneralStore::MixMode(syncMode, highMode); + std::string kvQuery = ""; + DistributedKv::KVDBQuery query(kvQuery); + SyncParam syncParam{}; + syncParam.mode = mixMode; + KvStoreNbDelegateMock mockDelegate; + store->delegate_ = &mockDelegate; + auto ret = store->Sync({}, query, [](const GenDetails &result) {}, syncParam); + EXPECT_EQ(ret, GeneralError::E_NOT_SUPPORT); + GeneralStore::StoreConfig storeConfig; + storeConfig.enableCloud_ = true; + store->SetConfig(storeConfig); + ret = store->Sync({}, query, [](const GenDetails &result) {}, syncParam); + EXPECT_EQ(ret, GeneralError::E_OK); + + syncMode = GeneralStore::SyncMode::NEARBY_END; + mixMode = GeneralStore::MixMode(syncMode, highMode); + syncParam.mode = mixMode; + ret = store->Sync({}, query, [](const GenDetails &result) {}, syncParam); + EXPECT_EQ(ret, GeneralError::E_INVALID_ARGS); + + std::vector devices = {"device1", "device2"}; + syncMode = GeneralStore::SyncMode::NEARBY_SUBSCRIBE_REMOTE; + mixMode = GeneralStore::MixMode(syncMode, highMode); + syncParam.mode = mixMode; + ret = store->Sync(devices, query, [](const GenDetails &result) {}, syncParam); + EXPECT_EQ(ret, GeneralError::E_OK); + + syncMode = GeneralStore::SyncMode::NEARBY_UNSUBSCRIBE_REMOTE; + mixMode = GeneralStore::MixMode(syncMode, highMode); + syncParam.mode = mixMode; + ret = store->Sync(devices, query, [](const GenDetails &result) {}, syncParam); + EXPECT_EQ(ret, GeneralError::E_OK); + + syncMode = GeneralStore::SyncMode::NEARBY_PULL_PUSH; + mixMode = GeneralStore::MixMode(syncMode, highMode); + syncParam.mode = mixMode; + ret = store->Sync(devices, query, [](const GenDetails &result) {}, syncParam); + EXPECT_EQ(ret, GeneralError::E_OK); + + syncMode = GeneralStore::SyncMode::MODE_BUTT; + mixMode = GeneralStore::MixMode(syncMode, highMode); + syncParam.mode = mixMode; + ret = store->Sync(devices, query, [](const GenDetails &result) {}, syncParam); + EXPECT_EQ(ret, GeneralError::E_ERROR); +} + +/** +* @tc.name: Clean +* @tc.desc: Clean test the functionality of different branches. +* @tc.type: FUNC +* @tc.require: +* @tc.author: SQL +*/ +HWTEST_F(KVDBGeneralStoreTest, Clean, TestSize.Level0) +{ + auto store = new (std::nothrow) KVDBGeneralStore(metaData_); + ASSERT_NE(store, nullptr); + std::vector devices = {"device1", "device2"}; + std::string tableName = "tableName"; + auto ret = store->Clean(devices, -1, tableName); + EXPECT_EQ(ret, GeneralError::E_INVALID_ARGS); + ret = store->Clean(devices, 5, tableName); + EXPECT_EQ(ret, GeneralError::E_INVALID_ARGS); + ret = store->Clean(devices, GeneralStore::CleanMode::NEARBY_DATA, tableName); + EXPECT_EQ(ret, GeneralError::E_ALREADY_CLOSED); + + KvStoreNbDelegateMock mockDelegate; + store->delegate_ = &mockDelegate; + ret = store->Clean(devices, GeneralStore::CleanMode::CLOUD_INFO, tableName); + EXPECT_EQ(ret, GeneralError::E_OK); + + ret = store->Clean(devices, GeneralStore::CleanMode::CLOUD_DATA, tableName); + EXPECT_EQ(ret, GeneralError::E_OK); + + ret = store->Clean({}, GeneralStore::CleanMode::NEARBY_DATA, tableName); + EXPECT_EQ(ret, GeneralError::E_OK); + ret = store->Clean(devices, GeneralStore::CleanMode::NEARBY_DATA, tableName); + EXPECT_EQ(ret, GeneralError::E_OK); + + ret = store->Clean(devices, GeneralStore::CleanMode::LOCAL_DATA, tableName); + EXPECT_EQ(ret, GeneralError::E_ERROR); +} + +/** +* @tc.name: Watch +* @tc.desc: Watch and Unwatch test the functionality of different branches. +* @tc.type: FUNC +* @tc.require: +* @tc.author: SQL +*/ +HWTEST_F(KVDBGeneralStoreTest, Watch, TestSize.Level0) +{ + auto store = new (std::nothrow) KVDBGeneralStore(metaData_); + ASSERT_NE(store, nullptr); + DistributedDataTest::MockGeneralWatcher watcher; + auto ret = store->Watch(GeneralWatcher::Origin::ORIGIN_CLOUD, watcher); + EXPECT_EQ(ret, GeneralError::E_INVALID_ARGS); + ret = store->Unwatch(GeneralWatcher::Origin::ORIGIN_CLOUD, watcher); + EXPECT_EQ(ret, GeneralError::E_INVALID_ARGS); + + ret = store->Watch(GeneralWatcher::Origin::ORIGIN_ALL, watcher); + EXPECT_EQ(ret, GeneralError::E_OK); + ret = store->Watch(GeneralWatcher::Origin::ORIGIN_ALL, watcher); + EXPECT_EQ(ret, GeneralError::E_INVALID_ARGS); + + ret = store->Unwatch(GeneralWatcher::Origin::ORIGIN_ALL, watcher); + EXPECT_EQ(ret, GeneralError::E_OK); + ret = store->Unwatch(GeneralWatcher::Origin::ORIGIN_ALL, watcher); + EXPECT_EQ(ret, GeneralError::E_INVALID_ARGS); +} + +/** +* @tc.name: Release +* @tc.desc: Release and AddRef test the functionality of different branches. +* @tc.type: FUNC +* @tc.require: +* @tc.author: SQL +*/ +HWTEST_F(KVDBGeneralStoreTest, Release, TestSize.Level0) +{ + auto store = new (std::nothrow) KVDBGeneralStore(metaData_); + ASSERT_NE(store, nullptr); + auto ret = store->Release(); + EXPECT_EQ(ret, 0); + store = new (std::nothrow) KVDBGeneralStore(metaData_); + store->ref_ = 0; + ret = store->Release(); + EXPECT_EQ(ret, 0); + store->ref_ = 2; + ret = store->Release(); + EXPECT_EQ(ret, 1); + + ret = store->AddRef(); + EXPECT_EQ(ret, 2); + store->ref_ = 0; + ret = store->AddRef(); + EXPECT_EQ(ret, 0); +} + +/** +* @tc.name: ConvertStatus +* @tc.desc: ConvertStatus test the functionality of different branches. +* @tc.type: FUNC +* @tc.require: +* @tc.author: SQL +*/ +HWTEST_F(KVDBGeneralStoreTest, ConvertStatus, TestSize.Level0) +{ + auto store = new (std::nothrow) KVDBGeneralStore(metaData_); + ASSERT_NE(store, nullptr); + auto ret = store->ConvertStatus(DBStatus::OK); + EXPECT_EQ(ret, GeneralError::E_OK); + ret = store->ConvertStatus(DBStatus::CLOUD_NETWORK_ERROR); + EXPECT_EQ(ret, GeneralError::E_NETWORK_ERROR); + ret = store->ConvertStatus(DBStatus::CLOUD_LOCK_ERROR); + EXPECT_EQ(ret, GeneralError::E_LOCKED_BY_OTHERS); + ret = store->ConvertStatus(DBStatus::CLOUD_FULL_RECORDS); + EXPECT_EQ(ret, GeneralError::E_RECODE_LIMIT_EXCEEDED); + ret = store->ConvertStatus(DBStatus::CLOUD_ASSET_SPACE_INSUFFICIENT); + EXPECT_EQ(ret, GeneralError::E_NO_SPACE_FOR_ASSET); + ret = store->ConvertStatus(DBStatus::CLOUD_SYNC_TASK_MERGED); + EXPECT_EQ(ret, GeneralError::E_SYNC_TASK_MERGED); + ret = store->ConvertStatus(DBStatus::DB_ERROR); + EXPECT_EQ(ret, GeneralError::E_ERROR); +} + +/** +* @tc.name: GetWaterVersion +* @tc.desc: GetWaterVersion test the functionality of different branches. +* @tc.type: FUNC +* @tc.require: +* @tc.author: SQL +*/ +HWTEST_F(KVDBGeneralStoreTest, GetWaterVersion, TestSize.Level0) +{ + auto store = new (std::nothrow) KVDBGeneralStore(metaData_); + ASSERT_NE(store, nullptr); + std::string deviceId = "deviceId"; + std::vector res = {}; + auto ret = store->GetWaterVersion(deviceId); + EXPECT_EQ(ret, res); + KvStoreNbDelegateMock mockDelegate; + store->delegate_ = &mockDelegate; + ret = store->GetWaterVersion(""); + EXPECT_EQ(ret, res); + ret = store->GetWaterVersion("test"); + EXPECT_EQ(ret, res); + ret = store->GetWaterVersion("device"); + EXPECT_EQ(ret, res); + res = {"deviceId"}; + ret = store->GetWaterVersion(deviceId); + EXPECT_EQ(ret, res); +} + +/** +* @tc.name: OnChange +* @tc.desc: OnChange test the functionality of different branches. +* @tc.type: FUNC +* @tc.require: +* @tc.author: SQL +*/ +HWTEST_F(KVDBGeneralStoreTest, OnChange, TestSize.Level0) +{ + auto store = new (std::nothrow) KVDBGeneralStore(metaData_); + ASSERT_NE(store, nullptr); + DistributedDataTest::MockGeneralWatcher watcher; + DistributedDataTest::MockKvStoreChangedData data; + DistributedDB::ChangedData changedData; + store->observer_.OnChange(data); + store->observer_.OnChange(DistributedDB::Origin::ORIGIN_CLOUD, "originalId", std::move(changedData)); + auto result = store->Watch(GeneralWatcher::Origin::ORIGIN_ALL, watcher); + EXPECT_EQ(result, GeneralError::E_OK); + store->observer_.OnChange(data); + store->observer_.OnChange(DistributedDB::Origin::ORIGIN_CLOUD, "originalId", std::move(changedData)); + result = store->Unwatch(GeneralWatcher::Origin::ORIGIN_ALL, watcher); + EXPECT_EQ(result, GeneralError::E_OK); +} + +/** +* @tc.name: Delete +* @tc.desc: Delete test the function. +* @tc.type: FUNC +* @tc.require: +* @tc.author: SQL +*/ +HWTEST_F(KVDBGeneralStoreTest, Delete, TestSize.Level0) +{ + auto store = new (std::nothrow) KVDBGeneralStore(metaData_); + ASSERT_NE(store, nullptr); + KvStoreNbDelegateMock mockDelegate; + store->delegate_ = &mockDelegate; + store->SetDBPushDataInterceptor(DistributedKv::KvStoreType::DEVICE_COLLABORATION); + store->SetDBReceiveDataInterceptor(DistributedKv::KvStoreType::DEVICE_COLLABORATION); + DistributedData::VBuckets values; + auto ret = store->Insert("table", std::move(values)); + EXPECT_EQ(ret, GeneralError::E_NOT_SUPPORT); + + DistributedData::Values args; + store->SetDBPushDataInterceptor(DistributedKv::KvStoreType::SINGLE_VERSION); + store->SetDBReceiveDataInterceptor(DistributedKv::KvStoreType::SINGLE_VERSION); + ret = store->Delete("table", "sql", std::move(args)); + EXPECT_EQ(ret, GeneralError::E_NOT_SUPPORT); +} + +/** +* @tc.name: Query001 +* @tc.desc: KVDBGeneralStoreTest Query function test +* @tc.type: FUNC +* @tc.require: +* @tc.author: SQL +*/ +HWTEST_F(KVDBGeneralStoreTest, Query001, TestSize.Level1) +{ + auto store = new (std::nothrow) KVDBGeneralStore(metaData_); + ASSERT_NE(store, nullptr); + std::string table = "table"; + std::string sql = "sql"; + auto [errCode, result] = store->Query(table, sql, {}); + EXPECT_EQ(errCode, GeneralError::E_NOT_SUPPORT); + EXPECT_EQ(result, nullptr); +} + +/** +* @tc.name: Query002 +* @tc.desc: KVDBGeneralStoreTest Query function test +* @tc.type: FUNC +* @tc.require: +* @tc.author: SQL +*/ +HWTEST_F(KVDBGeneralStoreTest, Query002, TestSize.Level1) +{ + auto store = new (std::nothrow) KVDBGeneralStore(metaData_); + ASSERT_NE(store, nullptr); + std::string table = "table"; + MockQuery query; + auto [errCode, result] = store->Query(table, query); + EXPECT_EQ(errCode, GeneralError::E_NOT_SUPPORT); + EXPECT_EQ(result, nullptr); +} } // namespace DistributedDataTest -} // namespace OHOS::Test +} // namespace OHOS::Test \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/test/kvdb_service_impl_test.cpp b/datamgr_service/services/distributeddataservice/service/test/kvdb_service_impl_test.cpp index 6360e4cd96331db454ecc2523e73d50c33a7b4ea..2fb8c1861498c822b262e714aba05a6a8d0fe72a 100644 --- a/datamgr_service/services/distributeddataservice/service/test/kvdb_service_impl_test.cpp +++ b/datamgr_service/services/distributeddataservice/service/test/kvdb_service_impl_test.cpp @@ -1,5 +1,5 @@ /* -* Copyright (c) 2022 Huawei Device Co., Ltd. +* Copyright (c) 2024 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -16,32 +16,40 @@ #include #include "log_print.h" #include "accesstoken_kit.h" +#include "bootstrap.h" +#include "checker/checker_manager.h" +#include "distributed_kv_data_manager.h" +#include "device_manager_adapter.h" +#include "ipc_skeleton.h" #include "nativetoken_kit.h" - +#include "kvdb_service_impl.h" #include "kvdb_service_stub.h" -#include "checker/checker_manager.h" +#include "kvstore_death_recipient.h" +#include "kvstore_meta_manager.h" #include "utils/constant.h" #include "utils/anonymous.h" -#include "distributed_kv_data_manager.h" - -#include -#include "kvstore_death_recipient.h" +#include "token_setproc.h" #include "types.h" -#include "kvdb_service_impl.h" +#include using namespace testing::ext; using namespace OHOS::DistributedData; using namespace OHOS::Security::AccessToken; - -using Status = OHOS::DistributedKv::Status; +using Action = OHOS::DistributedData::MetaDataManager::Action; +using AppId = OHOS::DistributedKv::AppId; +using ChangeType = OHOS::DistributedData::DeviceMatrix::ChangeType; +using DistributedKvDataManager = OHOS::DistributedKv::DistributedKvDataManager; +using DBStatus = DistributedDB::DBStatus; +using DBMode = DistributedDB::SyncMode; using Options = OHOS::DistributedKv::Options; +using Status = OHOS::DistributedKv::Status; using SingleKvStore = OHOS::DistributedKv::SingleKvStore; -using DistributedKvDataManager = OHOS::DistributedKv::DistributedKvDataManager; -using UserId = OHOS::DistributedKv::UserId; - using StoreId = OHOS::DistributedKv::StoreId; -using AppId = OHOS::DistributedKv::AppId; using SyncInfo = OHOS::DistributedKv::KVDBService::SyncInfo; +using SyncMode = OHOS::DistributedKv::SyncMode; +using SyncAction = OHOS::DistributedKv::KVDBServiceImpl::SyncAction; +using SwitchState = OHOS::DistributedKv::SwitchState; +using UserId = OHOS::DistributedKv::UserId; static OHOS::DistributedKv::StoreId storeId = { "kvdb_test_storeid" }; static OHOS::DistributedKv::AppId appId = { "ohos.test.kvdb" }; @@ -90,7 +98,6 @@ void KvdbServiceImplTest::SetUpTestCase(void) { auto executors = std::make_shared(NUM_MAX, NUM_MIN); manager.SetExecutors(executors); - userId.userId = "kvdbserviceimpltest1"; appId.appId = "ohos.kvdbserviceimpl.test"; create.createIfMissing = true; @@ -128,6 +135,45 @@ void KvdbServiceImplTest::TearDown(void) KvdbServiceImplTest::KvdbServiceImplTest(void) {} +/** +* @tc.name: KvdbServiceImpl001 +* @tc.desc: KvdbServiceImplTest function test. +* @tc.type: FUNC +* @tc.author: SQL +*/ +HWTEST_F(KvdbServiceImplTest, KvdbServiceImpl001, TestSize.Level0) +{ + std::string device = "OH_device_test"; + StoreId id1; + id1.storeId = "id1"; + Status status = manager.GetSingleKvStore(create, appId, id1, kvStore); + EXPECT_NE(kvStore, nullptr); + EXPECT_EQ(status, Status::SUCCESS); + int32_t result = kvdbServiceImpl_->OnInitialize(); + EXPECT_EQ(result, Status::SUCCESS); + FeatureSystem::Feature::BindInfo bindInfo; + result = kvdbServiceImpl_->OnBind(bindInfo); + EXPECT_EQ(result, Status::SUCCESS); + result = kvdbServiceImpl_->Online(device); + EXPECT_EQ(result, Status::SUCCESS); + status = kvdbServiceImpl_->SubscribeSwitchData(appId); + EXPECT_EQ(status, Status::SUCCESS); + SyncInfo syncInfo; + status = kvdbServiceImpl_->CloudSync(appId, id1, syncInfo); + EXPECT_EQ(status, Status::INVALID_ARGUMENT); + + DistributedKv::StoreConfig storeConfig; + status = kvdbServiceImpl_->SetConfig(appId, id1, storeConfig); + EXPECT_EQ(status, Status::SUCCESS); + status = kvdbServiceImpl_->NotifyDataChange(appId, id1, 0); + EXPECT_EQ(status, Status::INVALID_ARGUMENT); + + status = kvdbServiceImpl_->UnsubscribeSwitchData(appId); + EXPECT_EQ(status, Status::SUCCESS); + status = kvdbServiceImpl_->Close(appId, id1); + EXPECT_EQ(status, Status::SUCCESS); +} + /** * @tc.name: GetStoreIdsTest001 * @tc.desc: GetStoreIds @@ -536,6 +582,218 @@ HWTEST_F(KvdbServiceImplTest, OnReadyTest001, TestSize.Level0) auto status = kvdbServiceImpl_->OnReady(device); ZLOGI("OnReadyTest001 status = :%{public}d", status); ASSERT_EQ(status, Status::SUCCESS); + status = kvdbServiceImpl_->OnSessionReady(device); + ASSERT_EQ(status, Status::SUCCESS); +} + +/** +* @tc.name: ResolveAutoLaunch +* @tc.desc: ResolveAutoLaunch function test. +* @tc.type: FUNC +* @tc.author: SQL +*/ +HWTEST_F(KvdbServiceImplTest, ResolveAutoLaunch, TestSize.Level0) +{ + StoreId id1; + id1.storeId = "id1"; + Status status = manager.GetSingleKvStore(create, appId, id1, kvStore); + EXPECT_NE(kvStore, nullptr); + EXPECT_EQ(status, Status::SUCCESS); + std::string identifier = "identifier"; + DistributedKv::KVDBServiceImpl::DBLaunchParam launchParam; + auto result = kvdbServiceImpl_->ResolveAutoLaunch(identifier, launchParam); + EXPECT_EQ(result, Status::STORE_NOT_FOUND); + std::shared_ptr executors = std::make_shared(1, 0); + Bootstrap::GetInstance().LoadDirectory(); + Bootstrap::GetInstance().LoadCheckers(); + DistributedKv::KvStoreMetaManager::GetInstance().BindExecutor(executors); + DistributedKv::KvStoreMetaManager::GetInstance().InitMetaParameter(); + DistributedKv::KvStoreMetaManager::GetInstance().InitMetaListener(); + result = kvdbServiceImpl_->ResolveAutoLaunch(identifier, launchParam); + EXPECT_EQ(result, Status::SUCCESS); +} + +/** +* @tc.name: PutSwitch +* @tc.desc: PutSwitch function test. +* @tc.type: FUNC +* @tc.author: SQL +*/ +HWTEST_F(KvdbServiceImplTest, PutSwitch, TestSize.Level0) +{ + StoreId id1; + id1.storeId = "id1"; + Status status = manager.GetSingleKvStore(create, appId, id1, kvStore); + ASSERT_NE(kvStore, nullptr); + ASSERT_EQ(status, Status::SUCCESS); + DistributedKv::SwitchData switchData; + status = kvdbServiceImpl_->PutSwitch(appId, switchData); + EXPECT_EQ(status, Status::INVALID_ARGUMENT); + switchData.value = DeviceMatrix::INVALID_VALUE; + switchData.length = DeviceMatrix::INVALID_LEVEL; + status = kvdbServiceImpl_->PutSwitch(appId, switchData); + EXPECT_EQ(status, Status::INVALID_ARGUMENT); + switchData.value = DeviceMatrix::INVALID_MASK; + switchData.length = DeviceMatrix::INVALID_LENGTH; + status = kvdbServiceImpl_->PutSwitch(appId, switchData); + EXPECT_EQ(status, Status::INVALID_ARGUMENT); + switchData.value = DeviceMatrix::INVALID_VALUE; + switchData.length = DeviceMatrix::INVALID_LENGTH; + status = kvdbServiceImpl_->PutSwitch(appId, switchData); + EXPECT_EQ(status, Status::INVALID_ARGUMENT); + switchData.value = DeviceMatrix::INVALID_MASK; + switchData.length = DeviceMatrix::INVALID_LEVEL; + status = kvdbServiceImpl_->PutSwitch(appId, switchData); + EXPECT_EQ(status, Status::SUCCESS); + std::string networkId = "networkId"; + status = kvdbServiceImpl_->GetSwitch(appId, networkId, switchData); + EXPECT_EQ(status, Status::INVALID_ARGUMENT); +} + +/** +* @tc.name: DoCloudSync +* @tc.desc: DoCloudSync error function test. +* @tc.type: FUNC +* @tc.author: SQL +*/ +HWTEST_F(KvdbServiceImplTest, DoCloudSync, TestSize.Level0) +{ + StoreId id1; + id1.storeId = "id1"; + Status status = manager.GetSingleKvStore(create, appId, id1, kvStore); + ASSERT_NE(kvStore, nullptr); + ASSERT_EQ(status, Status::SUCCESS); + StoreMetaData metaData; + SyncInfo syncInfo; + status = kvdbServiceImpl_->DoCloudSync(metaData, syncInfo); + EXPECT_EQ(status, Status::NOT_SUPPORT); + syncInfo.devices = {"device1", "device2"}; + syncInfo.query = "query"; + metaData.enableCloud = true; + status = kvdbServiceImpl_->DoCloudSync(metaData, syncInfo); + EXPECT_EQ(status, Status::CLOUD_DISABLED); +} + +/** +* @tc.name: ConvertDbStatus +* @tc.desc: ConvertDbStatus test the return result of input with different values. +* @tc.type: FUNC +* @tc.author: SQL +*/ +HWTEST_F(KvdbServiceImplTest, ConvertDbStatus, TestSize.Level0) +{ + EXPECT_EQ(kvdbServiceImpl_->ConvertDbStatus(DBStatus::BUSY), Status::DB_ERROR); + EXPECT_EQ(kvdbServiceImpl_->ConvertDbStatus(DBStatus::DB_ERROR), Status::DB_ERROR); + EXPECT_EQ(kvdbServiceImpl_->ConvertDbStatus(DBStatus::OK), Status::SUCCESS); + EXPECT_EQ(kvdbServiceImpl_->ConvertDbStatus(DBStatus::INVALID_ARGS), Status::INVALID_ARGUMENT); + EXPECT_EQ(kvdbServiceImpl_->ConvertDbStatus(DBStatus::NOT_FOUND), Status::KEY_NOT_FOUND); + EXPECT_EQ(kvdbServiceImpl_->ConvertDbStatus(DBStatus::INVALID_VALUE_FIELDS), Status::INVALID_VALUE_FIELDS); + EXPECT_EQ(kvdbServiceImpl_->ConvertDbStatus(DBStatus::INVALID_FIELD_TYPE), Status::INVALID_FIELD_TYPE); + EXPECT_EQ(kvdbServiceImpl_->ConvertDbStatus(DBStatus::CONSTRAIN_VIOLATION), Status::CONSTRAIN_VIOLATION); + EXPECT_EQ(kvdbServiceImpl_->ConvertDbStatus(DBStatus::INVALID_FORMAT), Status::INVALID_FORMAT); + EXPECT_EQ(kvdbServiceImpl_->ConvertDbStatus(DBStatus::INVALID_QUERY_FORMAT), Status::INVALID_QUERY_FORMAT); + EXPECT_EQ(kvdbServiceImpl_->ConvertDbStatus(DBStatus::INVALID_QUERY_FIELD), Status::INVALID_QUERY_FIELD); + EXPECT_EQ(kvdbServiceImpl_->ConvertDbStatus(DBStatus::NOT_SUPPORT), Status::NOT_SUPPORT); + EXPECT_EQ(kvdbServiceImpl_->ConvertDbStatus(DBStatus::TIME_OUT), Status::TIME_OUT); + EXPECT_EQ(kvdbServiceImpl_->ConvertDbStatus(DBStatus::OVER_MAX_LIMITS), Status::OVER_MAX_LIMITS); + EXPECT_EQ(kvdbServiceImpl_->ConvertDbStatus(DBStatus::EKEYREVOKED_ERROR), Status::SECURITY_LEVEL_ERROR); + EXPECT_EQ(kvdbServiceImpl_->ConvertDbStatus(DBStatus::SECURITY_OPTION_CHECK_ERROR), Status::SECURITY_LEVEL_ERROR); + EXPECT_EQ(kvdbServiceImpl_->ConvertDbStatus(DBStatus::SCHEMA_VIOLATE_VALUE), Status::ERROR); +} + +/** +* @tc.name: ConvertDBMode +* @tc.desc: ConvertDBMode test the return result of input with different values. +* @tc.type: FUNC +* @tc.author: SQL +*/ +HWTEST_F(KvdbServiceImplTest, ConvertDBMode, TestSize.Level0) +{ + auto status = kvdbServiceImpl_->ConvertDBMode(SyncMode::PUSH); + EXPECT_EQ(status, DBMode::SYNC_MODE_PUSH_ONLY); + status = kvdbServiceImpl_->ConvertDBMode(SyncMode::PULL); + EXPECT_EQ(status, DBMode::SYNC_MODE_PULL_ONLY); + status = kvdbServiceImpl_->ConvertDBMode(SyncMode::PUSH_PULL); + EXPECT_EQ(status, DBMode::SYNC_MODE_PUSH_PULL); +} + +/** +* @tc.name: ConvertGeneralSyncMode +* @tc.desc: ConvertGeneralSyncMode test the return result of input with different values. +* @tc.type: FUNC +* @tc.author: SQL +*/ +HWTEST_F(KvdbServiceImplTest, ConvertGeneralSyncMode, TestSize.Level0) +{ + auto status = kvdbServiceImpl_->ConvertGeneralSyncMode(SyncMode::PUSH, SyncAction::ACTION_SUBSCRIBE); + EXPECT_EQ(status, GeneralStore::SyncMode::NEARBY_SUBSCRIBE_REMOTE); + status = kvdbServiceImpl_->ConvertGeneralSyncMode(SyncMode::PUSH, SyncAction::ACTION_UNSUBSCRIBE); + EXPECT_EQ(status, GeneralStore::SyncMode::NEARBY_UNSUBSCRIBE_REMOTE); + status = kvdbServiceImpl_->ConvertGeneralSyncMode(SyncMode::PUSH, SyncAction::ACTION_SYNC); + EXPECT_EQ(status, GeneralStore::SyncMode::NEARBY_PUSH); + status = kvdbServiceImpl_->ConvertGeneralSyncMode(SyncMode::PULL, SyncAction::ACTION_SYNC); + EXPECT_EQ(status, GeneralStore::SyncMode::NEARBY_PULL); + status = kvdbServiceImpl_->ConvertGeneralSyncMode(SyncMode::PUSH_PULL, SyncAction::ACTION_SYNC); + EXPECT_EQ(status, GeneralStore::SyncMode::NEARBY_PULL_PUSH); + auto action = static_cast(SyncAction::ACTION_UNSUBSCRIBE + 1); + status = kvdbServiceImpl_->ConvertGeneralSyncMode(SyncMode::PUSH, action); + EXPECT_EQ(status, GeneralStore::SyncMode::NEARBY_END); +} + +/** +* @tc.name: ConvertType +* @tc.desc: ConvertType test the return result of input with different values. +* @tc.type: FUNC +* @tc.author: SQL +*/ +HWTEST_F(KvdbServiceImplTest, ConvertType, TestSize.Level0) +{ + auto status = kvdbServiceImpl_->ConvertType(SyncMode::PUSH); + EXPECT_EQ(status, ChangeType::CHANGE_LOCAL); + status = kvdbServiceImpl_->ConvertType(SyncMode::PULL); + EXPECT_EQ(status, ChangeType::CHANGE_REMOTE); + status = kvdbServiceImpl_->ConvertType(SyncMode::PUSH_PULL); + EXPECT_EQ(status, ChangeType::CHANGE_ALL); + auto action = static_cast(SyncMode::PUSH_PULL + 1); + status = kvdbServiceImpl_->ConvertType(action); + EXPECT_EQ(status, ChangeType::CHANGE_ALL); +} + +/** +* @tc.name: ConvertAction +* @tc.desc: ConvertAction test the return result of input with different values. +* @tc.type: FUNC +* @tc.author: SQL +*/ +HWTEST_F(KvdbServiceImplTest, ConvertAction, TestSize.Level0) +{ + auto status = kvdbServiceImpl_->ConvertAction(Action::INSERT); + EXPECT_EQ(status, SwitchState::INSERT); + status = kvdbServiceImpl_->ConvertAction(Action::UPDATE); + EXPECT_EQ(status, SwitchState::UPDATE); + status = kvdbServiceImpl_->ConvertAction(Action::DELETE); + EXPECT_EQ(status, SwitchState::DELETE); + auto action = static_cast(Action::DELETE + 1); + status = kvdbServiceImpl_->ConvertAction(action); + EXPECT_EQ(status, SwitchState::INSERT); +} + +/** +* @tc.name: GetSyncMode +* @tc.desc: GetSyncMode test the return result of input with different values. +* @tc.type: FUNC +* @tc.author: SQL +*/ +HWTEST_F(KvdbServiceImplTest, GetSyncMode, TestSize.Level0) +{ + auto status = kvdbServiceImpl_->GetSyncMode(true, true); + EXPECT_EQ(status, SyncMode::PUSH_PULL); + status = kvdbServiceImpl_->GetSyncMode(true, false); + EXPECT_EQ(status, SyncMode::PUSH); + status = kvdbServiceImpl_->GetSyncMode(false, true); + EXPECT_EQ(status, SyncMode::PULL); + status = kvdbServiceImpl_->GetSyncMode(false, false); + EXPECT_EQ(status, SyncMode::PUSH_PULL); } } // namespace DistributedDataTest -} // namespace OHOS::Test +} // namespace OHOS::Test \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/test/kvdb_service_test.cpp b/datamgr_service/services/distributeddataservice/service/test/kvdb_service_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..026b9c039349a5cf5d5544bdc8b270d98d0d45b9 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/test/kvdb_service_test.cpp @@ -0,0 +1,685 @@ +/* +* Copyright (c) 2024 Huawei Device Co., Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#include +#include "log_print.h" +#include "accesstoken_kit.h" +#include "auth_delegate.h" +#include "bootstrap.h" +#include "crypto_manager.h" +#include "device_manager_adapter.h" +#include "directory/directory_manager.h" +#include "metadata/meta_data_manager.h" +#include "metadata/secret_key_meta_data.h" +#include "metadata/store_meta_data.h" +#include "metadata/store_meta_data_local.h" +#include "query_helper.h" +#include "upgrade.h" +#include "user_delegate.h" +#include "kvdb_general_store.h" +#include "kvdb_watcher.h" +#include "kvdb_notifier_proxy.h" +#include "kvstore_sync_manager.h" +#include "kvstore_meta_manager.h" + +using namespace testing::ext; +using namespace DistributedDB; +using namespace OHOS::DistributedData; +using StoreMetaData = OHOS::DistributedData::StoreMetaData; +using DBPassword = DistributedDB::CipherPassword; +using DBStatus = DistributedDB::DBStatus; +using Status = OHOS::DistributedKv::Status; +using KVDBWatcher = OHOS::DistributedKv::KVDBWatcher; +using KVDBNotifierProxy = OHOS::DistributedKv::KVDBNotifierProxy; +using QueryHelper = OHOS::DistributedKv::QueryHelper; +namespace OHOS::Test { +namespace DistributedDataTest { +class UpgradeTest : public testing::Test { +public: + static void SetUpTestCase(void){}; + static void TearDownTestCase(void){}; + void SetUp(); + void TearDown(){}; +protected: + static constexpr const char *bundleName = "test_upgrade"; + static constexpr const char *storeName = "test_upgrade_meta"; + void InitMetaData(); + StoreMetaData metaData_; +}; + +void UpgradeTest::InitMetaData() +{ + metaData_.bundleName = bundleName; + metaData_.appId = bundleName; + metaData_.user = "0"; + metaData_.area = OHOS::DistributedKv::EL1; + metaData_.instanceId = 0; + metaData_.isAutoSync = true; + metaData_.storeType = DistributedKv::KvStoreType::SINGLE_VERSION; + metaData_.storeId = storeName; + metaData_.dataDir = "/data/service/el1/public/database/" + std::string(bundleName) + "/kvdb/upgrade"; + metaData_.securityLevel = DistributedKv::SecurityLevel::S2; +} + +void UpgradeTest::SetUp() +{ + Bootstrap::GetInstance().LoadDirectory(); + InitMetaData(); +} + +class KvStoreSyncManagerTest : public testing::Test { +public: + static void SetUpTestCase(void){}; + static void TearDownTestCase(void){}; + void SetUp(){}; + void TearDown(){}; +protected: +}; + +class KVDBWatcherTest : public testing::Test { +public: + static void SetUpTestCase(void){}; + static void TearDownTestCase(void){}; + void SetUp(){}; + void TearDown(){}; +protected: +}; + +class UserDelegateTest : public testing::Test { +public: + static void SetUpTestCase(void){}; + static void TearDownTestCase(void){}; + void SetUp(){}; + void TearDown(){}; +protected: +}; + +class QueryHelperTest : public testing::Test { +public: + static void SetUpTestCase(void){}; + static void TearDownTestCase(void){}; + void SetUp(){}; + void TearDown(){}; +protected: +}; + +class AuthHandlerTest : public testing::Test { +public: + static void SetUpTestCase(void){}; + static void TearDownTestCase(void){}; + void SetUp(){}; + void TearDown(){}; +protected: +}; + +/** +* @tc.name: UpdateStore +* @tc.desc: UpdateStore test the return result of input with different values. +* @tc.type: FUNC +* @tc.author: SQL +*/ +HWTEST_F(UpgradeTest, UpdateStore, TestSize.Level0) +{ + DistributedKv::Upgrade upgrade; + StoreMetaData oldMeta = metaData_; + oldMeta.version = 1; + oldMeta.storeType = DistributedKv::KvStoreType::DEVICE_COLLABORATION; + oldMeta.dataDir = "/data/service/el1/public/database/" + std::string(bundleName) + "/kvdb/upgrade/old"; + std::vector password = {0x01, 0x02, 0x03}; + auto dbStatus = upgrade.UpdateStore(oldMeta, metaData_, password); + EXPECT_EQ(dbStatus, DBStatus::DB_ERROR); + + oldMeta.version = StoreMetaData::CURRENT_VERSION; + dbStatus = upgrade.UpdateStore(oldMeta, metaData_, password); + EXPECT_EQ(dbStatus, DBStatus::NOT_SUPPORT); + + oldMeta.storeType = DistributedKv::KvStoreType::SINGLE_VERSION; + DistributedKv::Upgrade::Exporter exporter = [](const StoreMetaData &, DBPassword &) { + return "testexporter"; + }; + upgrade.exporter_ = exporter; + dbStatus = upgrade.UpdateStore(oldMeta, metaData_, password); + EXPECT_EQ(dbStatus, DBStatus::NOT_SUPPORT); + + oldMeta.version = 1; + DistributedKv::Upgrade::Cleaner cleaner = [](const StoreMetaData &meta) -> DistributedKv::Status { + return DistributedKv::Status::SUCCESS; + }; + upgrade.cleaner_ = cleaner; + upgrade.exporter_ = nullptr; + upgrade.UpdatePassword(metaData_, password); + dbStatus = upgrade.UpdateStore(oldMeta, metaData_, password); + EXPECT_EQ(dbStatus, DBStatus::NOT_SUPPORT); + + metaData_.isEncrypt = true; + upgrade.UpdatePassword(metaData_, password); + EXPECT_TRUE(upgrade.RegisterExporter(oldMeta.version, exporter)); + EXPECT_TRUE(upgrade.RegisterCleaner(oldMeta.version, cleaner)); + dbStatus = upgrade.UpdateStore(oldMeta, metaData_, password); + EXPECT_EQ(dbStatus, DBStatus::DB_ERROR); + + StoreMetaData oldMetas = metaData_; + dbStatus = upgrade.UpdateStore(oldMetas, metaData_, password); + EXPECT_EQ(dbStatus, DBStatus::OK); +} + +/** +* @tc.name: ExportStore +* @tc.desc: ExportStore test the return result of input with different values. +* @tc.type: FUNC +* @tc.author: SQL +*/ +HWTEST_F(UpgradeTest, ExportStore, TestSize.Level0) +{ + DistributedKv::Upgrade upgrade; + StoreMetaData oldMeta = metaData_; + auto dbStatus = upgrade.ExportStore(oldMeta, metaData_); + EXPECT_EQ(dbStatus, DBStatus::OK); + + oldMeta.dataDir = "/data/service/el1/public/database/" + std::string(bundleName) + "/kvdb/upgrade/old"; + dbStatus = upgrade.ExportStore(oldMeta, metaData_); + EXPECT_EQ(dbStatus, DBStatus::NOT_SUPPORT); + + DistributedKv::Upgrade::Exporter exporter = [](const StoreMetaData &, DBPassword &) { + return "testexporter"; + }; + EXPECT_TRUE(upgrade.RegisterExporter(oldMeta.version, exporter)); + dbStatus = upgrade.ExportStore(oldMeta, metaData_); + EXPECT_EQ(dbStatus, DBStatus::OK); + + DistributedKv::Upgrade::Exporter test = [](const StoreMetaData &, DBPassword &) { + return ""; + }; + EXPECT_TRUE(upgrade.RegisterExporter(oldMeta.version, test)); + dbStatus = upgrade.ExportStore(oldMeta, metaData_); + EXPECT_EQ(dbStatus, DBStatus::NOT_FOUND); +} + +/** +* @tc.name: GetEncryptedUuidByMeta +* @tc.desc: GetEncryptedUuidByMeta test the return result of input with different values. +* @tc.type: FUNC +* @tc.author: SQL +*/ +HWTEST_F(UpgradeTest, GetEncryptedUuidByMeta, TestSize.Level0) +{ + DistributedKv::Upgrade upgrade; + auto dbStatus = upgrade.GetEncryptedUuidByMeta(metaData_); + EXPECT_EQ(dbStatus, metaData_.deviceId); + metaData_.appId = ""; + dbStatus = upgrade.GetEncryptedUuidByMeta(metaData_); + EXPECT_EQ(dbStatus, metaData_.appId); +} + +/** +* @tc.name: AddSyncOperation +* @tc.desc: AddSyncOperation test the return result of input with different values. +* @tc.type: FUNC +* @tc.author: SQL +*/ +HWTEST_F(KvStoreSyncManagerTest, AddSyncOperation, TestSize.Level0) +{ + DistributedKv::KvStoreSyncManager syncManager; + uintptr_t syncId = 0; + DistributedKv::KvStoreSyncManager::SyncFunc syncFunc = nullptr; + DistributedKv::KvStoreSyncManager::SyncEnd syncEnd = nullptr; + auto kvStatus = syncManager.AddSyncOperation(syncId, 0, syncFunc, syncEnd); + EXPECT_EQ(kvStatus, Status::INVALID_ARGUMENT); + syncId = 1; + kvStatus = syncManager.AddSyncOperation(syncId, 0, syncFunc, syncEnd); + EXPECT_EQ(kvStatus, Status::INVALID_ARGUMENT); + syncFunc = [](const DistributedKv::KvStoreSyncManager::SyncEnd &callback) -> Status { + std::map status_map = + {{"key1", DBStatus::OK}, {"key2", DBStatus::DB_ERROR}}; + callback(status_map); + return Status::SUCCESS; + }; + kvStatus = syncManager.AddSyncOperation(0, 0, syncFunc, syncEnd); + EXPECT_EQ(kvStatus, Status::INVALID_ARGUMENT); +} + +/** +* @tc.name: RemoveSyncOperation +* @tc.desc: RemoveSyncOperation test the return result of input with different values. +* @tc.type: FUNC +* @tc.author: SQL +*/ +HWTEST_F(KvStoreSyncManagerTest, RemoveSyncOperation, TestSize.Level0) +{ + DistributedKv::KvStoreSyncManager syncManager; + uintptr_t syncId = 0; + auto kvStatus = syncManager.RemoveSyncOperation(syncId); + EXPECT_EQ(kvStatus, Status::ERROR); +} + +/** +* @tc.name: DoRemoveSyncingOp +* @tc.desc: DoRemoveSyncingOp test the return result of input with different values. +* @tc.type: FUNC +* @tc.author: SQL +*/ +HWTEST_F(KvStoreSyncManagerTest, GetTimeoutSyncOps, TestSize.Level0) +{ + DistributedKv::KvStoreSyncManager syncManager; + DistributedKv::KvStoreSyncManager::TimePoint currentTime = std::chrono::steady_clock::now(); + DistributedKv::KvStoreSyncManager::KvSyncOperation syncOp; + syncOp.syncId = 1; + syncOp.beginTime = std::chrono::steady_clock::now() + std::chrono::milliseconds(1); + std::list syncOps; + + EXPECT_TRUE(syncManager.realtimeSyncingOps_.empty()); + EXPECT_TRUE(syncManager.scheduleSyncOps_.empty()); + auto kvStatus = syncManager.GetTimeoutSyncOps(currentTime, syncOps); + EXPECT_EQ(kvStatus, false); + syncManager.realtimeSyncingOps_.push_back(syncOp); + kvStatus = syncManager.GetTimeoutSyncOps(currentTime, syncOps); + EXPECT_EQ(kvStatus, false); + syncManager.realtimeSyncingOps_ = syncOps; + syncManager.scheduleSyncOps_.insert(std::make_pair(syncOp.beginTime, syncOp)); + kvStatus = syncManager.GetTimeoutSyncOps(currentTime, syncOps); + EXPECT_EQ(kvStatus, false); + + syncManager.realtimeSyncingOps_.push_back(syncOp); + syncManager.scheduleSyncOps_.insert(std::make_pair(syncOp.beginTime, syncOp)); + EXPECT_TRUE(!syncManager.realtimeSyncingOps_.empty()); + EXPECT_TRUE(!syncManager.scheduleSyncOps_.empty()); + kvStatus = syncManager.GetTimeoutSyncOps(currentTime, syncOps); + EXPECT_EQ(kvStatus, true); +} + +/** +* @tc.name: KVDBWatcher +* @tc.desc: KVDBWatcher test the return result of input with different values. +* @tc.type: FUNC +* @tc.author: SQL +*/ +HWTEST_F(KVDBWatcherTest, KVDBWatcher, TestSize.Level0) +{ + GeneralWatcher::Origin origin; + GeneralWatcher::PRIFields primaryFields = {{"primaryFields1", "primaryFields2"}}; + GeneralWatcher::ChangeInfo values; + std::shared_ptr watcher = std::make_shared(); + sptr observer; + watcher->SetObserver(observer); + EXPECT_EQ(watcher->observer_, nullptr); + auto result = watcher->OnChange(origin, primaryFields, std::move(values)); + EXPECT_EQ(result, GeneralError::E_OK); + GeneralWatcher::Fields fields; + GeneralWatcher::ChangeData data; + result = watcher->OnChange(origin, fields, std::move(data)); + EXPECT_EQ(result, GeneralError::E_OK); +} + +/** +* @tc.name: ConvertToEntries +* @tc.desc: ConvertToEntries test the return result of input with different values. +* @tc.type: FUNC +* @tc.author: SQL +*/ +HWTEST_F(KVDBWatcherTest, ConvertToEntries, TestSize.Level0) +{ + std::vector values; + Values info1; + info1.emplace_back(Bytes({1, 2, 3})); + info1.emplace_back(Bytes({4, 5, 6})); + values.emplace_back(info1); + Values info2; + info2.emplace_back(Bytes({7, 8, 9})); + info2.emplace_back(Bytes({10, 11, 12})); + values.emplace_back(info2); + Values info3; + info3.emplace_back(Bytes({16, 17, 18})); + info3.emplace_back(int64_t(1)); + values.emplace_back(info3); + Values info4; + info4.emplace_back(int64_t(1)); + info4.emplace_back(Bytes({19, 20, 21})); + values.emplace_back(info4); + Values info5; + info5.emplace_back(int64_t(1)); + info5.emplace_back(int64_t(1)); + values.emplace_back(info5); + std::shared_ptr watcher = std::make_shared(); + auto result = watcher->ConvertToEntries(values); + EXPECT_EQ(result.size(), 2); + EXPECT_EQ(result[0].key, Bytes({1, 2, 3})); + EXPECT_EQ(result[0].value, Bytes({4, 5, 6})); + EXPECT_EQ(result[1].key, Bytes({7, 8, 9})); + EXPECT_EQ(result[1].value, Bytes({10, 11, 12})); +} + +/** +* @tc.name: ConvertToKeys +* @tc.desc: ConvertToKeys test the return result of input with different values. +* @tc.type: FUNC +* @tc.author: SQL +*/ +HWTEST_F(KVDBWatcherTest, ConvertToKeys, TestSize.Level0) +{ + std::vector values = { "key1", 123, "key3", 456, "key5" }; + std::shared_ptr watcher = std::make_shared(); + auto result = watcher->ConvertToKeys(values); + EXPECT_EQ(result.size(), 3); + EXPECT_EQ(result[0], "key1"); + EXPECT_EQ(result[1], "key3"); + EXPECT_EQ(result[2], "key5"); +} + +/** +* @tc.name: UserDelegate +* @tc.desc: UserDelegate test the return result of input with different values. +* @tc.type: FUNC +* @tc.author: SQL +*/ +HWTEST_F(UserDelegateTest, UserDelegate, TestSize.Level0) +{ + std::shared_ptr userDelegate = std::make_shared(); + auto result = userDelegate->GetLocalUserStatus(); + EXPECT_EQ(result.size(), 0); + std::string deviceId = ""; + result = userDelegate->GetRemoteUserStatus(deviceId); + EXPECT_TRUE(deviceId.empty()); + EXPECT_TRUE(result.empty()); + deviceId = DeviceManagerAdapter::GetInstance().GetLocalDevice().uuid; + result = userDelegate->GetRemoteUserStatus(deviceId); + EXPECT_EQ(result.size(), 0); +} + +/** +* @tc.name: StringToDbQuery +* @tc.desc: StringToDbQuery test the return result of input with different values. +* @tc.type: FUNC +* @tc.author: SQL +*/ +HWTEST_F(QueryHelperTest, StringToDbQuery, TestSize.Level0) +{ + std::shared_ptr queryHelper = std::make_shared(); + bool isSuccess = false; + std::string query = ""; + auto result = queryHelper->StringToDbQuery(query, isSuccess); + EXPECT_TRUE(isSuccess); + std::string querys(5 * 1024, 'a'); + query = "querys" + querys; + result = queryHelper->StringToDbQuery(query, isSuccess); + EXPECT_FALSE(isSuccess); + query = "query"; + result = queryHelper->StringToDbQuery(query, isSuccess); + EXPECT_FALSE(isSuccess); +} + +/** +* @tc.name: Handle001 +* @tc.desc: Handle test the return result of input with different values. +* @tc.type: FUNC +* @tc.author: SQL +*/ +HWTEST_F(QueryHelperTest, Handle001, TestSize.Level0) +{ + std::shared_ptr queryHelper = std::make_shared(); + std::vector words = {"query0", "query1", "query2", "query3", "query4"}; + int pointer = 0; + int end = 1; + int ends = 4; + DistributedDB::Query dbQuery; + EXPECT_FALSE(queryHelper->Handle(words, pointer, end, dbQuery)); + EXPECT_FALSE(queryHelper->HandleExtra(words, pointer, end, dbQuery)); + EXPECT_FALSE(queryHelper->HandleEqualTo(words, pointer, end, dbQuery)); + EXPECT_FALSE(queryHelper->HandleNotEqualTo(words, pointer, end, dbQuery)); + EXPECT_FALSE(queryHelper->HandleNotEqualTo(words, pointer, ends, dbQuery)); + EXPECT_FALSE(queryHelper->HandleGreaterThan(words, pointer, ends, dbQuery)); + EXPECT_FALSE(queryHelper->HandleGreaterThan(words, pointer, end, dbQuery)); + EXPECT_FALSE(queryHelper->HandleLessThan(words, pointer, ends, dbQuery)); + EXPECT_FALSE(queryHelper->HandleLessThan(words, pointer, end, dbQuery)); + EXPECT_FALSE(queryHelper->HandleGreaterThanOrEqualTo(words, pointer, ends, dbQuery)); + EXPECT_FALSE(queryHelper->HandleGreaterThanOrEqualTo(words, pointer, end, dbQuery)); + EXPECT_FALSE(queryHelper->HandleLessThanOrEqualTo(words, pointer, ends, dbQuery)); + EXPECT_FALSE(queryHelper->HandleLessThanOrEqualTo(words, pointer, end, dbQuery)); + + pointer = 0; + words = {"INTEGER", "LONG", "DOUBLE", "STRING"}; + EXPECT_FALSE(queryHelper->Handle(words, pointer, end, dbQuery)); + EXPECT_FALSE(queryHelper->HandleExtra(words, pointer, end, dbQuery)); + EXPECT_FALSE(queryHelper->HandleEqualTo(words, pointer, end, dbQuery)); + EXPECT_TRUE(queryHelper->HandleNotEqualTo(words, pointer, ends, dbQuery)); + EXPECT_FALSE(queryHelper->HandleNotEqualTo(words, pointer, end, dbQuery)); + pointer = 0; + EXPECT_TRUE(queryHelper->HandleGreaterThan(words, pointer, ends, dbQuery)); + EXPECT_FALSE(queryHelper->HandleGreaterThan(words, pointer, end, dbQuery)); + pointer = 0; + EXPECT_TRUE(queryHelper->HandleLessThan(words, pointer, ends, dbQuery)); + EXPECT_FALSE(queryHelper->HandleLessThan(words, pointer, end, dbQuery)); + pointer = 0; + EXPECT_TRUE(queryHelper->HandleGreaterThanOrEqualTo(words, pointer, ends, dbQuery)); + EXPECT_FALSE(queryHelper->HandleGreaterThanOrEqualTo(words, pointer, end, dbQuery)); + pointer = 0; + EXPECT_TRUE(queryHelper->HandleLessThanOrEqualTo(words, pointer, ends, dbQuery)); + EXPECT_FALSE(queryHelper->HandleLessThanOrEqualTo(words, pointer, end, dbQuery)); +} + +/** +* @tc.name: Handle002 +* @tc.desc: Handle test the return result of input with different values. +* @tc.type: FUNC +* @tc.author: SQL +*/ +HWTEST_F(QueryHelperTest, Handle002, TestSize.Level0) +{ + std::shared_ptr queryHelper = std::make_shared(); + std::vector words = {"query0", "query1", "query2", "query3", "query4"}; + int pointer = 1; + int end = 1; + int ends = 4; + DistributedDB::Query dbQuery; + EXPECT_TRUE(queryHelper->HandleIsNull(words, pointer, ends, dbQuery)); + EXPECT_FALSE(queryHelper->HandleIsNull(words, pointer, end, dbQuery)); + pointer = 0; + EXPECT_TRUE(queryHelper->HandleIsNotNull(words, pointer, ends, dbQuery)); + EXPECT_FALSE(queryHelper->HandleIsNotNull(words, pointer, end, dbQuery)); + pointer = 0; + EXPECT_TRUE(queryHelper->HandleLike(words, pointer, ends, dbQuery)); + EXPECT_FALSE(queryHelper->HandleLike(words, pointer, end, dbQuery)); + pointer = 0; + EXPECT_TRUE(queryHelper->HandleNotLike(words, pointer, ends, dbQuery)); + EXPECT_FALSE(queryHelper->HandleNotLike(words, pointer, end, dbQuery)); + pointer = 0; + EXPECT_TRUE(queryHelper->HandleOrderByAsc(words, pointer, ends, dbQuery)); + EXPECT_FALSE(queryHelper->HandleOrderByAsc(words, pointer, end, dbQuery)); + pointer = 0; + EXPECT_TRUE(queryHelper->HandleOrderByDesc(words, pointer, ends, dbQuery)); + EXPECT_FALSE(queryHelper->HandleOrderByDesc(words, pointer, end, dbQuery)); + pointer = 0; + EXPECT_TRUE(queryHelper->HandleOrderByWriteTime(words, pointer, ends, dbQuery)); + EXPECT_FALSE(queryHelper->HandleOrderByWriteTime(words, pointer, end, dbQuery)); + pointer = 0; + EXPECT_TRUE(queryHelper->HandleLimit(words, pointer, ends, dbQuery)); + EXPECT_FALSE(queryHelper->HandleLimit(words, pointer, end, dbQuery)); + pointer = 0; + EXPECT_TRUE(queryHelper->HandleKeyPrefix(words, pointer, ends, dbQuery)); + EXPECT_FALSE(queryHelper->HandleKeyPrefix(words, pointer, end, dbQuery)); +} + +/** +* @tc.name: Handle003 +* @tc.desc: Handle test the return result of input with different values. +* @tc.type: FUNC +* @tc.author: SQL +*/ +HWTEST_F(QueryHelperTest, Handle003, TestSize.Level0) +{ + std::shared_ptr queryHelper = std::make_shared(); + std::vector words = {"query0", "query1", "query2", "query3", "query4", "query5"}; + std::vector wordss = {"^NOT_IN", "INTEGER", "LONG", "^START", "STRING", "^END"}; + int pointer = 0; + int end = 1; + int ends = 5; + DistributedDB::Query dbQuery; + EXPECT_FALSE(queryHelper->HandleIn(words, pointer, ends, dbQuery)); + EXPECT_FALSE(queryHelper->HandleIn(words, pointer, end, dbQuery)); + EXPECT_FALSE(queryHelper->HandleIn(wordss, pointer, end, dbQuery)); + EXPECT_TRUE(queryHelper->HandleIn(wordss, pointer, ends, dbQuery)); + pointer = 0; + EXPECT_FALSE(queryHelper->HandleNotIn(words, pointer, ends, dbQuery)); + EXPECT_FALSE(queryHelper->HandleNotIn(words, pointer, end, dbQuery)); + EXPECT_FALSE(queryHelper->HandleNotIn(wordss, pointer, end, dbQuery)); + EXPECT_TRUE(queryHelper->HandleNotIn(wordss, pointer, ends, dbQuery)); +} + +/** +* @tc.name: Handle004 +* @tc.desc: Handle test the return result of input with different values. +* @tc.type: FUNC +* @tc.author: SQL +*/ +HWTEST_F(QueryHelperTest, Handle004, TestSize.Level0) +{ + std::shared_ptr queryHelper = std::make_shared(); + std::vector words = {"query0", "query1", "query2", "query3", "query4", "query5"}; + std::vector wordss = {"^NOT_IN", "INTEGER", "LONG", "^START", "STRING", "^END"}; + int pointer = 2; + int end = 3; + int ends = 5; + DistributedDB::Query dbQuery; + EXPECT_FALSE(queryHelper->HandleInKeys(words, pointer, ends, dbQuery)); + EXPECT_FALSE(queryHelper->HandleInKeys(words, pointer, end, dbQuery)); + EXPECT_FALSE(queryHelper->HandleInKeys(wordss, pointer, end, dbQuery)); + EXPECT_TRUE(queryHelper->HandleInKeys(wordss, pointer, ends, dbQuery)); + pointer = 3; + EXPECT_FALSE(queryHelper->HandleSetSuggestIndex(wordss, pointer, end, dbQuery)); + EXPECT_TRUE(queryHelper->HandleSetSuggestIndex(wordss, pointer, ends, dbQuery)); + pointer = 3; + EXPECT_FALSE(queryHelper->HandleDeviceId(wordss, pointer, end, dbQuery)); + EXPECT_TRUE(queryHelper->HandleDeviceId(wordss, pointer, ends, dbQuery)); + queryHelper->hasPrefixKey_ = true; + pointer = 3; + EXPECT_TRUE(queryHelper->HandleDeviceId(wordss, pointer, ends, dbQuery)); +} + +/** +* @tc.name: StringTo +* @tc.desc: StringTo test the return result of input with different values. +* @tc.type: FUNC +* @tc.author: SQL +*/ +HWTEST_F(QueryHelperTest, StringTo, TestSize.Level0) +{ + std::shared_ptr queryHelper = std::make_shared(); + std::string word = "true"; + EXPECT_TRUE(queryHelper->StringToBoolean(word)); + word = "false"; + EXPECT_FALSE(queryHelper->StringToBoolean(word)); + word = "BOOL"; + EXPECT_FALSE(queryHelper->StringToBoolean(word)); + + word = "^EMPTY_STRING"; + auto result = queryHelper->StringToString(word); + EXPECT_EQ(result, ""); + word = "START"; + result = queryHelper->StringToString(word); + EXPECT_EQ(result, "START"); + word = "START^^START"; + result = queryHelper->StringToString(word); + EXPECT_EQ(result, "START START"); + word = "START(^)START"; + result = queryHelper->StringToString(word); + EXPECT_EQ(result, "START^START"); +} + +/** +* @tc.name: Get +* @tc.desc: Get test the return result of input with different values. +* @tc.type: FUNC +* @tc.author: SQL +*/ +HWTEST_F(QueryHelperTest, Get, TestSize.Level0) +{ + std::shared_ptr queryHelper = std::make_shared(); + std::vector words = {"1", "2", "3", "4", "5", "^END"}; + int elementPointer = 0; + int end = 5; + std::vector ret = {1, 2, 3, 4, 5}; + auto result = queryHelper->GetIntegerList(words, elementPointer, end); + EXPECT_EQ(result, ret); + elementPointer = 6; + ret = {}; + result = queryHelper->GetIntegerList(words, elementPointer, end); + EXPECT_EQ(result, ret); + + elementPointer = 0; + std::vector ret1 = {1, 2, 3, 4, 5}; + auto result1 = queryHelper->GetLongList(words, elementPointer, end); + EXPECT_EQ(result1, ret1); + elementPointer = 6; + ret1 = {}; + result1 = queryHelper->GetLongList(words, elementPointer, end); + EXPECT_EQ(result1, ret1); + + elementPointer = 0; + std::vector ret2 = {1, 2, 3, 4, 5}; + auto result2 = queryHelper->GetDoubleList(words, elementPointer, end); + EXPECT_EQ(result2, ret2); + elementPointer = 6; + ret2 = {}; + result2 = queryHelper->GetDoubleList(words, elementPointer, end); + EXPECT_EQ(result2, ret2); + + std::vector words1 = {"^NOT_IN", "INTEGER", "LONG", "^START", "STRING", "^END"}; + elementPointer = 0; + std::vector ret3 = { "^NOT_IN", "INTEGER", "LONG", "^START", "STRING" }; + auto result3 = queryHelper->GetStringList(words1, elementPointer, end); + EXPECT_EQ(result3, ret3); + elementPointer = 6; + ret3 = {}; + result3 = queryHelper->GetStringList(words1, elementPointer, end); + EXPECT_EQ(result3, ret3); +} + +/** +* @tc.name: AuthHandler +* @tc.desc: AuthHandler test the return result of input with different values. +* @tc.type: FUNC +* @tc.author: SQL +*/ +HWTEST_F(AuthHandlerTest, AuthHandler, TestSize.Level0) +{ + int localUserId = 0; + int peerUserId = 0; + std::string peerDeviceId = ""; + int32_t authType = static_cast(DistributedKv::AuthType::IDENTICAL_ACCOUNT); + bool isSend = false; + auto result = AuthDelegate::GetInstance()->CheckAccess(localUserId, peerUserId, peerDeviceId, authType, isSend); + EXPECT_FALSE(result); + authType = static_cast(DistributedKv::AuthType::DEFAULT); + result = AuthDelegate::GetInstance()->CheckAccess(localUserId, peerUserId, peerDeviceId, authType, isSend); + EXPECT_TRUE(result); + + authType = static_cast(DistributedKv::AuthType::IDENTICAL_ACCOUNT); + peerDeviceId = "peerDeviceId"; + result = AuthDelegate::GetInstance()->CheckAccess(localUserId, peerUserId, peerDeviceId, authType, isSend); + EXPECT_FALSE(result); + + authType = static_cast(DistributedKv::AuthType::DEFAULT); + result = AuthDelegate::GetInstance()->CheckAccess(localUserId, peerUserId, peerDeviceId, authType, isSend); + EXPECT_TRUE(result); + + localUserId = 1; + result = AuthDelegate::GetInstance()->CheckAccess(localUserId, peerUserId, peerDeviceId, authType, isSend); + EXPECT_FALSE(result); + + peerUserId = 1; + result = AuthDelegate::GetInstance()->CheckAccess(localUserId, peerUserId, peerDeviceId, authType, isSend); + EXPECT_FALSE(result); +} +} // namespace DistributedDataTest +} // namespace OHOS::Test \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/test/mock/BUILD.gn b/datamgr_service/services/distributeddataservice/service/test/mock/BUILD.gn index 4a458579a002f38c08e98e89e9bf2ef13a45de6a..2feaaa791831660d4eb32c5db3ba666dd4364b9e 100644 --- a/datamgr_service/services/distributeddataservice/service/test/mock/BUILD.gn +++ b/datamgr_service/services/distributeddataservice/service/test/mock/BUILD.gn @@ -37,6 +37,7 @@ ohos_static_library("distributeddata_mock_static") { "db_change_data_mock.cpp", "db_store_mock.cpp", "general_store_mock.cpp", + "kv_store_nb_delegate_mock.cpp", ] external_deps = [ diff --git a/datamgr_service/services/distributeddataservice/service/test/mock/db_store_mock.cpp b/datamgr_service/services/distributeddataservice/service/test/mock/db_store_mock.cpp index acb05513dc62d5049caed4623d88b668288a6a24..6466dd56c42129bffb3b4fd0e1e969b3384638a8 100644 --- a/datamgr_service/services/distributeddataservice/service/test/mock/db_store_mock.cpp +++ b/datamgr_service/services/distributeddataservice/service/test/mock/db_store_mock.cpp @@ -17,6 +17,10 @@ namespace OHOS { namespace DistributedData { using namespace DistributedDB; +DBStatus DBStoreMock::Reset() +{ + return OK; +} DBStatus DBStoreMock::Get(const Key &key, Value &value) const { return Get(entries_, key, value); @@ -263,7 +267,7 @@ DBStatus DBStoreMock::GetEntries(ConcurrentMap &store, const Key &ke store.ForEach([&entries, &keyPrefix](const Key &key, Value &value) { auto it = std::search(key.begin(), key.end(), keyPrefix.begin(), keyPrefix.end()); if (it == key.begin()) { - entries.push_back({key, value}); + entries.push_back({key, value}); } return false; }); @@ -356,12 +360,13 @@ std::pair> DBStoreMock::GetCloudVer { return { NOT_SUPPORT, {} }; } -DBStatus DBStoreMock::SetReceiveDataInterceptor(const DataInterceptor &interceptor) + +DBStatus DBStoreMock::SetCloudSyncConfig(const CloudSyncConfig &config) { return NOT_SUPPORT; } -DBStatus DBStoreMock::SetCloudSyncConfig(const CloudSyncConfig &config) +DBStatus DBStoreMock::SetReceiveDataInterceptor(const DataInterceptor &interceptor) { return NOT_SUPPORT; } @@ -370,9 +375,15 @@ DBStatus DBStoreMock::GetDeviceEntries(const std::string &device, std::vector &entries) const override; DBStatus GetEntries(const Key &keyPrefix, KvStoreResultSet *&resultSet) const override; @@ -107,10 +111,11 @@ public: int32_t GetTaskCount() override; void SetGenCloudVersionCallback(const GenerateCloudVersionCallback &callback) override; std::pair> GetCloudVersion(const std::string &device) override; - DBStatus SetReceiveDataInterceptor(const DataInterceptor &interceptor) override; DBStatus SetCloudSyncConfig(const CloudSyncConfig &config) override; + DBStatus SetReceiveDataInterceptor(const DataInterceptor &interceptor) override; DBStatus GetDeviceEntries(const std::string &device, std::vector &entries) const override; - DBStatus Reset(); + DBStatus Sync(const DeviceSyncOption &option, const DeviceSyncProcessCallback &onProcess) override; + DBStatus CancelSync(uint32_t syncId) override; private: static const uint32_t DEFAULT_SIZE = 0; DBStatus Get(ConcurrentMap &store, const Key &key, Value &value) const; diff --git a/datamgr_service/services/distributeddataservice/service/test/mock/general_store_mock.cpp b/datamgr_service/services/distributeddataservice/service/test/mock/general_store_mock.cpp index 748c022460587bf4d3b1f8432a61f85f14bf1d28..a3d3b7f93ee0920c46d0d35f3f6cbb6c4e598d22 100644 --- a/datamgr_service/services/distributeddataservice/service/test/mock/general_store_mock.cpp +++ b/datamgr_service/services/distributeddataservice/service/test/mock/general_store_mock.cpp @@ -74,9 +74,9 @@ int32_t GeneralStoreMock::Delete(const std::string &table, const std::string &sq return 0; } -std::shared_ptr GeneralStoreMock::Query(const std::string &table, GenQuery &query) +std::pair> GeneralStoreMock::Query(const std::string &table, GenQuery &query) { - return nullptr; + return {GeneralError::E_NOT_SUPPORT, nullptr}; } int32_t GeneralStoreMock::Sync(const Devices &devices, GenQuery &query, DetailAsync async, SyncParam &syncParm) @@ -84,9 +84,9 @@ int32_t GeneralStoreMock::Sync(const Devices &devices, GenQuery &query, DetailAs return 0; } -std::shared_ptr GeneralStoreMock::PreSharing(GenQuery &query) +std::pair> GeneralStoreMock::PreSharing(GenQuery &query) { - return nullptr; + return {GeneralError::E_NOT_SUPPORT, nullptr}; } int32_t GeneralStoreMock::Clean(const std::vector &devices, int32_t mode, const std::string &tableName) @@ -114,17 +114,7 @@ int32_t GeneralStoreMock::UnregisterDetailProgressObserver() return 0; } -int32_t GeneralStoreMock::OnChange(const GeneralWatcher::Origin& origin, const GeneralWatcher::PRIFields& primaries, - GeneralWatcher::ChangeInfo&& changeInfo) -{ - if (watcher_ != nullptr) { - watcher_->OnChange(origin, primaries, std::move(changeInfo)); - return GeneralError::E_OK; - } - return GeneralError::E_ERROR; -} - -int32_t GeneralStoreMock::Close() +int32_t GeneralStoreMock::Close(bool isForce) { return 0; } @@ -149,9 +139,10 @@ int32_t GeneralStoreMock::MergeMigratedData(const std::string &tableName, VBucke return 0; } -std::shared_ptr GeneralStoreMock::Query(const std::string &table, const std::string &sql, Values &&args) +std::pair> GeneralStoreMock::Query(const std::string &table, const std::string &sql, + Values &&args) { - return cursor_; + return {GeneralError::E_OK, cursor_}; } std::vector GeneralStoreMock::GetWaterVersion(const std::string &deviceId) @@ -164,6 +155,26 @@ void GeneralStoreMock::MakeCursor(const std::map &entry) auto resultSet = std::make_shared(1, entry); cursor_ = std::make_shared(resultSet); } + +std::pair GeneralStoreMock::LockCloudDB() +{ + return { E_OK, 0 }; +} + +int32_t GeneralStoreMock::UnLockCloudDB() +{ + return E_OK; +} + +void GeneralStoreMock::SetExecutor(std::shared_ptr executor) +{ + return; +} +int32_t GeneralStoreMock::OnChange(const GeneralWatcher::Origin &origin, const GeneralWatcher::PRIFields &primaries, + GeneralWatcher::ChangeInfo &&changeInfo) +{ + return 0; +} GeneralStoreMock::GeneralStoreMock() {} } // namespace DistributedData } // namespace OHOS \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/test/mock/general_store_mock.h b/datamgr_service/services/distributeddataservice/service/test/mock/general_store_mock.h index 45773e34638f6a3e831fa51bba3b5e641ab553f1..bf16a2c8f1724d46e91ff0d6df3c08f01f7e7d4e 100644 --- a/datamgr_service/services/distributeddataservice/service/test/mock/general_store_mock.h +++ b/datamgr_service/services/distributeddataservice/service/test/mock/general_store_mock.h @@ -47,22 +47,26 @@ public: Values &&conditions) override; int32_t Replace(const std::string &table, VBucket &&value) override; int32_t Delete(const std::string &table, const std::string &sql, Values &&args) override; - std::shared_ptr Query(const std::string &table, const std::string &sql, Values &&args) override; - std::shared_ptr Query(const std::string &table, GenQuery &query) override; + std::pair> Query(const std::string &table, const std::string &sql, + Values &&args) override; + std::pair> Query(const std::string &table, GenQuery &query) override; int32_t Sync(const Devices &devices, GenQuery &query, DetailAsync async, SyncParam &syncParm) override; - std::shared_ptr PreSharing(GenQuery &query) override; + std::pair> PreSharing(GenQuery &query) override; int32_t Clean(const std::vector &devices, int32_t mode, const std::string &tableName) override; int32_t Watch(int32_t origin, Watcher &watcher) override; int32_t Unwatch(int32_t origin, Watcher &watcher) override; int32_t RegisterDetailProgressObserver(DetailAsync async) override; int32_t UnregisterDetailProgressObserver() override; - int32_t Close() override; + int32_t Close(bool isForce) override; int32_t AddRef() override; int32_t Release() override; int32_t BindSnapshots(std::shared_ptr>> bindAssets) override; int32_t MergeMigratedData(const std::string &tableName, VBuckets &&values) override; std::vector GetWaterVersion(const std::string &deviceId) override; + void SetExecutor(std::shared_ptr executor) override; void MakeCursor(const std::map &entry); + std::pair LockCloudDB() override; + int32_t UnLockCloudDB() override; int32_t OnChange(const GeneralWatcher::Origin &origin, const GeneralWatcher::PRIFields &primaries, GeneralWatcher::ChangeInfo &&changeInfo); @@ -70,7 +74,7 @@ public: private: std::shared_ptr cursor_ = nullptr; - Watcher* watcher_ = nullptr; + Watcher* watcher_ = nullptr; }; } // namespace DistributedData } // namespace OHOS diff --git a/datamgr_service/services/distributeddataservice/service/test/mock/general_watcher_mock.cpp b/datamgr_service/services/distributeddataservice/service/test/mock/general_watcher_mock.cpp new file mode 100644 index 0000000000000000000000000000000000000000..e4ec970be4f9a7c68604566ab31385f642e57bc0 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/test/mock/general_watcher_mock.cpp @@ -0,0 +1,37 @@ +/* +* Copyright (c) 2024 Huawei Device Co., Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +#include "general_watcher_mock.h" + +namespace OHOS::DistributedData { +bool MockQuery::IsEqual(uint64_t tid) +{ + return (tid == TYPE_ID) && lastResult; +} + +std::vector MockQuery::GetTables() +{ + return tables_; +} + +int32_t MockGeneralWatcher::OnChange(const Origin &origin, const PRIFields &primaryFields, ChangeInfo &&values) +{ + return GeneralError::E_OK; +} + +int32_t MockGeneralWatcher::OnChange(const Origin &origin, const Fields &fields, ChangeData &&datas) +{ + return GeneralError::E_OK; +} +} // OHOS::DistributedData diff --git a/datamgr_service/services/distributeddataservice/service/test/mock/general_watcher_mock.h b/datamgr_service/services/distributeddataservice/service/test/mock/general_watcher_mock.h new file mode 100644 index 0000000000000000000000000000000000000000..27748455653f095d071d3761fc4cf5106516e079 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/test/mock/general_watcher_mock.h @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef OHOS_DISTRIBUTEDDATA_SERVICE_TEST_GENERAL_WATCH_MOCK_H +#define OHOS_DISTRIBUTEDDATA_SERVICE_TEST_GENERAL_WATCH_MOCK_H + +#include "store/general_value.h" +#include "store/general_watcher.h" + +namespace OHOS::DistributedData { +class MockQuery : public GenQuery { +public: + ~MockQuery() = default; + static constexpr uint64_t TYPE_ID = 0x20000001; + std::vector tables_; + bool lastResult = false; + bool IsEqual(uint64_t tid) override; + + std::vector GetTables() override; +}; + +class MockGeneralWatcher : public DistributedData::GeneralWatcher { +public: + int32_t OnChange(const Origin &origin, const PRIFields &primaryFields, ChangeInfo &&values) override; + + int32_t OnChange(const Origin &origin, const Fields &fields, ChangeData &&datas) override; +}; +} // OHOS::DistributedData +#endif \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/test/mock/kv_store_nb_delegate_mock.cpp b/datamgr_service/services/distributeddataservice/service/test/mock/kv_store_nb_delegate_mock.cpp new file mode 100644 index 0000000000000000000000000000000000000000..8c402f961d30586660275353a1a088c02ec8e1b8 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/test/mock/kv_store_nb_delegate_mock.cpp @@ -0,0 +1,333 @@ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "kv_store_nb_delegate_mock.h" +#include "store_types.h" +namespace DistributedDB { +DBStatus KvStoreNbDelegateMock::Get(const Key &key, Value &value) const +{ + return DBStatus::OK; +} + +DBStatus KvStoreNbDelegateMock::GetEntries(const Key &keyPrefix, std::vector &entries) const +{ + return DBStatus::OK; +} + +DBStatus KvStoreNbDelegateMock::GetEntries(const Key &keyPrefix, KvStoreResultSet *&resultSet) const +{ + return DBStatus::OK; +} + +DBStatus KvStoreNbDelegateMock::GetEntries(const Query &query, std::vector &entries) const +{ + return DBStatus::OK; +} + +DBStatus KvStoreNbDelegateMock::GetEntries(const Query &query, KvStoreResultSet *&resultSet) const +{ + return DBStatus::OK; +} + +DBStatus KvStoreNbDelegateMock::GetCount(const Query &query, int &count) const +{ + return DBStatus::OK; +} + +DBStatus KvStoreNbDelegateMock::CloseResultSet(KvStoreResultSet *&resultSet) +{ + return DBStatus::OK; +} + +DBStatus KvStoreNbDelegateMock::Put(const Key &key, const Value &value) +{ + return DBStatus::OK; +} + +DBStatus KvStoreNbDelegateMock::PutBatch(const std::vector &entries) +{ + return DBStatus::OK; +} + +DBStatus KvStoreNbDelegateMock::DeleteBatch(const std::vector &keys) +{ + return DBStatus::OK; +} + +DBStatus KvStoreNbDelegateMock::Delete(const Key &key) +{ + return DBStatus::OK; +} + +DBStatus KvStoreNbDelegateMock::GetLocal(const Key &key, Value &value) const +{ + return DBStatus::OK; +} + +DBStatus KvStoreNbDelegateMock::GetLocalEntries(const Key &keyPrefix, std::vector &entries) const +{ + return DBStatus::OK; +} + +DBStatus KvStoreNbDelegateMock::PutLocal(const Key &key, const Value &value) +{ + return DBStatus::OK; +} + +DBStatus KvStoreNbDelegateMock::DeleteLocal(const Key &key) +{ + return DBStatus::OK; +} + +DBStatus KvStoreNbDelegateMock::PublishLocal(const Key &key, bool deleteLocal, bool updateTimestamp, + const KvStoreNbPublishOnConflict &onConflict) +{ + return DBStatus::OK; +} + +DBStatus KvStoreNbDelegateMock::UnpublishToLocal(const Key &key, bool deletePublic, bool updateTimestamp) +{ + return DBStatus::OK; +} + +DBStatus KvStoreNbDelegateMock::RegisterObserver(const Key &key, unsigned int mode, + KvStoreObserver *observer) +{ + return DBStatus::OK; +} + +DBStatus KvStoreNbDelegateMock::UnRegisterObserver(const KvStoreObserver *observer) +{ + return DBStatus::OK; +} + +DBStatus KvStoreNbDelegateMock::RemoveDeviceData(const std::string &device) +{ + return DBStatus::OK; +} + +std::string KvStoreNbDelegateMock::GetStoreId() const +{ + return "ok"; +} + +DBStatus KvStoreNbDelegateMock::Sync(const std::vector &devices, SyncMode mode, + const std::function &devicesMap)> &onComplete, + bool wait) +{ + return DBStatus::OK; +} + +DBStatus KvStoreNbDelegateMock::Pragma(PragmaCmd cmd, PragmaData ¶mData) +{ + return DBStatus::OK; +} + +DBStatus KvStoreNbDelegateMock::SetConflictNotifier(int conflictType, + const KvStoreNbConflictNotifier ¬ifier) +{ + return DBStatus::OK; +} + +DBStatus KvStoreNbDelegateMock::Rekey(const CipherPassword &password) +{ + return DBStatus::OK; +} + +DBStatus KvStoreNbDelegateMock::Export(const std::string &filePath, + const CipherPassword &passwd, bool force) +{ + return DBStatus::OK; +} + +DBStatus KvStoreNbDelegateMock::Import(const std::string &filePath, const CipherPassword &passwd) +{ + return DBStatus::OK; +} + +DBStatus KvStoreNbDelegateMock::StartTransaction() +{ + return DBStatus::OK; +} + +DBStatus KvStoreNbDelegateMock::Commit() +{ + return DBStatus::OK; +} + +DBStatus KvStoreNbDelegateMock::Rollback() +{ + return DBStatus::OK; +} + +DBStatus KvStoreNbDelegateMock::PutLocalBatch(const std::vector &entries) +{ + return DBStatus::OK; +} + +DBStatus KvStoreNbDelegateMock::DeleteLocalBatch(const std::vector &keys) +{ + return DBStatus::OK; +} + +DBStatus KvStoreNbDelegateMock::GetSecurityOption(SecurityOption &option) const +{ + return DBStatus::OK; +} + +DBStatus KvStoreNbDelegateMock::SetRemotePushFinishedNotify(const RemotePushFinishedNotifier ¬ifier) +{ + return DBStatus::OK; +} + +DBStatus KvStoreNbDelegateMock::Sync(const std::vector &devices, SyncMode mode, + const std::function &devicesMap)> &onComplete, + const Query &query, bool wait) +{ + return DBStatus::OK; +} + +DBStatus KvStoreNbDelegateMock::CheckIntegrity() const +{ + return DBStatus::OK; +} + +DBStatus KvStoreNbDelegateMock::SetEqualIdentifier(const std::string &identifier, + const std::vector &targets) +{ + return DBStatus::OK; +} + +DBStatus KvStoreNbDelegateMock::SetPushDataInterceptor(const PushDataInterceptor &interceptor) +{ + return DBStatus::OK; +} + +DBStatus KvStoreNbDelegateMock::SubscribeRemoteQuery(const std::vector &devices, + const std::function &devicesMap)> &onComplete, + const Query &query, bool wait) +{ + return DBStatus::OK; +} + +DBStatus KvStoreNbDelegateMock::UnSubscribeRemoteQuery(const std::vector &devices, + const std::function &devicesMap)> &onComplete, + const Query &query, bool wait) +{ + return DBStatus::OK; +} + +DBStatus KvStoreNbDelegateMock::RemoveDeviceData() +{ + return DBStatus::OK; +} + +DBStatus KvStoreNbDelegateMock::GetKeys(const Key &keyPrefix, std::vector &keys) const +{ + return DBStatus::OK; +} + +size_t KvStoreNbDelegateMock::GetSyncDataSize(const std::string &device) const +{ + size_t size = 0; + return size; +} + +DBStatus KvStoreNbDelegateMock::UpdateKey(const UpdateKeyCallback &callback) +{ + return DBStatus::OK; +} + +std::pair KvStoreNbDelegateMock::GetWatermarkInfo(const std::string &device) +{ + std::pair ret; + return ret; +} + +DBStatus KvStoreNbDelegateMock::Sync(const CloudSyncOption &option, const SyncProcessCallback &onProcess) +{ + return DBStatus::OK; +} + +DBStatus KvStoreNbDelegateMock::SetCloudDB(const std::map> &cloudDBs) +{ + return DBStatus::OK; +} + +DBStatus KvStoreNbDelegateMock::SetCloudDbSchema(const std::map &schema) +{ + return DBStatus::OK; +} + +DBStatus KvStoreNbDelegateMock::RemoveDeviceData(const std::string &device, ClearMode mode) +{ + return DBStatus::OK; +} + +DBStatus KvStoreNbDelegateMock::RemoveDeviceData(const std::string &device, const std::string &user, ClearMode mode) +{ + return DBStatus::OK; +} + +int32_t KvStoreNbDelegateMock::GetTaskCount() +{ + int32_t taskCount = taskCountMock_; + return taskCount; +} + +void KvStoreNbDelegateMock::SetGenCloudVersionCallback(const GenerateCloudVersionCallback &callback) +{ + auto callback_ = callback; +} + +std::pair> KvStoreNbDelegateMock::GetCloudVersion( + const std::string &device) +{ + if (device.empty()) { + return { DBStatus::OK, {} }; + } else if (device == "test") { + return { DBStatus::DB_ERROR, {} }; + } else if (device == "device") { + return { DBStatus::DB_ERROR, {{device, device}} }; + } else { + return { DBStatus::OK, {{device, device}} }; + } +} + +DBStatus KvStoreNbDelegateMock::SetReceiveDataInterceptor(const DataInterceptor &interceptor) +{ + return DBStatus::OK; +} + +DBStatus KvStoreNbDelegateMock::SetCloudSyncConfig(const CloudSyncConfig &config) +{ + return DBStatus::OK; +} + +DBStatus KvStoreNbDelegateMock::GetDeviceEntries(const std::string &device, std::vector &entries) const +{ + return DBStatus::OK; +} + +DBStatus KvStoreNbDelegateMock::Sync(const DeviceSyncOption &option, const DeviceSyncProcessCallback &onProcess) +{ + return DBStatus::OK; +} + +DBStatus KvStoreNbDelegateMock::CancelSync(uint32_t syncId) +{ + return DBStatus::OK; +} +} // namespace DistributedDB \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/test/mock/kv_store_nb_delegate_mock.h b/datamgr_service/services/distributeddataservice/service/test/mock/kv_store_nb_delegate_mock.h new file mode 100644 index 0000000000000000000000000000000000000000..83d935fbf26be9904f7c7301f2343ded34541ccd --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/test/mock/kv_store_nb_delegate_mock.h @@ -0,0 +1,111 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef KV_STORE_NB_DELEGATE_H_MOCK +#define KV_STORE_NB_DELEGATE_H_MOCK + +#include +#include +#include + +#include "cloud/cloud_store_types.h" +#include "cloud/icloud_db.h" +#include "intercepted_data.h" +#include "iprocess_system_api_adapter.h" +#include "kv_store_nb_delegate.h" +#include "kv_store_nb_conflict_data.h" +#include "kv_store_observer.h" +#include "kv_store_result_set.h" +#include "query.h" +#include "store_types.h" + +namespace DistributedDB { +class KvStoreNbDelegateMock : public DistributedDB::KvStoreNbDelegate { +public: + int32_t taskCountMock_ = 0; + ~KvStoreNbDelegateMock() = default; + DBStatus Get(const Key &key, Value &value) const; + DBStatus GetEntries(const Key &keyPrefix, std::vector &entries) const; + DBStatus GetEntries(const Key &keyPrefix, KvStoreResultSet *&resultSet) const; + DBStatus GetEntries(const Query &query, std::vector &entries) const; + DBStatus GetEntries(const Query &query, KvStoreResultSet *&resultSet) const; + DBStatus GetCount(const Query &query, int &count) const; + DBStatus CloseResultSet(KvStoreResultSet *&resultSet); + DBStatus Put(const Key &key, const Value &value); + DBStatus PutBatch(const std::vector &entries); + DBStatus DeleteBatch(const std::vector &keys); + DBStatus Delete(const Key &key); + DBStatus GetLocal(const Key &key, Value &value) const; + DBStatus GetLocalEntries(const Key &keyPrefix, std::vector &entries) const; + DBStatus PutLocal(const Key &key, const Value &value); + DBStatus DeleteLocal(const Key &key); + DBStatus PublishLocal(const Key &key, bool deleteLocal, bool updateTimestamp, + const KvStoreNbPublishOnConflict &onConflict); + DBStatus UnpublishToLocal(const Key &key, bool deletePublic, bool updateTimestamp); + DBStatus RegisterObserver(const Key &key, unsigned int mode, KvStoreObserver *observer); + DBStatus UnRegisterObserver(const KvStoreObserver *observer); + DBStatus RemoveDeviceData(const std::string &device); + std::string GetStoreId() const; + DBStatus Sync(const std::vector &devices, SyncMode mode, + const std::function &devicesMap)> &onComplete, + bool wait = false); + DBStatus Pragma(PragmaCmd cmd, PragmaData ¶mData); + DBStatus SetConflictNotifier(int conflictType, + const KvStoreNbConflictNotifier ¬ifier); + DBStatus Rekey(const CipherPassword &password); + DBStatus Export(const std::string &filePath, const CipherPassword &passwd, bool force = false); + DBStatus Import(const std::string &filePath, const CipherPassword &passwd); + DBStatus StartTransaction(); + DBStatus Commit(); + DBStatus Rollback(); + DBStatus PutLocalBatch(const std::vector &entries); + DBStatus DeleteLocalBatch(const std::vector &keys); + DBStatus GetSecurityOption(SecurityOption &option) const; + DBStatus SetRemotePushFinishedNotify(const RemotePushFinishedNotifier ¬ifier); + DBStatus Sync(const std::vector &devices, SyncMode mode, + const std::function &devicesMap)> &onComplete, + const Query &query, bool wait); + DBStatus CheckIntegrity() const; + DBStatus SetEqualIdentifier(const std::string &identifier, + const std::vector &targets); + DBStatus SetPushDataInterceptor(const PushDataInterceptor &interceptor); + DBStatus SubscribeRemoteQuery(const std::vector &devices, + const std::function &devicesMap)> &onComplete, + const Query &query, bool wait); + DBStatus UnSubscribeRemoteQuery(const std::vector &devices, + const std::function &devicesMap)> &onComplete, + const Query &query, bool wait); + DBStatus RemoveDeviceData(); + DBStatus GetKeys(const Key &keyPrefix, std::vector &keys) const; + size_t GetSyncDataSize(const std::string &device) const; + DBStatus UpdateKey(const UpdateKeyCallback &callback); + std::pair GetWatermarkInfo(const std::string &device); + DBStatus Sync(const CloudSyncOption &option, const SyncProcessCallback &onProcess); + DBStatus SetCloudDB(const std::map> &cloudDBs); + DBStatus SetCloudDbSchema(const std::map &schema); + DBStatus RemoveDeviceData(const std::string &device, ClearMode mode); + DBStatus RemoveDeviceData(const std::string &device, const std::string &user, ClearMode mode); + int32_t GetTaskCount(); + void SetGenCloudVersionCallback(const GenerateCloudVersionCallback &callback); + std::pair> GetCloudVersion( + const std::string &device); + DBStatus SetReceiveDataInterceptor(const DataInterceptor &interceptor); + DBStatus SetCloudSyncConfig(const CloudSyncConfig &config); + DBStatus GetDeviceEntries(const std::string &device, std::vector &entries) const; + DBStatus Sync(const DeviceSyncOption &option, const DeviceSyncProcessCallback &onProcess); + DBStatus CancelSync(uint32_t syncId); +}; +} // namespace DistributedDB +#endif // KV_STORE_NB_DELEGATE_H_MOCK \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/test/object_asset_loader_test.cpp b/datamgr_service/services/distributeddataservice/service/test/object_asset_loader_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ab44449262ffef3f7615f91296eddeae55b9c6b1 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/test/object_asset_loader_test.cpp @@ -0,0 +1,207 @@ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define LOG_TAG "ObjectAssetLoaderTest" + +#include "object_asset_loader.h" +#include +#include "snapshot/machine_status.h" +#include "executor_pool.h" + +using namespace testing::ext; +using namespace OHOS::DistributedObject; +using namespace OHOS::DistributedData; +namespace OHOS::Test { + +class ObjectAssetLoaderTest : public testing::Test { +public: + void SetUp(); + void TearDown(); + +protected: + Asset asset_; + std::string uri_; + int32_t userId_ = 1; + std::string bundleName_ = "test_bundleName_1"; + std::string deviceId_ = "test_deviceId__1"; +}; + +void ObjectAssetLoaderTest::SetUp() +{ + uri_ = "file:://com.example.hmos.notepad/data/storage/el2/distributedfiles/dir/asset1.jpg"; + Asset asset{ + .name = "test_name", + .uri = uri_, + .modifyTime = "modifyTime", + .size = "size", + .hash = "modifyTime_size", + }; + asset_ = asset; +} + +void ObjectAssetLoaderTest::TearDown() {} + +/** +* @tc.name: UploadTest001 +* @tc.desc: Transfer test. +* @tc.type: FUNC +* @tc.require: +* @tc.author: wangbin +*/ +HWTEST_F(ObjectAssetLoaderTest, UploadTest001, TestSize.Level0) +{ + auto assetLoader = ObjectAssetLoader::GetInstance(); + auto result = assetLoader->Transfer(userId_, bundleName_, deviceId_, asset_); + ASSERT_EQ(result, false); +} + +/** +* @tc.name: TransferAssetsAsync001 +* @tc.desc: TransferAssetsAsync test. +* @tc.type: FUNC +* @tc.require: +* @tc.author: wangbin +*/ +HWTEST_F(ObjectAssetLoaderTest, TransferAssetsAsync001, TestSize.Level0) +{ + auto assetLoader = ObjectAssetLoader::GetInstance(); + std::function lambdaFunc = [](bool success) { + if (success) {} + }; + std::vector assets{ asset_ }; + ASSERT_EQ(assetLoader->executors_, nullptr); + assetLoader->TransferAssetsAsync(userId_, bundleName_, deviceId_, assets, lambdaFunc); +} + +/** +* @tc.name: TransferAssetsAsync002 +* @tc.desc: TransferAssetsAsync test. +* @tc.type: FUNC +* @tc.require: +* @tc.author: wangbin +*/ +HWTEST_F(ObjectAssetLoaderTest, TransferAssetsAsync002, TestSize.Level0) +{ + auto assetLoader = ObjectAssetLoader::GetInstance(); + std::function lambdaFunc = [](bool success) { + if (success) {} + }; + std::vector assets{ asset_ }; + std::shared_ptr executors = std::make_shared(5, 3); + ASSERT_NE(executors, nullptr); + assetLoader->SetThreadPool(executors); + ASSERT_NE(assetLoader->executors_, nullptr); + assetLoader->TransferAssetsAsync(userId_, bundleName_, deviceId_, assets, lambdaFunc); +} + +/** +* @tc.name: FinishTask001 +* @tc.desc: FinishTask test. +* @tc.type: FUNC +* @tc.require: +* @tc.author: wangbin +*/ +HWTEST_F(ObjectAssetLoaderTest, FinishTask001, TestSize.Level0) +{ + auto assetLoader = ObjectAssetLoader::GetInstance(); + ASSERT_NE(assetLoader, nullptr); + TransferTask task; + task.downloadAssets.insert(uri_); + assetLoader->FinishTask(asset_.uri, true); + ASSERT_TRUE(assetLoader->tasks_.Empty()); + assetLoader->FinishTask(asset_.uri, false); + ASSERT_TRUE(assetLoader->tasks_.Empty()); +} + +/** +* @tc.name: IsDownloading001 +* @tc.desc: IsDownloading test. +* @tc.type: FUNC +* @tc.require: +* @tc.author: wangbin +*/ +HWTEST_F(ObjectAssetLoaderTest, IsDownloading001, TestSize.Level0) +{ + auto assetLoader = ObjectAssetLoader::GetInstance(); + assetLoader->downloading_.InsertOrAssign(asset_.uri, asset_.hash); + auto result = assetLoader->IsDownloading(asset_); + ASSERT_EQ(result, true); + assetLoader->downloading_.Erase(asset_.uri); + result = assetLoader->IsDownloading(asset_); + ASSERT_EQ(result, false); +} + +/** +* @tc.name: IsDownloaded001 +* @tc.desc: IsDownloaded test. +* @tc.type: FUNC +* @tc.require: +* @tc.author: wangbin +*/ +HWTEST_F(ObjectAssetLoaderTest, IsDownloaded001, TestSize.Level0) +{ + auto assetLoader = ObjectAssetLoader::GetInstance(); + auto result = assetLoader->IsDownloaded(asset_); + ASSERT_EQ(result, false); + assetLoader->downloaded_.Insert(asset_.uri, "modifyTime_size"); + result = assetLoader->IsDownloaded(asset_); + ASSERT_EQ(result, true); +} + +/** +* @tc.name: UpdateDownloaded001 +* @tc.desc: UpdateDownloaded test. +* @tc.type: FUNC +* @tc.require: +* @tc.author: wangbin +*/ +HWTEST_F(ObjectAssetLoaderTest, UpdateDownloaded001, TestSize.Level0) +{ + auto assetLoader = ObjectAssetLoader::GetInstance(); + ASSERT_NE(assetLoader, nullptr); + while (!assetLoader->assetQueue_.empty()) { + assetLoader->assetQueue_.pop(); + } + assetLoader->UpdateDownloaded(asset_); + auto [success, hash] = assetLoader->downloaded_.Find(asset_.uri); + ASSERT_TRUE(success); + EXPECT_EQ(hash, asset_.hash); +} + +/** +* @tc.name: UpdateDownloaded002 +* @tc.desc: UpdateDownloaded test. +* @tc.type: FUNC +* @tc.require: +* @tc.author: wangbin +*/ +HWTEST_F(ObjectAssetLoaderTest, UpdateDownloaded002, TestSize.Level0) +{ + auto assetLoader = ObjectAssetLoader::GetInstance(); + ASSERT_NE(assetLoader, nullptr); + while (!assetLoader->assetQueue_.empty()) { + assetLoader->assetQueue_.pop(); + } + for (int i = 0; i <= assetLoader->LAST_DOWNLOAD_ASSET_SIZE; i++) { + assetLoader->assetQueue_.push(asset_.uri); + } + assetLoader->UpdateDownloaded(asset_); + EXPECT_NE(assetLoader->assetQueue_.size(), ObjectAssetLoader::LAST_DOWNLOAD_ASSET_SIZE); + EXPECT_EQ(assetLoader->assetQueue_.size(), ObjectAssetLoader::LAST_DOWNLOAD_ASSET_SIZE + 1); + auto [success, hash] = assetLoader->downloaded_.Find(asset_.uri); + EXPECT_EQ(success, false); + EXPECT_EQ(hash, ""); +} +} // namespace OHOS::Test diff --git a/datamgr_service/services/distributeddataservice/service/test/object_asset_machine_test.cpp b/datamgr_service/services/distributeddataservice/service/test/object_asset_machine_test.cpp index 969122494400b1729b915e82fd879ad839cefe48..c6e34358179beee37619d8a457254b96c197c77c 100644 --- a/datamgr_service/services/distributeddataservice/service/test/object_asset_machine_test.cpp +++ b/datamgr_service/services/distributeddataservice/service/test/object_asset_machine_test.cpp @@ -82,37 +82,12 @@ void ObjectAssetMachineTest::TearDown() {} /** * @tc.name: StatusTransfer001 -* @tc.desc: Transfer event. -* @tc.type: FUNC -* @tc.require: -* @tc.author: whj -*/ -HWTEST_F(ObjectAssetMachineTest, StatusTransfer001, TestSize.Level0) -{ - auto machine = std::make_shared(); - Asset asset{ - .name = "test_name", - .uri = uri_, - .modifyTime = "modifyTime1", - .size = "size1", - .hash = "modifyTime1_size1", - }; - std::pair changedAsset{ "device_1", asset }; - changedAssets_[uri_].status = STATUS_STABLE; - machine->DFAPostEvent(REMOTE_CHANGED, changedAssets_[uri_], asset, changedAsset); - ASSERT_EQ(changedAssets_[uri_].status, STATUS_TRANSFERRING); - ASSERT_EQ(changedAssets_[uri_].deviceId, changedAsset.first); - ASSERT_EQ(changedAssets_[uri_].asset.hash, asset.hash); -} - -/** -* @tc.name: StatusTransfer002 * @tc.desc: Remote changed when transferring. * @tc.type: FUNC * @tc.require: * @tc.author: whj */ -HWTEST_F(ObjectAssetMachineTest, StatusTransfer002, TestSize.Level0) +HWTEST_F(ObjectAssetMachineTest, StatusTransfer001, TestSize.Level0) { auto machine = std::make_shared(); Asset asset{ @@ -131,40 +106,13 @@ HWTEST_F(ObjectAssetMachineTest, StatusTransfer002, TestSize.Level0) } /** -* @tc.name: StatusTransfer003 -* @tc.desc: Compensate transfer in conflict scenario. -* @tc.type: FUNC -* @tc.require: -* @tc.author: whj -*/ -HWTEST_F(ObjectAssetMachineTest, StatusTransfer003, TestSize.Level0) -{ - auto machine = std::make_shared(); - Asset asset{ - .name = "test_name", - .uri = uri_, - .modifyTime = "modifyTime1", - .size = "size1", - .hash = "modifyTime1_size1", - }; - std::pair changedAsset{ "device_1", asset }; - changedAssets_[uri_].status = STATUS_WAIT_TRANSFER; - changedAssets_[uri_].deviceId = "device_2"; - changedAssets_[uri_].asset.hash = "modifyTime2_size2"; - machine->DFAPostEvent(TRANSFER_FINISHED, changedAssets_[uri_], asset, changedAsset); - ASSERT_EQ(changedAssets_[uri_].status, STATUS_TRANSFERRING); - ASSERT_EQ(changedAssets_[uri_].deviceId, "device_2"); - ASSERT_EQ(changedAssets_[uri_].asset.hash, "modifyTime2_size2"); -} - -/** -* @tc.name: StatusTransfer004 +* @tc.name: StatusTransfer002 * @tc.desc: Transfer finished. * @tc.type: FUNC * @tc.require: * @tc.author: whj */ -HWTEST_F(ObjectAssetMachineTest, StatusTransfer004, TestSize.Level0) +HWTEST_F(ObjectAssetMachineTest, StatusTransfer002, TestSize.Level0) { auto machine = std::make_shared(); Asset asset{ @@ -181,13 +129,13 @@ HWTEST_F(ObjectAssetMachineTest, StatusTransfer004, TestSize.Level0) } /** -* @tc.name: StatusTransfer005 +* @tc.name: StatusTransfer003 * @tc.desc: Transfer event * @tc.type: FUNC * @tc.require: * @tc.author: nhj */ -HWTEST_F(ObjectAssetMachineTest, StatusTransfer005, TestSize.Level0) +HWTEST_F(ObjectAssetMachineTest, StatusTransfer003, TestSize.Level0) { auto machine = std::make_shared(); Asset asset{ @@ -270,46 +218,33 @@ HWTEST_F(ObjectAssetMachineTest, StatusDownload001, TestSize.Level0) { auto machine = std::make_shared(); Asset asset{ - .name = "test_name", - .uri = uri_, - .modifyTime = "modifyTime1", - .size = "size1", - .hash = "modifyTime1_size1", + .name = "name_006", + .uri = "uri_006", + .modifyTime = "modifyTime_006", + .size = "size_006", + .hash = "modifyTime_006_size_006", }; - std::pair changedAsset{ "device_1", asset }; - machine->DFAPostEvent(DOWNLOAD, changedAssets_[uri_], asset, changedAsset); - ASSERT_EQ(changedAssets_[uri_].status, STATUS_DOWNLOADING); - - machine->DFAPostEvent(DOWNLOAD_FINISHED, changedAssets_[uri_], asset); - ASSERT_EQ(changedAssets_[uri_].status, STATUS_STABLE); -} - -/** -* @tc.name: StatusDownload002 -* @tc.desc: Conflict scenario: Download before transfer. -* @tc.type: FUNC -* @tc.require: -* @tc.author: nhj -*/ -HWTEST_F(ObjectAssetMachineTest, StatusDownload002, TestSize.Level0) -{ - auto machine = std::make_shared(); - Asset asset{ - .name = "test_name", - .uri = uri_, - .modifyTime = "modifyTime1", - .size = "size1", - .hash = "modifyTime1_size1", + AssetBindInfo AssetBindInfo{ + .storeName = "store_006", + .tableName = "table_006", + .primaryKey = {{ "006", "006" }}, + .field = "attachment_006", + .assetName = "asset_006.jpg", }; - std::pair changedAsset{ "device_1", asset }; - machine->DFAPostEvent(DOWNLOAD, changedAssets_[uri_], asset); - ASSERT_EQ(changedAssets_[uri_].status, STATUS_DOWNLOADING); + StoreInfo storeInfo { + .tokenId = 600, + .bundleName = "bundleName_006", + .storeName = "store_006", + .instanceId = 600, + .user = 600, + }; + ChangedAssetInfo changedAssetInfo(asset, AssetBindInfo, storeInfo); + std::pair changedAsset{ "device_006", asset }; - machine->DFAPostEvent(REMOTE_CHANGED, changedAssets_[uri_], asset, changedAsset); - ASSERT_EQ(changedAssets_[uri_].status, STATUS_WAIT_TRANSFER); - ASSERT_EQ(changedAssets_[uri_].asset.hash, asset.hash); + machine->DFAPostEvent(DOWNLOAD, changedAssetInfo, asset, changedAsset); + ASSERT_EQ(changedAssetInfo.status, STATUS_DOWNLOADING); - machine->DFAPostEvent(DOWNLOAD_FINISHED, changedAssets_[uri_], asset); - ASSERT_EQ(changedAssets_[uri_].status, STATUS_TRANSFERRING); + machine->DFAPostEvent(DOWNLOAD_FINISHED, changedAssetInfo, asset); + ASSERT_EQ(changedAssetInfo.status, STATUS_STABLE); } } // namespace OHOS::Test \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/test/object_manager_test.cpp b/datamgr_service/services/distributeddataservice/service/test/object_manager_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..bccbc22e28dddaa98d1d2f07f9261a49b8261297 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/test/object_manager_test.cpp @@ -0,0 +1,893 @@ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define LOG_TAG "ObjectManagerTest" + +#include "object_manager.h" +#include +#include "snapshot/machine_status.h" +#include "executor_pool.h" +#include "object_types.h" +#include "kv_store_nb_delegate_mock.h" +#include + +using namespace testing::ext; +using namespace OHOS::DistributedObject; +using AssetValue = OHOS::CommonType::AssetValue; +using RestoreStatus = OHOS::DistributedObject::ObjectStoreManager::RestoreStatus; +namespace OHOS::Test { + +class ObjectManagerTest : public testing::Test { +public: + void SetUp(); + void TearDown(); + +protected: + Asset asset_; + std::string uri_; + std::string appId_ = "objectManagerTest_appid_1"; + std::string sessionId_ = "123"; + std::vector data_; + std::string deviceId_ = "7001005458323933328a258f413b3900"; + uint64_t sequenceId_ = 10; + uint64_t sequenceId_2 = 20; + uint64_t sequenceId_3 = 30; + std::string userId_ = "100"; + std::string bundleName_ = "com.examples.hmos.notepad"; + OHOS::ObjectStore::AssetBindInfo assetBindInfo_; + pid_t pid_ = 10; + uint32_t tokenId_ = 100; + AssetValue assetValue_; +}; + +void ObjectManagerTest::SetUp() +{ + uri_ = "file:://com.examples.hmos.notepad/data/storage/el2/distributedfiles/dir/asset1.jpg"; + Asset asset{ + .name = "test_name", + .uri = uri_, + .modifyTime = "modifyTime", + .size = "size", + .hash = "modifyTime_size", + }; + asset_ = asset; + + AssetValue assetValue{ + .id = "test_name", + .name = uri_, + .uri = uri_, + .createTime = "2024.07.23", + .modifyTime = "modifyTime", + .size = "size", + .hash = "modifyTime_size", + .path = "/data/storage/el2", + }; + assetValue_ = assetValue; + + data_.push_back(10); // 10 is for testing + data_.push_back(20); // 20 is for testing + data_.push_back(30); // 30 is for testing + + OHOS::ObjectStore::AssetBindInfo AssetBindInfo{ + .storeName = "store_test", + .tableName = "table_test", + .field = "attachment", + .assetName = "asset1.jpg", + }; + assetBindInfo_ = AssetBindInfo; +} + +void ObjectManagerTest::TearDown() {} + +/** +* @tc.name: DeleteNotifier001 +* @tc.desc: DeleteNotifier test. +* @tc.type: FUNC +* @tc.require: +* @tc.author: wangbin +*/ +HWTEST_F(ObjectManagerTest, DeleteNotifier001, TestSize.Level0) +{ + auto syncManager = SequenceSyncManager::GetInstance(); + auto result = syncManager->DeleteNotifier(sequenceId_, userId_); + ASSERT_EQ(result, SequenceSyncManager::ERR_SID_NOT_EXIST); +} + +/** +* @tc.name: Process001 +* @tc.desc: Process test. +* @tc.type: FUNC +* @tc.require: +* @tc.author: wangbin +*/ +HWTEST_F(ObjectManagerTest, Process001, TestSize.Level0) +{ + auto syncManager = SequenceSyncManager::GetInstance(); + std::map results; + results = {{ "test_cloud", DistributedDB::DBStatus::OK }}; + + std::function &results)> func; + func = [](const std::map &results) { + return results; + }; + auto result = syncManager->Process(sequenceId_, results, userId_); + ASSERT_EQ(result, SequenceSyncManager::ERR_SID_NOT_EXIST); + syncManager->seqIdCallbackRelations_.emplace(sequenceId_, func); + result = syncManager->Process(sequenceId_, results, userId_); + ASSERT_EQ(result, SequenceSyncManager::SUCCESS_USER_HAS_FINISHED); +} + +/** +* @tc.name: DeleteNotifierNoLock001 +* @tc.desc: DeleteNotifierNoLock test. +* @tc.type: FUNC +* @tc.require: +* @tc.author: wangbin +*/ +HWTEST_F(ObjectManagerTest, DeleteNotifierNoLock001, TestSize.Level0) +{ + auto syncManager = SequenceSyncManager::GetInstance(); + std::function &results)> func; + func = [](const std::map &results) { + return results; + }; + syncManager->seqIdCallbackRelations_.emplace(sequenceId_, func); + std::vector seqIds = {sequenceId_, sequenceId_2, sequenceId_3}; + std::string userId = "user_1"; + auto result = syncManager->DeleteNotifierNoLock(sequenceId_, userId_); + ASSERT_EQ(result, SequenceSyncManager::SUCCESS_USER_HAS_FINISHED); + syncManager->userIdSeqIdRelations_[userId] = seqIds; + result = syncManager->DeleteNotifierNoLock(sequenceId_, userId_); + ASSERT_EQ(result, SequenceSyncManager::SUCCESS_USER_IN_USE); +} + +/** +* @tc.name: Clear001 +* @tc.desc: Clear test. +* @tc.type: FUNC +* @tc.require: +* @tc.author: wangbin +*/ +HWTEST_F(ObjectManagerTest, Clear001, TestSize.Level0) +{ + auto manager = ObjectStoreManager::GetInstance(); + auto result = manager->Clear(); + ASSERT_EQ(result, OHOS::DistributedObject::OBJECT_STORE_NOT_FOUND); +} + +/** +* @tc.name: registerAndUnregisterRemoteCallback001 +* @tc.desc: test RegisterRemoteCallback and UnregisterRemoteCallback. +* @tc.type: FUNC +* @tc.require: +* @tc.author: wangbin +*/ +HWTEST_F(ObjectManagerTest, registerAndUnregisterRemoteCallback001, TestSize.Level0) +{ + auto manager = ObjectStoreManager::GetInstance(); + sptr callback; + manager->RegisterRemoteCallback(bundleName_, sessionId_, pid_, tokenId_, callback); + ObjectStoreManager::CallbackInfo callbackInfo = manager->callbacks_.Find(tokenId_).second; + std::string prefix = bundleName_ + sessionId_; + ASSERT_NE(callbackInfo.observers_.find(prefix), callbackInfo.observers_.end()); + manager->UnregisterRemoteCallback(bundleName_, pid_, tokenId_, sessionId_); + callbackInfo = manager->callbacks_.Find(tokenId_).second; + ASSERT_EQ(callbackInfo.observers_.find(prefix), callbackInfo.observers_.end()); +} + +/** +* @tc.name: registerAndUnregisterRemoteCallback002 +* @tc.desc: abnormal use cases. +* @tc.type: FUNC +* @tc.require: +* @tc.author: wangbin +*/ +HWTEST_F(ObjectManagerTest, registerAndUnregisterRemoteCallback002, TestSize.Level0) +{ + auto manager = ObjectStoreManager::GetInstance(); + sptr callback; + uint32_t tokenId = 101; + manager->RegisterRemoteCallback("", sessionId_, pid_, tokenId, callback); + manager->RegisterRemoteCallback(bundleName_, "", pid_, tokenId, callback); + manager->RegisterRemoteCallback("", "", pid_, tokenId, callback); + ASSERT_EQ(manager->callbacks_.Find(tokenId).first, false); + manager->UnregisterRemoteCallback("", pid_, tokenId, sessionId_); +} + +/** +* @tc.name: NotifyDataChanged001 +* @tc.desc: NotifyDataChanged test. +* @tc.type: FUNC +* @tc.require: +* @tc.author: wangbin +*/ +HWTEST_F(ObjectManagerTest, NotifyDataChanged001, TestSize.Level0) +{ + auto manager = ObjectStoreManager::GetInstance(); + std::string bundleName1_ = "com.examples.ophm.notepad"; + std::string objectKey = bundleName1_ + sessionId_; + std::map>> data; + std::map> data1; + std::vector data1_; + data1_.push_back(RestoreStatus::DATA_READY); + data1_.push_back(RestoreStatus::ASSETS_READY); + data1_.push_back(RestoreStatus::ALL_READY); + data1 = {{ "objectKey", data1_ }}; + data = {{ objectKey, data1 }}; + std::shared_ptr executors = std::make_shared(5, 3); // executor pool + manager->SetThreadPool(executors); + ASSERT_EQ(manager->restoreStatus_.Find(objectKey).first, false); + manager->NotifyDataChanged(data, {}); + ASSERT_EQ(manager->restoreStatus_.Find(objectKey).second, RestoreStatus::DATA_READY); +} + +/** +* @tc.name: NotifyAssetsReady001 +* @tc.desc: NotifyAssetsReady test. +* @tc.type: FUNC +* @tc.require: +* @tc.author: wangbin +*/ +HWTEST_F(ObjectManagerTest, NotifyAssetsReady001, TestSize.Level0) +{ + auto manager = ObjectStoreManager::GetInstance(); + std::string objectKey = bundleName_ + sessionId_; + std::string srcNetworkId = "1"; + ASSERT_EQ(manager->restoreStatus_.Find(objectKey).first, false); + manager->NotifyAssetsReady(objectKey, srcNetworkId); + ASSERT_EQ(manager->restoreStatus_.Find(objectKey).second, RestoreStatus::ASSETS_READY); + manager->restoreStatus_.Clear(); + manager->restoreStatus_.Insert(objectKey, RestoreStatus::DATA_READY); + manager->NotifyAssetsReady(objectKey, srcNetworkId); + ASSERT_EQ(manager->restoreStatus_.Find(objectKey).second, RestoreStatus::ALL_READY); +} + +/** + * @tc.name: NotifyAssetsReady002 + * @tc.desc: NotifyAssetsReady test. + * @tc.type: FUNC + */ +HWTEST_F(ObjectManagerTest, NotifyAssetsReady002, TestSize.Level0) +{ + auto manager = ObjectStoreManager::GetInstance(); + std::string objectKey="com.example.myapplicaiton123456"; + std::string srcNetworkId = "654321"; + + manager->restoreStatus_.Clear(); + manager->NotifyAssetsStart(objectKey, srcNetworkId); + auto [has0, value0] = manager->restoreStatus_.Find(objectKey); + EXPECT_TRUE(has0); + EXPECT_EQ(value0, RestoreStatus::NONE); + + manager->restoreStatus_.Clear(); + manager->NotifyAssetsReady(objectKey, srcNetworkId); + auto [has1, value1] = manager->restoreStatus_.Find(objectKey); + EXPECT_TRUE(has1); + EXPECT_EQ(value1, RestoreStatus::ASSETS_READY); + + manager->restoreStatus_.Clear(); + manager->restoreStatus_.Insert(objectKey, RestoreStatus::DATA_NOTIFIED); + manager->NotifyAssetsReady(objectKey, srcNetworkId); + auto [has2, value2] = manager->restoreStatus_.Find(objectKey); + EXPECT_TRUE(has2); + EXPECT_EQ(value2, RestoreStatus::ALL_READY); + + manager->restoreStatus_.Clear(); + manager->restoreStatus_.Insert(objectKey, RestoreStatus::DATA_READY); + manager->NotifyAssetsReady(objectKey, srcNetworkId); + auto [has3, value3] = manager->restoreStatus_.Find(objectKey); + EXPECT_TRUE(has3); + EXPECT_EQ(value3, RestoreStatus::ALL_READY); + manager->restoreStatus_.Clear(); +} + +/** +* @tc.name: NotifyChange001 +* @tc.desc: NotifyChange test. +* @tc.type: FUNC +* @tc.require: +* @tc.author: wangbin +*/ +HWTEST_F(ObjectManagerTest, NotifyChange001, TestSize.Level0) +{ + auto manager = ObjectStoreManager::GetInstance(); + std::map> data; + std::map> data1; + std::vector data1_; + data1_.push_back(RestoreStatus::DATA_READY); + data_.push_back(RestoreStatus::ALL_READY); + data = {{ "test_cloud", data_ }}; + data1 = {{ "p_###SAVEINFO###001", data1_ }}; + manager->NotifyChange(data1); + manager->NotifyChange(data); +} + +/** + * @tc.name: NotifyChange002 + * @tc.desc: NotifyChange test. + * @tc.type: FUNC + */ +HWTEST_F(ObjectManagerTest, NotifyChange002, TestSize.Level0) +{ + auto manager = ObjectStoreManager::GetInstance(); + std::shared_ptr executor = std::make_shared(1, 0); + manager->SetThreadPool(executor); + std::map> data{}; + std::vector value{0}; + std::string bundleName = "com.example.myapplication"; + std::string sessionId = "123456"; + std::string source = "source"; + std::string target = "target"; + std::string timestamp = "1234567890"; + ObjectStoreManager::SaveInfo saveInfo(bundleName, sessionId, source, target, timestamp); + std::string saveInfoStr = DistributedData::Serializable::Marshall(saveInfo); + auto saveInfoValue = std::vector(saveInfoStr.begin(), saveInfoStr.end()); + std::string prefix = saveInfo.ToPropertyPrefix(); + std::string assetPrefix = prefix + "p_asset"; + data.insert_or_assign(prefix + "p_###SAVEINFO###", saveInfoValue); + data.insert_or_assign(prefix + "p_data", value); + data.insert_or_assign(assetPrefix + ObjectStore::NAME_SUFFIX, value); + data.insert_or_assign(assetPrefix + ObjectStore::URI_SUFFIX, value); + data.insert_or_assign(assetPrefix + ObjectStore::PATH_SUFFIX, value); + data.insert_or_assign(assetPrefix + ObjectStore::CREATE_TIME_SUFFIX, value); + data.insert_or_assign(assetPrefix + ObjectStore::MODIFY_TIME_SUFFIX, value); + data.insert_or_assign(assetPrefix + ObjectStore::SIZE_SUFFIX, value); + data.insert_or_assign("testkey", value); + manager->NotifyChange(data); + EXPECT_TRUE(manager->restoreStatus_.Contains(bundleName+sessionId)); + auto [has, taskId] = manager->objectTimer_.Find(bundleName+sessionId); + EXPECT_TRUE(has); + manager->restoreStatus_.Clear(); + manager->executors_->Remove(taskId); + manager->objectTimer_.Clear(); +} + +/** + * @tc.name: ComputeStatus001 + * @tc.desc: ComputeStatus.test + * @tc.type: FUNC + */ +HWTEST_F(ObjectManagerTest, ComputeStatus001, TestSize.Level0) +{ + auto manager = ObjectStoreManager::GetInstance(); + std::shared_ptr executor = std::make_shared(1, 0); + manager->SetThreadPool(executor); + std::string objectKey="com.example.myapplicaiton123456"; + std::map>> data{}; + manager->restoreStatus_.Clear(); + manager->ComputeStatus(objectKey, {}, data); + auto [has0, value0] = manager->restoreStatus_.Find(objectKey); + EXPECT_TRUE(has0); + EXPECT_EQ(value0, RestoreStatus::DATA_READY); + auto [has1, taskId1] = manager->objectTimer_.Find(objectKey); + EXPECT_TRUE(has1); + manager->executors_->Remove(taskId1); + manager->objectTimer_.Clear(); + manager->restoreStatus_.Clear(); + + manager->restoreStatus_.Insert(objectKey, RestoreStatus::ASSETS_READY); + manager->ComputeStatus(objectKey, {}, data); + auto [has2, value2] = manager->restoreStatus_.Find(objectKey); + EXPECT_TRUE(has2); + EXPECT_EQ(value2, RestoreStatus::ALL_READY); + auto [has3, taskId3] = manager->objectTimer_.Find(objectKey); + EXPECT_FALSE(has3); + manager->restoreStatus_.Clear(); +} + +/** +* @tc.name: Open001 +* @tc.desc: Open test. +* @tc.type: FUNC +* @tc.require: +* @tc.author: wangbin +*/ +HWTEST_F(ObjectManagerTest, Open001, TestSize.Level0) +{ + auto manager = ObjectStoreManager::GetInstance(); + manager->kvStoreDelegateManager_ = nullptr; + auto result = manager->Open(); + ASSERT_EQ(result, DistributedObject::OBJECT_INNER_ERROR); + std::string dataDir = "/data/app/el2/100/database"; + manager->SetData(dataDir, userId_); + manager->delegate_ = nullptr; + result = manager->Open(); + ASSERT_EQ(result, DistributedObject::OBJECT_SUCCESS); + manager->delegate_ = manager->OpenObjectKvStore(); + result = manager->Open(); + ASSERT_EQ(result, DistributedObject::OBJECT_SUCCESS); +} + +/** +* @tc.name: OnAssetChanged001 +* @tc.desc: OnAssetChanged test. +* @tc.type: FUNC +* @tc.require: +* @tc.author: wangbin +*/ +HWTEST_F(ObjectManagerTest, OnAssetChanged001, TestSize.Level0) +{ + auto manager = ObjectStoreManager::GetInstance(); + std::shared_ptr snapshot = std::make_shared(); + auto snapshotKey = appId_ + "_" + sessionId_; + auto result = manager->OnAssetChanged(tokenId_, appId_, sessionId_, deviceId_, assetValue_); + ASSERT_EQ(result, DistributedObject::OBJECT_INNER_ERROR); + manager->snapshots_.Insert(snapshotKey, snapshot); + result = manager->OnAssetChanged(tokenId_, appId_, sessionId_, deviceId_, assetValue_); + ASSERT_EQ(result, DistributedObject::OBJECT_SUCCESS); +} + +/** +* @tc.name: DeleteSnapshot001 +* @tc.desc: DeleteSnapshot test. +* @tc.type: FUNC +* @tc.require: +* @tc.author: wangbin +*/ +HWTEST_F(ObjectManagerTest, DeleteSnapshot001, TestSize.Level0) +{ + auto manager = ObjectStoreManager::GetInstance(); + std::shared_ptr snapshot = std::make_shared(); + auto snapshotKey = bundleName_ + "_" + sessionId_; + auto snapshots = manager->snapshots_.Find(snapshotKey).second; + ASSERT_EQ(snapshots, nullptr); + manager->DeleteSnapshot(bundleName_, sessionId_); + + manager->snapshots_.Insert(snapshotKey, snapshot); + snapshots = manager->snapshots_.Find(snapshotKey).second; + ASSERT_NE(snapshots, nullptr); + manager->DeleteSnapshot(bundleName_, sessionId_); +} + +/** +* @tc.name: OpenObjectKvStore001 +* @tc.desc: OpenObjectKvStore test. +* @tc.type: FUNC +* @tc.require: +* @tc.author: wangbin +*/ +HWTEST_F(ObjectManagerTest, OpenObjectKvStore001, TestSize.Level0) +{ + auto manager = ObjectStoreManager::GetInstance(); + manager->objectDataListener_ = nullptr; + ASSERT_EQ(manager->objectDataListener_, nullptr); + manager->OpenObjectKvStore(); + ASSERT_NE(manager->objectDataListener_, nullptr); + manager->OpenObjectKvStore(); +} + +/** +* @tc.name: FlushClosedStore001 +* @tc.desc: FlushClosedStore test. +* @tc.type: FUNC +* @tc.require: +* @tc.author: wangbin +*/ +HWTEST_F(ObjectManagerTest, FlushClosedStore001, TestSize.Level0) +{ + auto manager = ObjectStoreManager::GetInstance(); + manager->isSyncing_ = true; + manager->syncCount_ = 10; // test syncCount_ + manager->delegate_ = nullptr; + manager->FlushClosedStore(); + manager->isSyncing_ = false; + manager->FlushClosedStore(); + manager->syncCount_ = 0; // test syncCount_ + manager->FlushClosedStore(); + manager->delegate_ = manager->OpenObjectKvStore(); + manager->FlushClosedStore(); +} + +/** +* @tc.name: Close001 +* @tc.desc: Close test. +* @tc.type: FUNC +* @tc.require: +* @tc.author: wangbin +*/ +HWTEST_F(ObjectManagerTest, Close001, TestSize.Level0) +{ + auto manager = ObjectStoreManager::GetInstance(); + manager->syncCount_ = 1; // test syncCount_ + manager->Close(); + ASSERT_EQ(manager->syncCount_, 1); // 1 is for testing + manager->delegate_ = manager->OpenObjectKvStore(); + manager->Close(); + ASSERT_EQ(manager->syncCount_, 0); // 0 is for testing +} + +/** +* @tc.name: SyncOnStore001 +* @tc.desc: SyncOnStore test. +* @tc.type: FUNC +* @tc.require: +* @tc.author: wangbin +*/ +HWTEST_F(ObjectManagerTest, SyncOnStore001, TestSize.Level0) +{ + auto manager = ObjectStoreManager::GetInstance(); + std::function &results)> func; + func = [](const std::map &results) { + return results; + }; + std::string prefix = "ObjectManagerTest"; + std::vector deviceList; + deviceList.push_back("local"); + deviceList.push_back("local1"); + auto result = manager->SyncOnStore(prefix, deviceList, func); + ASSERT_EQ(result, OBJECT_SUCCESS); +} + +/** +* @tc.name: RevokeSaveToStore001 +* @tc.desc: RetrieveFromStore test. +* @tc.type: FUNC +* @tc.require: +* @tc.author: wangbin +*/ +HWTEST_F(ObjectManagerTest, RevokeSaveToStore001, TestSize.Level0) +{ + auto manager = ObjectStoreManager::GetInstance(); + DistributedDB::KvStoreNbDelegateMock mockDelegate; + manager->delegate_ = &mockDelegate; + std::vector id; + id.push_back(1); // for testing + id.push_back(2); // for testing + std::map> results; + results = {{ "test_cloud", id }}; + auto result = manager->RetrieveFromStore(appId_, sessionId_, results); + ASSERT_EQ(result, OBJECT_SUCCESS); +} + +/** +* @tc.name: SyncCompleted001 +* @tc.desc: SyncCompleted test. +* @tc.type: FUNC +* @tc.require: +* @tc.author: wangbin +*/ +HWTEST_F(ObjectManagerTest, SyncCompleted001, TestSize.Level0) +{ + auto manager = ObjectStoreManager::GetInstance(); + auto syncManager = SequenceSyncManager::GetInstance(); + std::map results; + results = {{ "test_cloud", DistributedDB::DBStatus::OK }}; + std::function &results)> func; + func = [](const std::map &results) { + return results; + }; + manager->userId_ = "99"; + std::vector userId; + userId.push_back(99); + userId.push_back(100); + manager->SyncCompleted(results, sequenceId_); + syncManager->userIdSeqIdRelations_ = {{ "test_cloud", userId }}; + manager->SyncCompleted(results, sequenceId_); + userId.clear(); + syncManager->seqIdCallbackRelations_.emplace(sequenceId_, func); + manager->SyncCompleted(results, sequenceId_); + userId.push_back(99); + userId.push_back(100); + manager->SyncCompleted(results, sequenceId_); +} + +/** +* @tc.name: SplitEntryKey001 +* @tc.desc: SplitEntryKey test. +* @tc.type: FUNC +* @tc.require: +* @tc.author: wangbin +*/ +HWTEST_F(ObjectManagerTest, SplitEntryKey001, TestSize.Level0) +{ + auto manager = ObjectStoreManager::GetInstance(); + std::string key1 = ""; + std::string key2 = "ObjectManagerTest"; + auto result = manager->SplitEntryKey(key1); + ASSERT_EQ(result.empty(), true); + result = manager->SplitEntryKey(key2); + ASSERT_EQ(result.empty(), true); +} + +/** +* @tc.name: SplitEntryKey002 +* @tc.desc: SplitEntryKey test. +* @tc.type: FUNC +*/ +HWTEST_F(ObjectManagerTest, SplitEntryKey002, TestSize.Level0) +{ + auto manager = ObjectStoreManager::GetInstance(); + std::string key1 = "com.example.myapplication_sessionId_source_target_1234567890_p_propertyName"; + auto res = manager->SplitEntryKey(key1); + EXPECT_EQ(res[0], "com.example.myapplication"); + EXPECT_EQ(res[1], "sessionId"); + EXPECT_EQ(res[2], "source"); + EXPECT_EQ(res[3], "target"); + EXPECT_EQ(res[4], "1234567890"); + EXPECT_EQ(res[5], "p_propertyName"); + + std::string key2 = "com.example.myapplication_sessionId_source_target_000_p_propertyName"; + res = manager->SplitEntryKey(key2); + EXPECT_TRUE(res.empty()); + + std::string key3 = "com.example.myapplicationsessionIdsourcetarget_1234567890_p_propertyName"; + res = manager->SplitEntryKey(key3); + EXPECT_TRUE(res.empty()); + + std::string key4 = "com.example.myapplicationsessionIdsource_target_1234567890_p_propertyName"; + res = manager->SplitEntryKey(key4); + EXPECT_TRUE(res.empty()); + + std::string key5 = "com.example.myapplicationsessionId_source_target_1234567890_p_propertyName"; + res = manager->SplitEntryKey(key5); + EXPECT_TRUE(res.empty()); +} + +/** +* @tc.name: ProcessOldEntry001 +* @tc.desc: ProcessOldEntry test. +* @tc.type: FUNC +* @tc.require: +* @tc.author: wangbin +*/ +HWTEST_F(ObjectManagerTest, ProcessOldEntry001, TestSize.Level0) +{ + auto manager = ObjectStoreManager::GetInstance(); + manager->delegate_ = manager->OpenObjectKvStore(); + std::vector entries; + auto status = manager->delegate_->GetEntries(std::vector(appId_.begin(), appId_.end()), entries); + ASSERT_EQ(status, DistributedDB::DBStatus::NOT_FOUND); + manager->ProcessOldEntry(appId_); + + DistributedDB::KvStoreNbDelegateMock mockDelegate; + manager->delegate_ = &mockDelegate; + status = manager->delegate_->GetEntries(std::vector(appId_.begin(), appId_.end()), entries); + ASSERT_EQ(status, DistributedDB::DBStatus::OK); + manager->ProcessOldEntry(appId_); +} + +/** +* @tc.name: ProcessSyncCallback001 +* @tc.desc: ProcessSyncCallback test. +* @tc.type: FUNC +* @tc.require: +* @tc.author: wangbin +*/ +HWTEST_F(ObjectManagerTest, ProcessSyncCallback001, TestSize.Level0) +{ + auto manager = ObjectStoreManager::GetInstance(); + std::map results; + manager->ProcessSyncCallback(results, appId_, sessionId_, deviceId_); + results.insert({"local", 1}); // for testing + ASSERT_EQ(results.empty(), false); + ASSERT_NE(results.find("local"), results.end()); + manager->ProcessSyncCallback(results, appId_, sessionId_, deviceId_); +} + +/** +* @tc.name: IsAssetComplete001 +* @tc.desc: IsAssetComplete test. +* @tc.type: FUNC +* @tc.require: +* @tc.author: wangbin +*/ +HWTEST_F(ObjectManagerTest, IsAssetComplete001, TestSize.Level0) +{ + auto manager = ObjectStoreManager::GetInstance(); + std::map> results; + std::vector completes; + completes.push_back(1); // for testing + completes.push_back(2); // for testing + std::string assetPrefix = "IsAssetComplete_test"; + results.insert({assetPrefix, completes}); + auto result = manager->IsAssetComplete(results, assetPrefix); + ASSERT_EQ(result, false); + results.insert({assetPrefix + ObjectStore::NAME_SUFFIX, completes}); + result = manager->IsAssetComplete(results, assetPrefix); + ASSERT_EQ(result, false); + results.insert({assetPrefix + ObjectStore::URI_SUFFIX, completes}); + result = manager->IsAssetComplete(results, assetPrefix); + ASSERT_EQ(result, false); + results.insert({assetPrefix + ObjectStore::PATH_SUFFIX, completes}); + result = manager->IsAssetComplete(results, assetPrefix); + ASSERT_EQ(result, false); + results.insert({assetPrefix + ObjectStore::CREATE_TIME_SUFFIX, completes}); + result = manager->IsAssetComplete(results, assetPrefix); + ASSERT_EQ(result, false); + results.insert({assetPrefix + ObjectStore::MODIFY_TIME_SUFFIX, completes}); + result = manager->IsAssetComplete(results, assetPrefix); + ASSERT_EQ(result, false); + results.insert({assetPrefix + ObjectStore::SIZE_SUFFIX, completes}); + result = manager->IsAssetComplete(results, assetPrefix); + ASSERT_EQ(result, true); +} + +/** +* @tc.name: GetAssetsFromDBRecords001 +* @tc.desc: GetAssetsFromDBRecords test. +* @tc.type: FUNC +* @tc.require: +* @tc.author: wangbin +*/ +HWTEST_F(ObjectManagerTest, GetAssetsFromDBRecords001, TestSize.Level0) +{ + auto manager = ObjectStoreManager::GetInstance(); + std::map> results; + std::vector completes; + completes.push_back(1); // for testing + completes.push_back(2); // for testing + std::string assetPrefix = "IsAssetComplete_test"; + results.insert({assetPrefix, completes}); + results.insert({assetPrefix + ObjectStore::NAME_SUFFIX, completes}); + results.insert({assetPrefix + ObjectStore::URI_SUFFIX, completes}); + results.insert({assetPrefix + ObjectStore::MODIFY_TIME_SUFFIX, completes}); + results.insert({assetPrefix + ObjectStore::SIZE_SUFFIX, completes}); + auto result = manager->GetAssetsFromDBRecords(results); + ASSERT_EQ(result.empty(), false); +} + +/** +* @tc.name: GetAssetsFromDBRecords002 +* @tc.desc: GetAssetsFromDBRecords test. +* @tc.type: FUNC +*/ +HWTEST_F(ObjectManagerTest, GetAssetsFromDBRecords002, TestSize.Level0) +{ + auto manager = ObjectStoreManager::GetInstance(); + std::map> result; + + std::vector value0{0}; + std::string data0 = "[STRING]test"; + value0.insert(value0.end(), data0.begin(), data0.end()); + + std::vector value1{0}; + std::string data1 = "(string)test"; + value1.insert(value1.end(), data1.begin(), data1.end()); + + std::string prefix = "bundleName_sessionId_source_target_timestamp"; + std::string dataKey = prefix + "_p_data"; + std::string assetPrefix0 = prefix + "_p_asset0"; + std::string assetPrefix1 = prefix + "_p_asset1"; + + result.insert({dataKey, value0}); + auto assets = manager->GetAssetsFromDBRecords(result); + EXPECT_TRUE(assets.empty()); + + result.clear(); + result.insert({assetPrefix0 + ObjectStore::URI_SUFFIX, value0}); + assets = manager->GetAssetsFromDBRecords(result); + EXPECT_TRUE(assets.empty()); + + result.clear(); + result.insert({assetPrefix1 + ObjectStore::NAME_SUFFIX, value1}); + assets = manager->GetAssetsFromDBRecords(result); + EXPECT_TRUE(assets.empty()); + + result.clear(); + result.insert({assetPrefix0 + ObjectStore::NAME_SUFFIX, value0}); + result.insert({assetPrefix0 + ObjectStore::URI_SUFFIX, value0}); + result.insert({assetPrefix0 + ObjectStore::MODIFY_TIME_SUFFIX, value0}); + result.insert({assetPrefix0 + ObjectStore::SIZE_SUFFIX, value0}); + assets = manager->GetAssetsFromDBRecords(result); + ASSERT_EQ(assets.size(), 1); + EXPECT_EQ(assets[0].name, "test"); + EXPECT_EQ(assets[0].uri, "test"); + EXPECT_EQ(assets[0].modifyTime, "test"); + EXPECT_EQ(assets[0].size, "test"); + EXPECT_EQ(assets[0].hash, "test_test"); + + result.clear(); + result.insert({assetPrefix1 + ObjectStore::NAME_SUFFIX, value1}); + result.insert({assetPrefix1 + ObjectStore::URI_SUFFIX, value1}); + result.insert({assetPrefix1 + ObjectStore::MODIFY_TIME_SUFFIX, value1}); + result.insert({assetPrefix1 + ObjectStore::SIZE_SUFFIX, value1}); + assets = manager->GetAssetsFromDBRecords(result); + ASSERT_EQ(assets.size(), 1); + EXPECT_EQ(assets[0].name, "(string)test"); + EXPECT_EQ(assets[0].uri, "(string)test"); + EXPECT_EQ(assets[0].modifyTime, "(string)test"); + EXPECT_EQ(assets[0].size, "(string)test"); + EXPECT_EQ(assets[0].hash, "(string)test_(string)test"); +} + +/** +* @tc.name: RegisterAssetsLister001 +* @tc.desc: RegisterAssetsLister test. +* @tc.type: FUNC +* @tc.require: +* @tc.author: wangbin +*/ +HWTEST_F(ObjectManagerTest, RegisterAssetsLister001, TestSize.Level0) +{ + auto manager = ObjectStoreManager::GetInstance(); + manager->objectAssetsSendListener_ = nullptr; + manager->objectAssetsRecvListener_ = nullptr; + auto result = manager->RegisterAssetsLister(); + ASSERT_EQ(result, true); + manager->objectAssetsSendListener_ = new ObjectAssetsSendListener(); + manager->objectAssetsRecvListener_ = new ObjectAssetsRecvListener();; + result = manager->RegisterAssetsLister(); + ASSERT_EQ(result, true); +} + +/** +* @tc.name: RegisterAssetsLister001 +* @tc.desc: PushAssets test. +* @tc.type: FUNC +* @tc.require: +* @tc.author: wangbin +*/ +HWTEST_F(ObjectManagerTest, PushAssets001, TestSize.Level0) +{ + auto manager = ObjectStoreManager::GetInstance(); + std::map> data; + std::string assetPrefix = "PushAssets_test"; + std::vector completes; + completes.push_back(1); // for testing + completes.push_back(2); // for testing + data.insert({assetPrefix, completes}); + auto result = manager->PushAssets(100, appId_, sessionId_, data, deviceId_); + ASSERT_EQ(result, DistributedObject::OBJECT_SUCCESS); +} + +/** +* @tc.name: AddNotifier001 +* @tc.desc: AddNotifie and DeleteNotifier test. +* @tc.type: FUNC +*/ +HWTEST_F(ObjectManagerTest, AddNotifier001, TestSize.Level0) +{ + auto syncManager = SequenceSyncManager::GetInstance(); + std::function &results)> func; + func = [](const std::map &results) { + return results; + }; + auto sequenceId_ = syncManager->AddNotifier(userId_, func); + auto result = syncManager->DeleteNotifier(sequenceId_, userId_); + ASSERT_EQ(result, SequenceSyncManager::SUCCESS_USER_HAS_FINISHED); +} + +/** +* @tc.name: AddNotifier002 +* @tc.desc: AddNotifie and DeleteNotifier test. +* @tc.type: FUNC +*/ +HWTEST_F(ObjectManagerTest, AddNotifier002, TestSize.Level0) +{ + auto syncManager = SequenceSyncManager::GetInstance(); + std::function &results)> func; + func = [](const std::map &results) { + return results; + }; + auto sequenceId = syncManager->AddNotifier(userId_, func); + ASSERT_NE(sequenceId, sequenceId_); + auto result = syncManager->DeleteNotifier(sequenceId_, userId_); + ASSERT_EQ(result, SequenceSyncManager::ERR_SID_NOT_EXIST); +} + +/** +* @tc.name: BindAsset 001 +* @tc.desc: BindAsset test. +* @tc.type: FUNC +*/ +HWTEST_F(ObjectManagerTest, BindAsset001, TestSize.Level0) +{ + auto manager = ObjectStoreManager::GetInstance(); + std::string bundleName = "BindAsset"; + uint32_t tokenId = IPCSkeleton::GetCallingTokenID(); + auto result = manager->BindAsset(tokenId, bundleName, sessionId_, assetValue_, assetBindInfo_); + ASSERT_EQ(result, DistributedObject::OBJECT_DBSTATUS_ERROR); +} +} // namespace OHOS::Test diff --git a/datamgr_service/services/distributeddataservice/service/test/object_snapshot_test.cpp b/datamgr_service/services/distributeddataservice/service/test/object_snapshot_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..90cdc9daf4852c6f521e6104ec59eb004b0bc2b9 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/test/object_snapshot_test.cpp @@ -0,0 +1,371 @@ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define LOG_TAG "ObjectSnapshotTest" + +#include "object_snapshot.h" +#include +#include "snapshot/machine_status.h" +#include "executor_pool.h" + +using namespace testing::ext; +using namespace OHOS::DistributedObject; +using namespace OHOS::DistributedData; +namespace OHOS::Test { + +class ObjectSnapshotTest : public testing::Test { +public: + void SetUp(); + void TearDown(); + +protected: + AssetBindInfo AssetBindInfo_; + Asset asset_; + std::string uri_; + StoreInfo storeInfo_; +}; + +void ObjectSnapshotTest::SetUp() +{ + uri_ = "file:://com.example.hmos.notepad/data/storage/el2/distributedfiles/dir/asset1.jpg"; + Asset asset{ + .name = "test_name", + .uri = uri_, + .modifyTime = "modifyTime", + .size = "size", + .hash = "modifyTime_size", + }; + asset_ = asset; + + VBucket vBucket{ { "11", 111 } }; + AssetBindInfo AssetBindInfo{ + .storeName = "store_test", + .tableName = "table_test", + .primaryKey = vBucket, + .field = "attachment", + .assetName = "asset1.jpg", + }; + AssetBindInfo_ = AssetBindInfo; + StoreInfo storeInfo { + .tokenId = 0, + .bundleName = "bundleName_test", + .storeName = "store_test", + .instanceId = 1, + .user = 100, + }; + storeInfo_ = storeInfo; + ChangedAssetInfo changedAssetInfo(asset, AssetBindInfo, storeInfo); +} + +void ObjectSnapshotTest::TearDown() {} + +/** +* @tc.name: UploadTest001 +* @tc.desc: Upload test. +* @tc.type: FUNC +* @tc.require: +* @tc.author: wangbin +*/ +HWTEST_F(ObjectSnapshotTest, UploadTest001, TestSize.Level0) +{ + auto snapshot = std::make_shared(); + Asset asset{ + .name = "test_name", + .uri = "file:://com.example.hmos.notepad/data/storage/el2/distributedfiles/dir/asset2.jpg", + .modifyTime = "modifyTime1", + .size = "size1", + .hash = "modifyTime1_size1", + }; + snapshot->BindAsset(asset_, AssetBindInfo_, storeInfo_); + ASSERT_EQ(snapshot->IsBoundAsset(asset), false); + auto upload = snapshot->Upload(asset); + ASSERT_EQ(upload, 0); +} + +/** +* @tc.name: UploadTest002 +* @tc.desc: Upload test. +* @tc.type: FUNC +* @tc.require: +* @tc.author: wangbin +*/ +HWTEST_F(ObjectSnapshotTest, UploadTest002, TestSize.Level0) +{ + auto snapshot = std::make_shared(); + snapshot->BindAsset(asset_, AssetBindInfo_, storeInfo_); + ASSERT_EQ(snapshot->IsBoundAsset(asset_), true); + auto upload = snapshot->Upload(asset_); + ASSERT_EQ(upload, 0); +} + +/** +* @tc.name: DownloadTest001 +* @tc.desc: Download test. +* @tc.type: FUNC +* @tc.require: +* @tc.author: wangbin +*/ +HWTEST_F(ObjectSnapshotTest, DownloadTest001, TestSize.Level0) +{ + auto snapshot = std::make_shared(); + Asset asset{ + .name = "test_name", + .uri = "file:://com.example.hmos.notepad/data/storage/el2/distributedfiles/dir/asset2.jpg", + .modifyTime = "modifyTime1", + .size = "size1", + .hash = "modifyTime1_size1", + }; + snapshot->BindAsset(asset_, AssetBindInfo_, storeInfo_); + ASSERT_EQ(snapshot->IsBoundAsset(asset), false); + auto upload = snapshot->Download(asset); + ASSERT_EQ(upload, 0); +} + +/** +* @tc.name: DownloadTest002 +* @tc.desc: Download test. +* @tc.type: FUNC +* @tc.require: +* @tc.author: wangbin +*/ +HWTEST_F(ObjectSnapshotTest, DownloadTest002, TestSize.Level0) +{ + auto snapshot = std::make_shared(); + snapshot->BindAsset(asset_, AssetBindInfo_, storeInfo_); + ASSERT_EQ(snapshot->IsBoundAsset(asset_), true); + auto upload = snapshot->Download(asset_); + ASSERT_EQ(upload, 0); +} + +/** +* @tc.name: GetAssetStatusTest001 +* @tc.desc: GetAssetStatus test. +* @tc.type: FUNC +* @tc.require: +* @tc.author: wangbin +*/ +HWTEST_F(ObjectSnapshotTest, GetAssetStatusTest001, TestSize.Level0) +{ + auto snapshot = std::make_shared(); + Asset asset{ + .name = "test_name", + .uri = "file:://com.example.hmos.notepad/data/storage/el2/distributedfiles/dir/asset2.jpg", + .modifyTime = "modifyTime1", + .size = "size1", + .hash = "modifyTime1_size1", + }; + snapshot->BindAsset(asset_, AssetBindInfo_, storeInfo_); + ASSERT_EQ(snapshot->IsBoundAsset(asset), false); + auto upload = snapshot->GetAssetStatus(asset); + ASSERT_EQ(upload, STATUS_BUTT); +} + +/** +* @tc.name: GetAssetStatusTest002 +* @tc.desc: GetAssetStatus test. +* @tc.type: FUNC +* @tc.require: +* @tc.author: wangbin +*/ +HWTEST_F(ObjectSnapshotTest, GetAssetStatusTest002, TestSize.Level0) +{ + auto snapshot = std::make_shared(); + snapshot->BindAsset(asset_, AssetBindInfo_, storeInfo_); + ASSERT_EQ(snapshot->IsBoundAsset(asset_), true); + auto upload = snapshot->GetAssetStatus(asset_); + ASSERT_EQ(upload, STATUS_STABLE); +} + +/** +* @tc.name: UploadedTest001 +* @tc.desc: Uploaded test. +* @tc.type: FUNC +* @tc.require: +* @tc.author: wangbin +*/ +HWTEST_F(ObjectSnapshotTest, UploadedTest001, TestSize.Level0) +{ + auto snapshot = std::make_shared(); + Asset asset{ + .name = "test_name", + .uri = "file:://com.example.hmos.notepad/data/storage/el2/distributedfiles/dir/asset2.jpg", + .modifyTime = "modifyTime1", + .size = "size1", + .hash = "modifyTime1_size1", + }; + snapshot->BindAsset(asset_, AssetBindInfo_, storeInfo_); + ASSERT_EQ(snapshot->IsBoundAsset(asset), false); + auto upload = snapshot->Uploaded(asset); + ASSERT_EQ(upload, E_OK); +} + +/** +* @tc.name: UploadedTest002 +* @tc.desc: Uploaded test. +* @tc.type: FUNC +* @tc.require: +* @tc.author: wangbin +*/ +HWTEST_F(ObjectSnapshotTest, UploadedTest002, TestSize.Level0) +{ + auto snapshot = std::make_shared(); + snapshot->BindAsset(asset_, AssetBindInfo_, storeInfo_); + ASSERT_EQ(snapshot->IsBoundAsset(asset_), true); + auto upload = snapshot->Uploaded(asset_); + ASSERT_EQ(upload, E_OK); +} + +/** +* @tc.name: DownloadedTest001 +* @tc.desc: Downloaded test. +* @tc.type: FUNC +* @tc.require: +* @tc.author: wangbin +*/ +HWTEST_F(ObjectSnapshotTest, DownloadedTest001, TestSize.Level0) +{ + auto snapshot = std::make_shared(); + Asset asset{ + .name = "test_name", + .uri = "file:://com.example.hmos.notepad/data/storage/el2/distributedfiles/dir/asset2.jpg", + .modifyTime = "modifyTime1", + .size = "size1", + .hash = "modifyTime1_size1", + }; + snapshot->BindAsset(asset_, AssetBindInfo_, storeInfo_); + ASSERT_EQ(snapshot->IsBoundAsset(asset), false); + auto upload = snapshot->Downloaded(asset); + ASSERT_EQ(upload, E_OK); +} + +/** +* @tc.name: DownloadedTest002 +* @tc.desc: Downloaded test. +* @tc.type: FUNC +* @tc.require: +* @tc.author: wangbin +*/ +HWTEST_F(ObjectSnapshotTest, DownloadedTest002, TestSize.Level0) +{ + auto snapshot = std::make_shared(); + snapshot->BindAsset(asset_, AssetBindInfo_, storeInfo_); + ASSERT_EQ(snapshot->IsBoundAsset(asset_), true); + auto upload = snapshot->Downloaded(asset_); + ASSERT_EQ(upload, E_OK); +} + +/** +* @tc.name: TransferredTest001 +* @tc.desc: Transferred test. +* @tc.type: FUNC +* @tc.require: +* @tc.author: wangbin +*/ +HWTEST_F(ObjectSnapshotTest, TransferredTest001, TestSize.Level0) +{ + auto snapshot = std::make_shared(); + Asset asset{ + .name = "test_name", + .uri = "file:://com.example.hmos.notepad/data/storage/el2/distributedfiles/dir/asset2.jpg", + .modifyTime = "modifyTime1", + .size = "size1", + .hash = "modifyTime1_size1", + }; + snapshot->BindAsset(asset_, AssetBindInfo_, storeInfo_); + ASSERT_EQ(snapshot->IsBoundAsset(asset), false); + auto upload = snapshot->Transferred(asset); + ASSERT_EQ(upload, E_OK); +} + +/** +* @tc.name: TransferredTest002 +* @tc.desc: Transferred test. +* @tc.type: FUNC +* @tc.require: +* @tc.author: wangbin +*/ +HWTEST_F(ObjectSnapshotTest, TransferredTest002, TestSize.Level0) +{ + auto snapshot = std::make_shared(); + snapshot->BindAsset(asset_, AssetBindInfo_, storeInfo_); + ASSERT_EQ(snapshot->IsBoundAsset(asset_), true); + auto upload = snapshot->Transferred(asset_); + ASSERT_EQ(upload, E_OK); +} + +/** +* @tc.name: OnDataChangedTest001 +* @tc.desc: OnDataChanged test. +* @tc.type: FUNC +* @tc.require: +* @tc.author: wangbin +*/ +HWTEST_F(ObjectSnapshotTest, OnDataChangedTest001, TestSize.Level0) +{ + auto snapshot = std::make_shared(); + std::string deviceId = "object_snapshot_test_1"; + Asset asset{ + .name = "test_name", + .uri = "file:://com.example.hmos.notepad/data/storage/el2/distributedfiles/dir/asset2.jpg", + .modifyTime = "modifyTime1", + .size = "size1", + .hash = "modifyTime1_size1", + }; + snapshot->BindAsset(asset_, AssetBindInfo_, storeInfo_); + ASSERT_EQ(snapshot->IsBoundAsset(asset), false); + auto upload = snapshot->OnDataChanged(asset, deviceId); + ASSERT_EQ(upload, E_OK); +} + +/** +* @tc.name: OnDataChangedTest002 +* @tc.desc: OnDataChanged test. +* @tc.type: FUNC +* @tc.require: +* @tc.author: wangbin +*/ +HWTEST_F(ObjectSnapshotTest, OnDataChangedTest002, TestSize.Level0) +{ + auto snapshot = std::make_shared(); + std::string deviceId = "object_snapshot_test_1"; + snapshot->BindAsset(asset_, AssetBindInfo_, storeInfo_); + ASSERT_EQ(snapshot->IsBoundAsset(asset_), true); + auto upload = snapshot->OnDataChanged(asset_, deviceId); + ASSERT_EQ(upload, E_OK); +} + +/** +* @tc.name: BindAsset001 +* @tc.desc: BindAsset test. +* @tc.type: FUNC +* @tc.require: +* @tc.author: wangbin +*/ +HWTEST_F(ObjectSnapshotTest, BindAsset001, TestSize.Level0) +{ + auto snapshot = std::make_shared(); + Asset asset{ + .name = "test_name", + .uri = "file:://com.example.hmos.notepad/data/storage/el2/distributedfiles/dir/asset2.jpg", + .modifyTime = "modifyTime1", + .size = "size1", + .hash = "modifyTime1_size1", + }; + ASSERT_EQ(snapshot->IsBoundAsset(asset), false); + snapshot->BindAsset(asset, AssetBindInfo_, storeInfo_); + ASSERT_EQ(snapshot->IsBoundAsset(asset), true); + snapshot->BindAsset(asset, AssetBindInfo_, storeInfo_); +} +} // namespace OHOS::Test \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/test/rdb_asset_loader_test.cpp b/datamgr_service/services/distributeddataservice/service/test/rdb_asset_loader_test.cpp index 9ab9c95ef80dab137089088ea62bd128c771adf4..91b54fb417965db1fc7bac83474ee52434e78c08 100644 --- a/datamgr_service/services/distributeddataservice/service/test/rdb_asset_loader_test.cpp +++ b/datamgr_service/services/distributeddataservice/service/test/rdb_asset_loader_test.cpp @@ -17,8 +17,11 @@ #include "gtest/gtest.h" #include "log_print.h" #include "rdb_asset_loader.h" +#include "rdb_notifier_proxy.h" +#include "rdb_watcher.h" #include "store/cursor.h" - +#include "store/general_value.h" +#include "store/general_watcher.h" using namespace OHOS; using namespace testing; using namespace testing::ext; @@ -61,6 +64,14 @@ public: } }; +class RdbWatcherTest : public testing::Test { +public: + static void SetUpTestCase(void){}; + static void TearDownTestCase(void){}; + void SetUp(){}; + void TearDown(){}; +}; + /** * @tc.name: Download * @tc.desc: RdbAssetLoader download test. @@ -121,5 +132,25 @@ HWTEST_F(RdbAssetLoaderTest, PostEvent, TestSize.Level0) auto result = rdbAssetLoader.Download(tableName, groupId, prefix, assets); EXPECT_EQ(result, DistributedDB::DBStatus::CLOUD_ERROR); } + +/** +* @tc.name: RdbWatcher +* @tc.desc: RdbWatcher function test. +* @tc.type: FUNC +* @tc.require: +* @tc.author: SQL +*/ +HWTEST_F(RdbWatcherTest, RdbWatcher, TestSize.Level0) +{ + GeneralWatcher::Origin origin; + GeneralWatcher::PRIFields primaryFields = {{"primaryFields1", "primaryFields2"}}; + GeneralWatcher::ChangeInfo values; + std::shared_ptr watcher = std::make_shared(); + sptr notifier; + watcher->SetNotifier(notifier); + EXPECT_EQ(watcher->notifier_, nullptr); + auto result = watcher->OnChange(origin, primaryFields, std::move(values)); + EXPECT_EQ(result, GeneralError::E_NOT_INIT); +} } // namespace DistributedRDBTest } // namespace OHOS::Test \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/test/rdb_cloud_test.cpp b/datamgr_service/services/distributeddataservice/service/test/rdb_cloud_test.cpp index 3be6d2d0f7dbad3436a5a41a02bed3b159b6f964..0646e6ff9a77baa0ecd474bd5533cdebec549f57 100644 --- a/datamgr_service/services/distributeddataservice/service/test/rdb_cloud_test.cpp +++ b/datamgr_service/services/distributeddataservice/service/test/rdb_cloud_test.cpp @@ -14,9 +14,10 @@ */ #define LOG_TAG "RdbCloudTest" +#include "rdb_cloud.h" + #include "gtest/gtest.h" #include "log_print.h" -#include "rdb_cloud.h" #include "rdb_cloud_data_translate.h" using namespace testing::ext; @@ -56,7 +57,7 @@ HWTEST_F(RdbCloudTest, RdbCloudTest001, TestSize.Level1) { BindAssets bindAssets; Bytes bytes; - std::shared_ptr cloudDB = std::make_shared(); + std::shared_ptr cloudDB = std::make_shared(); RdbCloud rdbCloud(cloudDB, &bindAssets); std::string tableName = "testTable"; auto result = rdbCloud.BatchInsert(tableName, std::move(g_DBVBucket), g_DBVBucket); @@ -77,7 +78,7 @@ HWTEST_F(RdbCloudTest, RdbCloudTest001, TestSize.Level1) HWTEST_F(RdbCloudTest, RdbCloudTest002, TestSize.Level1) { BindAssets bindAssets; - std::shared_ptr cloudDB = std::make_shared(); + std::shared_ptr cloudDB = std::make_shared(); RdbCloud rdbCloud(cloudDB, &bindAssets); std::string tableName = "testTable"; rdbCloud.Lock(); @@ -113,7 +114,7 @@ HWTEST_F(RdbCloudTest, RdbCloudTest003, TestSize.Level1) { BindAssets bindAssets; bindAssets.bindAssets = nullptr; - std::shared_ptr cloudDB = std::make_shared(); + std::shared_ptr cloudDB = std::make_shared(); RdbCloud rdbCloud(cloudDB, &bindAssets); std::string tableName = "testTable"; DBVBucket extends = { @@ -151,7 +152,7 @@ HWTEST_F(RdbCloudTest, RdbCloudTest003, TestSize.Level1) HWTEST_F(RdbCloudTest, ConvertStatus, TestSize.Level1) { BindAssets bindAssets; - std::shared_ptr cloudDB = std::make_shared(); + std::shared_ptr cloudDB = std::make_shared(); RdbCloud rdbCloud(cloudDB, &bindAssets); auto result = rdbCloud.ConvertStatus(GeneralError::E_OK); EXPECT_EQ(result, DBStatus::OK); diff --git a/datamgr_service/services/distributeddataservice/service/test/rdb_cursor_test.cpp b/datamgr_service/services/distributeddataservice/service/test/rdb_cursor_test.cpp index d8aa4815288ff55cbfadb138c55d7fb6bc2f7807..02f36f3ca6dc9cbd553e2b12f5f5610b871f3fbf 100644 --- a/datamgr_service/services/distributeddataservice/service/test/rdb_cursor_test.cpp +++ b/datamgr_service/services/distributeddataservice/service/test/rdb_cursor_test.cpp @@ -16,7 +16,6 @@ #include "gtest/gtest.h" #include "log_print.h" -#define private public #include "rdb_cursor.h" #include "result_set.h" #include "store/general_value.h" diff --git a/datamgr_service/services/distributeddataservice/service/test/rdb_general_store_test.cpp b/datamgr_service/services/distributeddataservice/service/test/rdb_general_store_test.cpp index a0a1794ca435a51ab29f9716b0d56a46a7f1a708..6697dae26ee74c0766a53abce35375daba9938c1 100644 --- a/datamgr_service/services/distributeddataservice/service/test/rdb_general_store_test.cpp +++ b/datamgr_service/services/distributeddataservice/service/test/rdb_general_store_test.cpp @@ -14,19 +14,20 @@ */ #define LOG_TAG "RdbGeneralStoreTest" +#include "rdb_general_store.h" #include +#include #include "bootstrap.h" #include "cloud/schema_meta.h" #include "gtest/gtest.h" -#define private public -#include "rdb_general_store.h" #include "log_print.h" #include "metadata/meta_data_manager.h" #include "metadata/secret_key_meta_data.h" #include "metadata/store_meta_data.h" #include "metadata/store_meta_data_local.h" +#include "mock/general_watcher_mock.h" #include "rdb_query.h" #include "store/general_store.h" #include "types.h" @@ -230,42 +231,13 @@ protected: } }; -class MockQuery : public GenQuery { -public: - ~MockQuery() = default; - static constexpr uint64_t TYPE_ID = 0x20000001; - std::vector tables_; - bool lastResult = false; - bool IsEqual(uint64_t tid) override - { - return (tid == TYPE_ID) && lastResult; - } - - std::vector GetTables() override - { - return tables_; - } -}; - -class MockGeneralWatcher : public DistributedData::GeneralWatcher { -public: - int32_t OnChange(const Origin &origin, const PRIFields &primaryFields, ChangeInfo &&values) override - { - return GeneralError::E_OK; - } - - int32_t OnChange(const Origin &origin, const Fields &fields, ChangeData &&datas) override - { - return GeneralError::E_OK; - } -}; - class MockStoreChangedData : public DistributedDB::StoreChangedData { public: std::string GetDataChangeDevice() const override { return "DataChangeDevice"; } + void GetStoreProperty(DistributedDB::StoreProperty &storeProperty) const override { return; @@ -433,6 +405,29 @@ HWTEST_F(RdbGeneralStoreTest, Close, TestSize.Level1) EXPECT_EQ(ret, GeneralError::E_BUSY); } +/** +* @tc.name: Close +* @tc.desc: RdbGeneralStore Close test +* @tc.type: FUNC +* @tc.require: +* @tc.author: shaoyuanzhao +*/ +HWTEST_F(RdbGeneralStoreTest, BusyClose, TestSize.Level1) +{ + auto store = std::make_shared(metaData_); + ASSERT_NE(store, nullptr); + std::thread thread([store]() { + std::unique_lockrwMutex_)> lock(store->rwMutex_); + std::this_thread::sleep_for(std::chrono::seconds(1)); + }); + std::this_thread::sleep_for(std::chrono::milliseconds(500)); + auto ret = store->Close(); + EXPECT_EQ(ret, GeneralError::E_BUSY); + thread.join(); + ret = store->Close(); + EXPECT_EQ(ret, GeneralError::E_OK); +} + /** * @tc.name: Execute * @tc.desc: RdbGeneralStore Execute function test @@ -658,13 +653,15 @@ HWTEST_F(RdbGeneralStoreTest, Query001, TestSize.Level1) ASSERT_NE(store, nullptr); std::string table = "table"; std::string sql = "sql"; - auto result = store->Query(table, sql, std::move(g_RdbValues)); - EXPECT_EQ(result, nullptr); + auto [err1, result1] = store->Query(table, sql, std::move(g_RdbValues)); + EXPECT_EQ(err1, GeneralError::E_ALREADY_CLOSED); + EXPECT_EQ(result1, nullptr); MockRelationalStoreDelegate mockDelegate; store->delegate_ = &mockDelegate; - result = store->Query(table, sql, std::move(g_RdbValues)); - EXPECT_NE(result, nullptr); + auto [err2, result2] = store->Query(table, sql, std::move(g_RdbValues)); + EXPECT_EQ(err2, GeneralError::E_OK); + EXPECT_NE(result2, nullptr); } /** @@ -681,12 +678,14 @@ HWTEST_F(RdbGeneralStoreTest, Query002, TestSize.Level1) std::string table = "table"; std::string sql = "sql"; MockQuery query; - auto result = store->Query(table, query); - EXPECT_EQ(result, nullptr); + auto [err1, result1] = store->Query(table, query); + EXPECT_EQ(err1, GeneralError::E_INVALID_ARGS); + EXPECT_EQ(result1, nullptr); query.lastResult = true; - result = store->Query(table, query); - EXPECT_EQ(result, nullptr); + auto [err2, result2] = store->Query(table, query); + EXPECT_EQ(err2, GeneralError::E_ALREADY_CLOSED); + EXPECT_EQ(result2, nullptr); } /** @@ -747,7 +746,8 @@ HWTEST_F(RdbGeneralStoreTest, PreSharing, TestSize.Level1) auto store = new (std::nothrow) RdbGeneralStore(metaData_); ASSERT_NE(store, nullptr); MockQuery query; - auto result = store->PreSharing(query); + auto [errCode, result] = store->PreSharing(query); + EXPECT_NE(errCode, GeneralError::E_OK); EXPECT_EQ(result, nullptr); } @@ -867,7 +867,7 @@ HWTEST_F(RdbGeneralStoreTest, OnChange, TestSize.Level1) /** * @tc.name: Release -* @tc.desc: RdbGeneralStore Release function test +* @tc.desc: RdbGeneralStore Release and AddRef function test * @tc.type: FUNC * @tc.require: * @tc.author: SQL @@ -878,6 +878,8 @@ HWTEST_F(RdbGeneralStoreTest, Release, TestSize.Level1) ASSERT_NE(store, nullptr); auto result = store->Release(); EXPECT_EQ(result, 0); + store = new (std::nothrow) RdbGeneralStore(metaData_); + store->ref_ = 0; result = store->Release(); EXPECT_EQ(result, 0); store->ref_ = 2; @@ -1009,10 +1011,13 @@ HWTEST_F(RdbGeneralStoreTest, QuerySql, TestSize.Level1) ASSERT_NE(store, nullptr); MockRelationalStoreDelegate mockDelegate; store->delegate_ = &mockDelegate; - auto result = store->QuerySql("", std::move(g_RdbValues)); - EXPECT_TRUE(result.empty()); - result = store->QuerySql("sql", std::move(g_RdbValues)); - EXPECT_TRUE(result.empty()); + auto [err1, result1] = store->QuerySql("", std::move(g_RdbValues)); + EXPECT_EQ(err1, GeneralError::E_ERROR); + EXPECT_TRUE(result1.empty()); + + auto [err2, result2] = store->QuerySql("sql", std::move(g_RdbValues)); + EXPECT_EQ(err1, GeneralError::E_ERROR); + EXPECT_TRUE(result2.empty()); } } // namespace DistributedRDBTest } // namespace OHOS::Test \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/test/value_proxy_test.cpp b/datamgr_service/services/distributeddataservice/service/test/value_proxy_test.cpp index dba39e9d06b6f297c97ce893a2a21a77d2a6f913..327e2e4905cc6a3faf68ca7c16087ac5fe91eb4c 100644 --- a/datamgr_service/services/distributeddataservice/service/test/value_proxy_test.cpp +++ b/datamgr_service/services/distributeddataservice/service/test/value_proxy_test.cpp @@ -13,14 +13,14 @@ * limitations under the License. */ -#define LOG_TAG "CloudDataTest" +#define LOG_TAG "ValueProxyServiceTest" #include #include "log_print.h" #include "value_proxy.h" -namespace Test { +namespace OHOS::Test { using namespace testing::ext; using namespace OHOS::DistributedData; -class ValueProxyTest : public testing::Test { +class ValueProxyServiceTest : public testing::Test { }; /** @@ -30,7 +30,7 @@ class ValueProxyTest : public testing::Test { * @tc.require: * @tc.author: ht */ -HWTEST_F(ValueProxyTest, VBucketsNormal2GaussDB, TestSize.Level0) +HWTEST_F(ValueProxyServiceTest, VBucketsNormal2GaussDB, TestSize.Level0) { std::vector dbVBuckets; OHOS::DistributedData::VBuckets extends = { @@ -48,7 +48,7 @@ HWTEST_F(ValueProxyTest, VBucketsNormal2GaussDB, TestSize.Level0) * @tc.require: * @tc.author: ht */ -HWTEST_F(ValueProxyTest, VBucketsGaussDB2Normal, TestSize.Level0) +HWTEST_F(ValueProxyServiceTest, VBucketsGaussDB2Normal, TestSize.Level0) { std::vector dbVBuckets = { {{"#gid", {"0000000"}}, {"#flag", {true }}, {"#value", {int64_t(100)}}, {"#float", {double(100)}}}, @@ -66,7 +66,7 @@ HWTEST_F(ValueProxyTest, VBucketsGaussDB2Normal, TestSize.Level0) * @tc.require: * @tc.author: ht */ -HWTEST_F(ValueProxyTest, VBucketsNormal2Rdb, TestSize.Level0) +HWTEST_F(ValueProxyServiceTest, VBucketsNormal2Rdb, TestSize.Level0) { using RdbBucket = OHOS::NativeRdb::ValuesBucket; std::vector rdbVBuckets; @@ -85,7 +85,7 @@ HWTEST_F(ValueProxyTest, VBucketsNormal2Rdb, TestSize.Level0) * @tc.require: * @tc.author: ht */ -HWTEST_F(ValueProxyTest, VBucketsRdb2Normal, TestSize.Level0) +HWTEST_F(ValueProxyServiceTest, VBucketsRdb2Normal, TestSize.Level0) { using RdbBucket = OHOS::NativeRdb::ValuesBucket; using RdbValue = OHOS::NativeRdb::ValueObject; @@ -112,7 +112,7 @@ HWTEST_F(ValueProxyTest, VBucketsRdb2Normal, TestSize.Level0) * @tc.require: * @tc.author: ht */ -HWTEST_F(ValueProxyTest, ConvertIntMapTest, TestSize.Level0) +HWTEST_F(ValueProxyServiceTest, ConvertIntMapTest, TestSize.Level0) { std::map testMap = { { "name", 1 }, { "school", 2 }, { "address", 3 } }; auto res = ValueProxy::Convert(testMap); @@ -130,7 +130,7 @@ HWTEST_F(ValueProxyTest, ConvertIntMapTest, TestSize.Level0) * @tc.require: * @tc.author: ht */ -HWTEST_F(ValueProxyTest, ConvertAssetMapGaussDB2NormalTest, TestSize.Level0) +HWTEST_F(ValueProxyServiceTest, ConvertAssetMapGaussDB2NormalTest, TestSize.Level0) { DistributedDB::Asset dbAsset0 { .name = "dbname", .uri = "dburi" }; DistributedDB::Asset dbAsset1 { .name = "dbname", .uri = "dburi" }; @@ -157,7 +157,7 @@ HWTEST_F(ValueProxyTest, ConvertAssetMapGaussDB2NormalTest, TestSize.Level0) * @tc.require: * @tc.author: ht */ -HWTEST_F(ValueProxyTest, ConvertAssetMapNormal2GaussDBTest, TestSize.Level0) +HWTEST_F(ValueProxyServiceTest, ConvertAssetMapNormal2GaussDBTest, TestSize.Level0) { using NormalAsset = OHOS::DistributedData::Asset; using NormalAssets = OHOS::DistributedData::Assets; @@ -186,7 +186,7 @@ HWTEST_F(ValueProxyTest, ConvertAssetMapNormal2GaussDBTest, TestSize.Level0) * @tc.require: * @tc.author: ht */ -HWTEST_F(ValueProxyTest, ConvertAssetMapRdb2NormalTest, TestSize.Level0) +HWTEST_F(ValueProxyServiceTest, ConvertAssetMapRdb2NormalTest, TestSize.Level0) { using RdbAsset = OHOS::NativeRdb::AssetValue; using RdbAssets = std::vector; @@ -215,7 +215,7 @@ HWTEST_F(ValueProxyTest, ConvertAssetMapRdb2NormalTest, TestSize.Level0) * @tc.require: * @tc.author: ht */ -HWTEST_F(ValueProxyTest, ConvertAssetMapNormal2RdbTest, TestSize.Level0) +HWTEST_F(ValueProxyServiceTest, ConvertAssetMapNormal2RdbTest, TestSize.Level0) { using RdbAsset = OHOS::NativeRdb::AssetValue; using RdbAssets = std::vector; @@ -244,4 +244,121 @@ HWTEST_F(ValueProxyTest, ConvertAssetMapNormal2RdbTest, TestSize.Level0) auto dataAsset = rdbAssets.begin(); ASSERT_EQ(dataAsset->name, "name"); } -} // namespace Test + +/** +* @tc.name: AssetConvertToDataStatus +* @tc.desc: Asset::ConvertToDataStatus function test. +* @tc.type: FUNC +* @tc.require: +* @tc.author: SQL +*/ +HWTEST_F(ValueProxyServiceTest, AssetConvertToDataStatus, TestSize.Level0) +{ + DistributedDB::Asset asset; + asset.status = static_cast(DistributedDB::AssetStatus::DOWNLOADING); + asset.flag = static_cast(DistributedDB::AssetOpType::DELETE); + auto result = ValueProxy::Asset::ConvertToDataStatus(asset); + EXPECT_EQ(result, DistributedData::Asset::STATUS_DELETE); + + asset.flag = static_cast(DistributedDB::AssetOpType::NO_CHANGE); + result = ValueProxy::Asset::ConvertToDataStatus(asset); + EXPECT_EQ(result, DistributedData::Asset::STATUS_DOWNLOADING); + + asset.status = static_cast(DistributedDB::AssetStatus::ABNORMAL); + result = ValueProxy::Asset::ConvertToDataStatus(asset); + EXPECT_EQ(result, DistributedData::Asset::STATUS_ABNORMAL); + + asset.status = static_cast(DistributedDB::AssetStatus::NORMAL); + asset.flag = static_cast(DistributedDB::AssetOpType::INSERT); + result = ValueProxy::Asset::ConvertToDataStatus(asset); + EXPECT_EQ(result, DistributedData::Asset::STATUS_INSERT); + + asset.flag = static_cast(DistributedDB::AssetOpType::UPDATE); + result = ValueProxy::Asset::ConvertToDataStatus(asset); + EXPECT_EQ(result, DistributedData::Asset::STATUS_UPDATE); + + asset.flag = static_cast(DistributedDB::AssetOpType::DELETE); + result = ValueProxy::Asset::ConvertToDataStatus(asset); + EXPECT_EQ(result, DistributedData::Asset::STATUS_DELETE); + + asset.flag = static_cast(DistributedDB::AssetOpType::NO_CHANGE); + result = ValueProxy::Asset::ConvertToDataStatus(asset); + EXPECT_EQ(result, DistributedData::Asset::STATUS_NORMAL); +} + +/** +* @tc.name: AssetConvertToDBStatus +* @tc.desc: Asset::ConvertToDBStatus function test. +* @tc.type: FUNC +* @tc.require: +* @tc.author: SQL +*/ +HWTEST_F(ValueProxyServiceTest, AssetConvertToDBStatus, TestSize.Level0) +{ + uint32_t status = static_cast(DistributedData::Asset::STATUS_NORMAL); + auto result = ValueProxy::Asset::ConvertToDBStatus(status); + EXPECT_EQ(result, DistributedDB::AssetStatus::NORMAL); + + status = static_cast(DistributedData::Asset::STATUS_ABNORMAL); + result = ValueProxy::Asset::ConvertToDBStatus(status); + EXPECT_EQ(result, DistributedDB::AssetStatus::ABNORMAL); + + status = static_cast(DistributedData::Asset::STATUS_INSERT); + result = ValueProxy::Asset::ConvertToDBStatus(status); + EXPECT_EQ(result, DistributedDB::AssetStatus::INSERT); + + status = static_cast(DistributedData::Asset::STATUS_UPDATE); + result = ValueProxy::Asset::ConvertToDBStatus(status); + EXPECT_EQ(result, DistributedDB::AssetStatus::UPDATE); + + status = static_cast(DistributedData::Asset::STATUS_DELETE); + result = ValueProxy::Asset::ConvertToDBStatus(status); + EXPECT_EQ(result, DistributedDB::AssetStatus::DELETE); + + status = static_cast(DistributedData::Asset::STATUS_DOWNLOADING); + result = ValueProxy::Asset::ConvertToDBStatus(status); + EXPECT_EQ(result, DistributedDB::AssetStatus::DOWNLOADING); + + status = static_cast(DistributedData::Asset::STATUS_UNKNOWN); + result = ValueProxy::Asset::ConvertToDBStatus(status); + EXPECT_EQ(result, DistributedDB::AssetStatus::NORMAL); +} + +/** +* @tc.name: TempAssetConvertToDataStatus +* @tc.desc: TempAsset::ConvertToDataStatus function test. +* @tc.type: FUNC +* @tc.require: +* @tc.author: SQL +*/ +HWTEST_F(ValueProxyServiceTest, TempAssetConvertToDataStatus, TestSize.Level0) +{ + uint32_t status = static_cast(DistributedDB::AssetStatus::NORMAL); + auto result = ValueProxy::TempAsset::ConvertToDataStatus(status); + EXPECT_EQ(result, DistributedData::Asset::STATUS_NORMAL); + + status = static_cast(DistributedDB::AssetStatus::ABNORMAL); + result = ValueProxy::TempAsset::ConvertToDataStatus(status); + EXPECT_EQ(result, DistributedData::Asset::STATUS_ABNORMAL); + + status = static_cast(DistributedDB::AssetStatus::INSERT); + result = ValueProxy::TempAsset::ConvertToDataStatus(status); + EXPECT_EQ(result, DistributedData::Asset::STATUS_INSERT); + + status = static_cast(DistributedDB::AssetStatus::UPDATE); + result = ValueProxy::TempAsset::ConvertToDataStatus(status); + EXPECT_EQ(result, DistributedData::Asset::STATUS_UPDATE); + + status = static_cast(DistributedDB::AssetStatus::DELETE); + result = ValueProxy::TempAsset::ConvertToDataStatus(status); + EXPECT_EQ(result, DistributedData::Asset::STATUS_DELETE); + + status = static_cast(DistributedDB::AssetStatus::DOWNLOADING); + result = ValueProxy::TempAsset::ConvertToDataStatus(status); + EXPECT_EQ(result, DistributedData::Asset::STATUS_DOWNLOADING); + + status = static_cast(DistributedDB::AssetStatus::DOWNLOAD_WITH_NULL); + result = ValueProxy::TempAsset::ConvertToDataStatus(status); + EXPECT_NE(result, DistributedData::Asset::STATUS_NORMAL); +} +} // namespace OHOS::Test \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/udmf/BUILD.gn b/datamgr_service/services/distributeddataservice/service/udmf/BUILD.gn index e64eb69f73cf5a5f4215dbc56d16fcbbf49a8f27..65d462e1d34b85819a1a08e5d43303e3275ec41f 100644 --- a/datamgr_service/services/distributeddataservice/service/udmf/BUILD.gn +++ b/datamgr_service/services/distributeddataservice/service/udmf/BUILD.gn @@ -19,6 +19,7 @@ config("module_public_config") { include_dirs = [ "${data_service_path}/framework/include", "${data_service_path}/adapter/include/communicator", + "${data_service_path}/adapter/include/account", "${data_service_path}/adapter/include/dfx", "${data_service_path}/service/udmf/lifecycle", "${data_service_path}/service/udmf/permission", @@ -55,6 +56,7 @@ ohos_shared_library("udmf_server") { "permission/uri_permission_manager.cpp", "preprocess/preprocess_utils.cpp", "store/runtime_store.cpp", + "store/store_account_observer.cpp", "store/store_cache.cpp", "udmf_service_impl.cpp", "udmf_service_stub.cpp", @@ -80,12 +82,12 @@ ohos_shared_library("udmf_server") { "c_utils:utils", "hilog:libhilog", "hisysevent:libhisysevent", - "image_framework:image", "ipc:ipc_core", "kv_store:distributeddb", "safwk:system_ability_fwk", "samgr:samgr_proxy", "udmf:udmf_client", + "udmf:utd_client", ] cflags_cc = [ "-fvisibility=hidden" ] subsystem_name = "distributeddatamgr" diff --git a/datamgr_service/services/distributeddataservice/service/udmf/lifecycle/lifecycle_manager.cpp b/datamgr_service/services/distributeddataservice/service/udmf/lifecycle/lifecycle_manager.cpp index f628847d943db71eb27b24794ed3b7cedc386a9d..c756012227678f60ae14f2055f142174bb5f862f 100644 --- a/datamgr_service/services/distributeddataservice/service/udmf/lifecycle/lifecycle_manager.cpp +++ b/datamgr_service/services/distributeddataservice/service/udmf/lifecycle/lifecycle_manager.cpp @@ -26,6 +26,7 @@ namespace UDMF { using CleanAfterGet = LifeCyclePolicy; std::unordered_map> LifeCycleManager::intentionPolicy_ = { { UD_INTENTION_MAP.at(UD_INTENTION_DRAG), std::make_shared() }, + { UD_INTENTION_MAP.at(UD_INTENTION_DATA_HUB), std::make_shared() } }; LifeCycleManager &LifeCycleManager::GetInstance() diff --git a/datamgr_service/services/distributeddataservice/service/udmf/permission/uri_permission_manager.cpp b/datamgr_service/services/distributeddataservice/service/udmf/permission/uri_permission_manager.cpp index c6215277df20f2ff8b9b68ee440e515ea8833965..4d5281432ce22f5092e3f407cea15bd258bb707e 100644 --- a/datamgr_service/services/distributeddataservice/service/udmf/permission/uri_permission_manager.cpp +++ b/datamgr_service/services/distributeddataservice/service/udmf/permission/uri_permission_manager.cpp @@ -31,7 +31,7 @@ UriPermissionManager &UriPermissionManager::GetInstance() } Status UriPermissionManager::GrantUriPermission( - const std::vector &allUri, uint32_t tokenId, const std::string &queryKey) + const std::vector &allUri, uint32_t tokenId, const std::string &queryKey, uint32_t &completeCount) { std::string bundleName; if (!PreProcessUtils::GetHapBundleNameByToken(tokenId, bundleName)) { @@ -57,9 +57,11 @@ Status UriPermissionManager::GrantUriPermission( status, queryKey.c_str(), instIndex); return E_NO_PERMISSION; } + completeCount = std::min(allUri.size(), index + GRANT_URI_PERMISSION_MAX_SIZE); auto time = std::chrono::steady_clock::now() + std::chrono::minutes(INTERVAL); std::for_each(uriLst.begin(), uriLst.end(), [&](const Uri &uri) { - uriTimeout_[std::make_pair(uri.ToString(), tokenId)] = time; + auto times = std::make_pair(uri.ToString(), tokenId); + uriTimeout_.Insert(times, time); }); } ZLOGI("GrantUriPermission end, url size:%{public}zu, queryKey:%{public}s.", allUri.size(), queryKey.c_str()); @@ -75,7 +77,7 @@ Status UriPermissionManager::GrantUriPermission( void UriPermissionManager::RevokeUriPermission() { auto current = std::chrono::steady_clock::now(); - uriTimeout_.EraseIf([&](auto &key, Time &time) { + uriTimeout_.EraseIf([&](const auto &key, const Time &time) { if (time > current) { return false; } diff --git a/datamgr_service/services/distributeddataservice/service/udmf/permission/uri_permission_manager.h b/datamgr_service/services/distributeddataservice/service/udmf/permission/uri_permission_manager.h index 87be83cdd3c6ac837403caa8b3f5d8aa8505c2b5..61dacb660422ff31d93c855324ef6ead79151ec2 100644 --- a/datamgr_service/services/distributeddataservice/service/udmf/permission/uri_permission_manager.h +++ b/datamgr_service/services/distributeddataservice/service/udmf/permission/uri_permission_manager.h @@ -30,7 +30,8 @@ class UriPermissionManager { public: using Time = std::chrono::steady_clock::time_point; static UriPermissionManager &GetInstance(); - Status GrantUriPermission(const std::vector &allUri, uint32_t tokenId, const std::string &queryKey); + Status GrantUriPermission(const std::vector &allUri, uint32_t tokenId, + const std::string &queryKey, uint32_t &completeCount); void SetThreadPool(std::shared_ptr executors); private: diff --git a/datamgr_service/services/distributeddataservice/service/udmf/preprocess/preprocess_utils.cpp b/datamgr_service/services/distributeddataservice/service/udmf/preprocess/preprocess_utils.cpp index 64885ff06ddc9136bf26806a34028a47fb007c59..b89ab80fbdc40469b5789f5d5145390047ce9714 100644 --- a/datamgr_service/services/distributeddataservice/service/udmf/preprocess/preprocess_utils.cpp +++ b/datamgr_service/services/distributeddataservice/service/udmf/preprocess/preprocess_utils.cpp @@ -37,7 +37,8 @@ namespace UDMF { static constexpr int ID_LEN = 32; static constexpr int MINIMUM = 48; static constexpr int MAXIMUM = 121; -const char SPECIAL = '^'; +constexpr char SPECIAL = '^'; +constexpr const char *FILE_SCHEME = "file"; static constexpr uint32_t VERIFY_URI_PERMISSION_MAX_SIZE = 500; using namespace Security::AccessToken; using namespace OHOS::AppFileService::ModuleRemoteFileShare; @@ -170,8 +171,10 @@ int32_t PreProcessUtils::SetRemoteUri(uint32_t tokenId, UnifiedData &data) continue; } Uri uri(file->GetUri()); - if (uri.GetAuthority().empty()) { - ZLOGW("Get uri authority empty."); + std::string scheme = uri.GetScheme(); + std::transform(scheme.begin(), scheme.end(), scheme.begin(), ::tolower); + if (uri.GetAuthority().empty() || scheme != FILE_SCHEME) { + ZLOGW("Get uri authority empty or uri scheme not equals to file."); continue; } uris.push_back(file->GetUri()); @@ -181,14 +184,17 @@ int32_t PreProcessUtils::SetRemoteUri(uint32_t tokenId, UnifiedData &data) if (!CheckUriAuthorization(uris, tokenId)) { ZLOGE("CheckUriAuthorization failed, bundleName:%{public}s, tokenId: %{public}d, uris size:%{public}zu.", data.GetRuntime()->createPackage.c_str(), tokenId, uris.size()); - RADAR_REPORT(BizScene::SET_DATA, SetDataStage::VERIFY_SHARE_PERMISSIONS, StageRes::FAILED, - ERROR_CODE, E_NO_PERMISSION); + RadarReporterAdapter::ReportFail(std::string(__FUNCTION__), + BizScene::SET_DATA, SetDataStage::VERIFY_SHARE_PERMISSIONS, StageRes::FAILED, E_NO_PERMISSION); return E_NO_PERMISSION; } + if (!IsNetworkingEnabled()) { + return E_OK; + } int ret = GetDfsUrisFromLocal(uris, userId, data); if (ret != E_OK) { - RADAR_REPORT(BizScene::SET_DATA, SetDataStage::GERERATE_DFS_URI, StageRes::FAILED, - ERROR_CODE, E_FS_ERROR); + RadarReporterAdapter::ReportFail(std::string(__FUNCTION__), + BizScene::SET_DATA, SetDataStage::GERERATE_DFS_URI, StageRes::FAILED, E_FS_ERROR); ZLOGE("Get remoteUri failed, ret = %{public}d, userId: %{public}d, uri size:%{public}zu.", ret, userId, uris.size()); return E_FS_ERROR; @@ -248,5 +254,16 @@ bool PreProcessUtils::GetInstIndex(uint32_t tokenId, int32_t &instIndex) instIndex = tokenInfo.instIndex; return true; } + +bool PreProcessUtils::IsNetworkingEnabled() +{ + std::vector devInfos = + DistributedData::DeviceManagerAdapter::GetInstance().GetRemoteDevices(); + ZLOGI("DM remote devices count is %{public}u.", static_cast(devInfos.size())); + if (devInfos.empty()) { + return false; + } + return true; +} } // namespace UDMF } // namespace OHOS \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/udmf/preprocess/preprocess_utils.h b/datamgr_service/services/distributeddataservice/service/udmf/preprocess/preprocess_utils.h index 70e9c6ee07775d7a20ae6e23e2ef385111e0c6fe..11ecccbb6660ee89c1965148cba8846d85aa24b3 100644 --- a/datamgr_service/services/distributeddataservice/service/udmf/preprocess/preprocess_utils.h +++ b/datamgr_service/services/distributeddataservice/service/udmf/preprocess/preprocess_utils.h @@ -38,6 +38,7 @@ public: static bool IsFileType(UDType udType); static int32_t SetRemoteUri(uint32_t tokenId, UnifiedData &data); static bool GetInstIndex(uint32_t tokenId, int32_t &instIndex); + static bool IsNetworkingEnabled(); private: static bool CheckUriAuthorization(const std::vector& uris, uint32_t tokenId); static int32_t GetDfsUrisFromLocal(const std::vector &uris, int32_t userId, UnifiedData &data); diff --git a/datamgr_service/services/distributeddataservice/service/udmf/store/runtime_store.cpp b/datamgr_service/services/distributeddataservice/service/udmf/store/runtime_store.cpp index d6dd6a0de5178555aff8d67aac0c20f7a6e981f9..e75733dfe1de5c789fa3db46fff111bc34104992 100644 --- a/datamgr_service/services/distributeddataservice/service/udmf/store/runtime_store.cpp +++ b/datamgr_service/services/distributeddataservice/service/udmf/store/runtime_store.cpp @@ -40,7 +40,7 @@ using namespace DistributedDB; using Anonymous = OHOS::DistributedData::Anonymous; using DmAdapter = OHOS::DistributedData::DeviceManagerAdapter; -const std::string TEMP_UNIFIED_DATA_FLAG = "temp_udmf_file_flag"; +constexpr const char *TEMP_UNIFIED_DATA_FLAG = "temp_udmf_file_flag"; static constexpr size_t TEMP_UDATA_RECORD_SIZE = 1; RuntimeStore::RuntimeStore(const std::string &storeId) : storeId_(storeId) @@ -277,23 +277,82 @@ Status RuntimeStore::Sync(const std::vector &devices) } } if (dbStatus != DBStatus::OK) { - RADAR_REPORT(BizScene::SYNC_DATA, SyncDataStage::SYNC_END, StageRes::FAILED, ERROR_CODE, dbStatus); + RadarReporterAdapter::ReportFail(std::string(__FUNCTION__), + BizScene::SYNC_DATA, SyncDataStage::SYNC_END, StageRes::FAILED, dbStatus); } else { - RADAR_REPORT(BizScene::SYNC_DATA, SyncDataStage::SYNC_END, StageRes::SUCCESS, - BIZ_STATE, BizState::DFX_NORMAL_END); + RadarReporterAdapter::ReportNormal(std::string(__FUNCTION__), + BizScene::SYNC_DATA, SyncDataStage::SYNC_END, StageRes::SUCCESS, BizState::DFX_NORMAL_END); } ZLOGI("sync complete, %{public}s, status:%{public}d.", Anonymous::Change(storeId_).c_str(), dbStatus); }; DBStatus status = kvStore_->Sync(syncDevices, SyncMode::SYNC_MODE_PULL_ONLY, onComplete); if (status != DBStatus::OK) { - RADAR_REPORT(BizScene::SYNC_DATA, SyncDataStage::SYNC_END, StageRes::FAILED, ERROR_CODE, status); + RadarReporterAdapter::ReportFail(std::string(__FUNCTION__), + BizScene::SYNC_DATA, SyncDataStage::SYNC_END, StageRes::FAILED, status); ZLOGE("Sync kvStore failed, status: %{public}d.", status); return E_DB_ERROR; } return E_OK; } +Status RuntimeStore::Sync(const std::vector &devices, ProcessCallback callback) +{ + UpdateTime(); + if (devices.empty()) { + ZLOGE("devices empty, no need sync."); + return E_INVALID_PARAMETERS; + } + std::vector syncDevices = DmAdapter::ToUUID(devices); + DevNameMap deviceNameMap; + for (const auto &device : devices) { + std::string deviceUuid = DmAdapter::GetInstance().ToUUID(device); + std::string deviceName = DmAdapter::GetInstance().GetDeviceInfo(device).deviceName; + deviceNameMap.emplace(deviceUuid, deviceName); + } + auto progressCallback = [this, callback, deviceNameMap](const DevSyncProcessMap &processMap) { + this->NotifySyncProcss(processMap, callback, deviceNameMap); + }; + + DistributedDB::DeviceSyncOption option; + option.devices = syncDevices; + option.isWait = false; + DBStatus status = kvStore_->Sync(option, progressCallback); + if (status != DBStatus::OK) { + RadarReporterAdapter::ReportFail(std::string(__FUNCTION__), + BizScene::SYNC_DATA, SyncDataStage::SYNC_END, StageRes::FAILED, status); + ZLOGE("Sync kvStore failed, status: %{public}d.", status); + return E_DB_ERROR; + } + return E_OK; +} + +void RuntimeStore::NotifySyncProcss(const DevSyncProcessMap &processMap, ProcessCallback callback, + const DevNameMap &deviceNameMap) +{ + AsyncProcessInfo processInfo{ASYNC_IDLE, ASYNC_IDLE, "", 0, 0, 0, 0, 0}; + for (const auto &[originDeviceId, syncProcess] : processMap) { // only one device + processInfo.srcDevName = deviceNameMap.at(originDeviceId); + processInfo.syncId = syncProcess.syncId; + processInfo.syncFinished = syncProcess.pullInfo.finishedCount; + processInfo.syncTotal = syncProcess.pullInfo.total; + if (syncProcess.process != DistributedDB::ProcessStatus::FINISHED) { + processInfo.syncStatus = ASYNC_RUNNING; + continue; + } + if (syncProcess.errCode == DBStatus::OK) { + processInfo.syncStatus = ASYNC_SUCCESS; + RadarReporterAdapter::ReportNormal(std::string(__FUNCTION__), + BizScene::SYNC_DATA, SyncDataStage::SYNC_END, StageRes::SUCCESS, BizState::DFX_NORMAL_END); + } else { + processInfo.syncStatus = ASYNC_FAILURE; + RadarReporterAdapter::ReportFail(std::string(__FUNCTION__), + BizScene::SYNC_DATA, SyncDataStage::SYNC_END, StageRes::FAILED, syncProcess.errCode); + } + } + callback(processInfo); +} + Status RuntimeStore::Clear() { UpdateTime(); @@ -415,7 +474,12 @@ bool RuntimeStore::SaveMetaData() } int foregroundUserId = 0; - DistributedKv::AccountDelegate::GetInstance()->QueryForegroundUserId(foregroundUserId); + bool ret = DistributedKv::AccountDelegate::GetInstance()->QueryForegroundUserId(foregroundUserId); + if (!ret) { + ZLOGE("QueryForegroundUserId failed."); + return false; + } + saveMeta.dataDir.append("/").append(std::to_string(foregroundUserId)); if (!DistributedData::DirectoryManager::GetInstance().CreateDirectory(saveMeta.dataDir)) { ZLOGE("Create directory error"); diff --git a/datamgr_service/services/distributeddataservice/service/udmf/store/runtime_store.h b/datamgr_service/services/distributeddataservice/service/udmf/store/runtime_store.h index 303b4b084e785ce7cab7eced67de233e30154465..e01d6e2dfd505d5ebbbf945975cb5e46c12f15b8 100644 --- a/datamgr_service/services/distributeddataservice/service/udmf/store/runtime_store.h +++ b/datamgr_service/services/distributeddataservice/service/udmf/store/runtime_store.h @@ -23,6 +23,8 @@ namespace OHOS { namespace UDMF { +using DevNameMap = std::map; +using DevSyncProcessMap = std::map; class API_EXPORT RuntimeStore final : public Store { public: explicit RuntimeStore(const std::string &storeId); @@ -34,6 +36,7 @@ public: Status Delete(const std::string &key) override; Status DeleteBatch(const std::vector &unifiedKeys) override; Status Sync(const std::vector &devices) override; + Status Sync(const std::vector &devices, ProcessCallback callback) override; Status Clear() override; Status GetBatchData(const std::string &dataPrefix, std::vector &unifiedDataSet) override; Status PutLocal(const std::string &key, const std::string &value) override; @@ -60,6 +63,8 @@ private: bool GetDetailsFromUData(UnifiedData &data, UDDetails &details); Status GetSummaryFromDetails(const UDDetails &details, Summary &summary); bool BuildMetaDataParam(DistributedData::StoreMetaData &metaData); + void NotifySyncProcss(const DevSyncProcessMap &processMap, ProcessCallback callback, + const DevNameMap &deviceNameMap); }; } // namespace UDMF } // namespace OHOS diff --git a/datamgr_service/services/distributeddataservice/service/udmf/store/store.h b/datamgr_service/services/distributeddataservice/service/udmf/store/store.h index 11a41da59878492753bd23dd41a81cb2d7f835a0..76471ef51c2c50d1a07c49b345e87d830421507f 100644 --- a/datamgr_service/services/distributeddataservice/service/udmf/store/store.h +++ b/datamgr_service/services/distributeddataservice/service/udmf/store/store.h @@ -27,6 +27,7 @@ namespace OHOS { namespace UDMF { +using ProcessCallback = std::function; class Store { public: using Time = std::chrono::steady_clock::time_point; @@ -37,6 +38,7 @@ public: virtual Status Delete(const std::string &key) = 0; virtual Status DeleteBatch(const std::vector &unifiedKeys) = 0; virtual Status Sync(const std::vector &devices) = 0; + virtual Status Sync(const std::vector &devices, ProcessCallback callback) = 0; virtual Status Clear() = 0; virtual Status GetBatchData(const std::string &dataPrefix, std::vector &unifiedDataSet) = 0; virtual Status PutLocal(const std::string &key, const std::string &value) = 0; diff --git a/datamgr_service/services/distributeddataservice/service/udmf/store/store_account_observer.cpp b/datamgr_service/services/distributeddataservice/service/udmf/store/store_account_observer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..1fa4c362410a14589eddb05d4c76a82c254631cb --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/udmf/store/store_account_observer.cpp @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#define LOG_TAG "RuntimeStoreAccountObserver" + +#include "store_account_observer.h" +#include "runtime_store.h" +#include "log_print.h" +#include "directory/directory_manager.h" +#include "account/account_delegate.h" +#include "bootstrap.h" +#include "ipc_skeleton.h" + +namespace OHOS { +namespace UDMF { +using namespace DistributedKv; +using namespace DistributedData; +void RuntimeStoreAccountObserver::OnAccountChanged(const DistributedKv::AccountEventInfo &eventInfo) +{ + ZLOGI("account event begin. status is %{public}d.", eventInfo.status); + if (eventInfo.status == DistributedKv::AccountStatus::DEVICE_ACCOUNT_DELETE) { + DistributedData::StoreMetaData metaData; + uint32_t token = IPCSkeleton::GetSelfTokenID(); + metaData.bundleName = DistributedData::Bootstrap::GetInstance().GetProcessLabel(); + metaData.appId = DistributedData::Bootstrap::GetInstance().GetProcessLabel(); + metaData.user = eventInfo.userId; + metaData.tokenId = token; + metaData.securityLevel = DistributedKv::SecurityLevel::S1; + metaData.area = DistributedKv::Area::EL1; + metaData.storeType = DistributedKv::KvStoreType::SINGLE_VERSION; + metaData.dataDir = DistributedData::DirectoryManager::GetInstance().GetStorePath(metaData); + std::string userPath = metaData.dataDir.append("/").append(eventInfo.userId); + DistributedData::DirectoryManager::GetInstance().DeleteDirectory(userPath.c_str()); + } +} + +} // namespace UDMF +} // namespace OHOS \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/udmf/store/store_account_observer.h b/datamgr_service/services/distributeddataservice/service/udmf/store/store_account_observer.h new file mode 100644 index 0000000000000000000000000000000000000000..c352fd9cd66c1d403c8e7d4f25202b6554ad777f --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/udmf/store/store_account_observer.h @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef STORE_ACCOUNT_OBSERVER_H +#define STORE_ACCOUNT_OBSERVER_H + +#include "account_delegate.h" +namespace OHOS { +namespace UDMF { +class RuntimeStoreAccountObserver : public DistributedKv::AccountDelegate::Observer { + void OnAccountChanged(const DistributedKv::AccountEventInfo &eventInfo) override; + // must specify unique name for observer + std::string Name() override + { + return "UdmfRuntimeStore"; + } + + LevelType GetLevel() override + { + return LevelType::LOW; + } +}; + +} // namespace UDMF +} // namespace OHOS + +#endif // STORE_ACCOUNT_OBSERVER_H \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/udmf/store/store_cache.cpp b/datamgr_service/services/distributeddataservice/service/udmf/store/store_cache.cpp index 9d4d9014b413b37168e190bea839377904c94bc7..f4c11ac569e6c87e217c1c297d3783ac3689f267 100644 --- a/datamgr_service/services/distributeddataservice/service/udmf/store/store_cache.cpp +++ b/datamgr_service/services/distributeddataservice/service/udmf/store/store_cache.cpp @@ -34,7 +34,11 @@ std::shared_ptr StoreCache::GetStore(std::string intention) { std::shared_ptr store; int foregroundUserId = 0; - DistributedKv::AccountDelegate::GetInstance()->QueryForegroundUserId(foregroundUserId); + bool ret = DistributedKv::AccountDelegate::GetInstance()->QueryForegroundUserId(foregroundUserId); + if (!ret) { + ZLOGE("QueryForegroundUserId failed."); + return nullptr; + } std::string key = intention; key.append(std::to_string(foregroundUserId)); diff --git a/datamgr_service/services/distributeddataservice/service/udmf/udmf_service_impl.cpp b/datamgr_service/services/distributeddataservice/service/udmf/udmf_service_impl.cpp index ec9febfc70530a3c387cc67a4b18ffab0cab251d..2a6356b765753b6743de6eb062fb814759b69cf3 100644 --- a/datamgr_service/services/distributeddataservice/service/udmf/udmf_service_impl.cpp +++ b/datamgr_service/services/distributeddataservice/service/udmf/udmf_service_impl.cpp @@ -33,6 +33,11 @@ #include "uri.h" #include "utd/custom_utd_installer.h" #include "udmf_radar_reporter.h" +#include "securec.h" +#include "unified_types.h" +#include "device_manager_adapter.h" +#include "store_account_observer.h" + namespace OHOS { namespace UDMF { @@ -41,8 +46,10 @@ using FeatureSystem = DistributedData::FeatureSystem; using UdmfBehaviourMsg = OHOS::DistributedDataDfx::UdmfBehaviourMsg; using Reporter = OHOS::DistributedDataDfx::Reporter; using namespace RadarReporter; +using namespace DistributedKv; constexpr const char *DRAG_AUTHORIZED_PROCESSES[] = {"msdp_sa", "collaboration_service"}; constexpr const char *DATA_PREFIX = "udmf://"; +constexpr const char *FILE_SCHEME = "file"; constexpr const char *PRIVILEGE_READ_AND_KEEP = "readAndKeep"; __attribute__((used)) UdmfServiceImpl::Factory UdmfServiceImpl::factory_; UdmfServiceImpl::Factory::Factory() @@ -56,6 +63,8 @@ UdmfServiceImpl::Factory::Factory() }, FeatureSystem::BIND_NOW); staticActs_ = std::make_shared(); FeatureSystem::GetInstance().RegisterStaticActs("udmf", staticActs_); + auto observer = std::make_shared(); + DistributedKv::AccountDelegate::GetInstance()->Subscribe(observer); } UdmfServiceImpl::Factory::~Factory() @@ -198,8 +207,8 @@ int32_t UdmfServiceImpl::RetrieveData(const QueryOption &query, UnifiedData &uni return E_DB_ERROR; } if (!CheckerManager::GetInstance().IsValid(runtime->privileges, info) && !IsPermissionInCache(query)) { - RADAR_REPORT(BizScene::GET_DATA, GetDataStage::VERIFY_PRIVILEGE, StageRes::FAILED, - ERROR_CODE, E_NO_PERMISSION); + RadarReporterAdapter::ReportFail(std::string(__FUNCTION__), + BizScene::GET_DATA, GetDataStage::VERIFY_PRIVILEGE, StageRes::FAILED, E_NO_PERMISSION); return E_NO_PERMISSION; } @@ -277,16 +286,21 @@ int32_t UdmfServiceImpl::ProcessUri(const QueryOption &query, UnifiedData &unifi continue; } Uri uri(file->GetUri()); - if (uri.GetAuthority().empty()) { - ZLOGW("Get authority is empty, key=%{public}s.", query.key.c_str()); + std::string scheme = uri.GetScheme(); + std::transform(scheme.begin(), scheme.end(), scheme.begin(), ::tolower); + if (uri.GetAuthority().empty() || scheme != FILE_SCHEME) { + ZLOGW("Get authority is empty or uri scheme not equals to file, key=%{public}s.", query.key.c_str()); continue; } allUri.push_back(uri); } } - if (UriPermissionManager::GetInstance().GrantUriPermission(allUri, query.tokenId, query.key) != E_OK) { - RADAR_REPORT(BizScene::GET_DATA, GetDataStage::GRANT_URI_PERMISSION, StageRes::FAILED, - ERROR_CODE, E_NO_PERMISSION); + asyncProcessInfo_.permStatus = ASYNC_RUNNING; + asyncProcessInfo_.permTotal = allUri.size(); + if (UriPermissionManager::GetInstance().GrantUriPermission(allUri, query.tokenId, query.key, + asyncProcessInfo_.permFnished) != E_OK) { + RadarReporterAdapter::ReportFail(std::string(__FUNCTION__), + BizScene::GET_DATA, GetDataStage::GRANT_URI_PERMISSION, StageRes::FAILED, E_NO_PERMISSION); ZLOGE("GrantUriPermission fail, bundleName=%{public}s, key=%{public}s.", bundleName.c_str(), query.key.c_str()); return E_NO_PERMISSION; @@ -332,23 +346,26 @@ int32_t UdmfServiceImpl::GetBatchData(const QueryOption &query, std::vectorGet(query.key, data); if (res != E_OK) { @@ -363,6 +380,10 @@ int32_t UdmfServiceImpl::UpdateData(const QueryOption &query, UnifiedData &unifi if (runtime == nullptr) { return E_DB_ERROR; } + if (runtime->tokenId != query.tokenId) { + ZLOGE("update data failed, query option tokenId not equals data's tokenId"); + return E_INVALID_PARAMETERS; + } runtime->lastModifiedTime = PreProcessUtils::GetTimestamp(); unifiedData.SetRuntime(*runtime); for (auto &record : unifiedData.GetRecords()) { @@ -396,9 +417,16 @@ int32_t UdmfServiceImpl::DeleteData(const QueryOption &query, std::vectorkey.key); + if (runtime->tokenId == query.tokenId) { + unifiedDataSet.push_back(data); + deleteKeys.push_back(runtime->key.key); + } + } + if (deleteKeys.empty()) { + ZLOGE("Delete nothing. There is no data belonging to this application"); + return E_OK; } + ZLOGI("Delete data start. size: %{public}zu.", deleteKeys.size()); if (store->DeleteBatch(deleteKeys) != E_OK) { ZLOGE("Remove data failed."); return E_DB_ERROR; @@ -484,7 +512,8 @@ int32_t UdmfServiceImpl::AddPrivilege(const QueryOption &query, Privilege &privi int32_t UdmfServiceImpl::Sync(const QueryOption &query, const std::vector &devices) { ZLOGD("start"); - RADAR_REPORT(BizScene::SYNC_DATA, SyncDataStage::SYNC_BEGIN, StageRes::IDLE, BIZ_STATE, BizState::DFX_BEGIN); + RadarReporterAdapter::ReportNormal(std::string(__FUNCTION__), + BizScene::SYNC_DATA, SyncDataStage::SYNC_BEGIN, StageRes::IDLE, BizState::DFX_BEGIN); UnifiedKey key(query.key); if (!key.IsValid()) { ZLOGE("Unified key: %{public}s is invalid.", query.key.c_str()); @@ -496,14 +525,32 @@ int32_t UdmfServiceImpl::Sync(const QueryOption &query, const std::vectorSync(devices) != E_OK) { + syncingData_ = true; + if (devices.size() > 0) { + syncingDevName_ = DistributedData::DeviceManagerAdapter::GetInstance().GetDeviceInfo(devices[0]).deviceName; + } + auto callback = [this](AsyncProcessInfo &syncInfo) { + asyncProcessInfo_.syncId = syncInfo.syncId; + asyncProcessInfo_.syncStatus = syncInfo.syncStatus; + asyncProcessInfo_.syncTotal = syncInfo.syncTotal; + asyncProcessInfo_.syncFinished = syncInfo.syncFinished; + asyncProcessInfo_.srcDevName = syncInfo.srcDevName; + if (asyncProcessInfo_.syncStatus != ASYNC_RUNNING) { + syncingData_ = false; + } + ZLOGD("store.Sync: name=%{public}s, id=%{public}u, status=%{public}u, total=%{public}u, finish=%{public}u", + syncInfo.srcDevName.c_str(), syncInfo.syncId, syncInfo.syncStatus, + syncInfo.syncTotal, syncInfo.syncFinished); + }; + if (store->Sync(devices, callback) != E_OK) { + syncingData_ = false; ZLOGE("Store sync failed, intention: %{public}s.", key.intention.c_str()); - RADAR_REPORT(BizScene::SYNC_DATA, SyncDataStage::SYNC_END, StageRes::FAILED, ERROR_CODE, E_DB_ERROR, - BIZ_STATE, BizState::DFX_ABNORMAL_END); + RadarReporterAdapter::ReportFail(std::string(__FUNCTION__), + BizScene::SYNC_DATA, SyncDataStage::SYNC_END, StageRes::FAILED, E_DB_ERROR, BizState::DFX_ABNORMAL_END); return E_DB_ERROR; } - RADAR_REPORT(BizScene::SYNC_DATA, SyncDataStage::SYNC_BEGIN, StageRes::SUCCESS); + RadarReporterAdapter::ReportNormal(std::string(__FUNCTION__), + BizScene::SYNC_DATA, SyncDataStage::SYNC_END, StageRes::SUCCESS, BizState::DFX_NORMAL_END); return E_OK; } @@ -711,5 +758,21 @@ int32_t UdmfServiceImpl::UdmfStatic::OnAppUninstall(const std::string &bundleNam } return status; } + +int32_t UdmfServiceImpl::ObtainAsynProcess(AsyncProcessInfo &processInfo) +{ + processInfo = asyncProcessInfo_; + if (syncingData_ && processInfo.syncStatus != ASYNC_RUNNING) { + processInfo.syncStatus = ASYNC_RUNNING; + processInfo.srcDevName = syncingDevName_; + } + return E_OK; +} + +int32_t UdmfServiceImpl::ClearAsynProcess() +{ + (void)memset_s(&asyncProcessInfo_, sizeof(asyncProcessInfo_), 0, sizeof(asyncProcessInfo_)); + return E_OK; +} } // namespace UDMF } // namespace OHOS \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/udmf/udmf_service_impl.h b/datamgr_service/services/distributeddataservice/service/udmf/udmf_service_impl.h index e172fe22e55c5b3bf411a765aa7f13112f6b1c69..ca9a11071ccb4267a7509b965c43c77510ab6d62 100644 --- a/datamgr_service/services/distributeddataservice/service/udmf/udmf_service_impl.h +++ b/datamgr_service/services/distributeddataservice/service/udmf/udmf_service_impl.h @@ -51,6 +51,8 @@ public: int32_t RemoveAppShareOption(const std::string &intention) override; int32_t OnInitialize() override; int32_t OnBind(const BindInfo &bindInfo) override; + int32_t ObtainAsynProcess(AsyncProcessInfo &processInfo) override; + int32_t ClearAsynProcess() override; private: int32_t SaveData(CustomOption &option, UnifiedData &unifiedData, std::string &key); @@ -81,6 +83,10 @@ private: static Factory factory_; std::map privilegeCache_; std::shared_ptr executors_; + + AsyncProcessInfo asyncProcessInfo_{}; + bool syncingData_{false}; + std::string syncingDevName_; }; } // namespace UDMF } // namespace OHOS diff --git a/datamgr_service/services/distributeddataservice/service/udmf/udmf_service_stub.cpp b/datamgr_service/services/distributeddataservice/service/udmf/udmf_service_stub.cpp index c71b3572c0854d5f9ce1929933b64240cc053c2d..2523b196844908bac1e50eee85e36f0784026c14 100644 --- a/datamgr_service/services/distributeddataservice/service/udmf/udmf_service_stub.cpp +++ b/datamgr_service/services/distributeddataservice/service/udmf/udmf_service_stub.cpp @@ -263,5 +263,29 @@ int32_t UdmfServiceStub::OnRemoveAppShareOption(MessageParcel &data, MessageParc } return E_OK; } + +int32_t UdmfServiceStub::OnObtainAsynProcess(MessageParcel &data, MessageParcel &reply) +{ + ZLOGD("start"); + AsyncProcessInfo processInfo; + int32_t status = ObtainAsynProcess(processInfo); + if (!ITypesUtil::Marshal(reply, status, processInfo)) { + ZLOGE("Marshal status or processInfo failed, status: %{public}d", status); + return E_WRITE_PARCEL_ERROR; + } + return E_OK; +} + +int32_t UdmfServiceStub::OnClearAsynProcess(MessageParcel &data, MessageParcel &reply) +{ + ZLOGD("start"); + int32_t status = ClearAsynProcess(); + if (!ITypesUtil::Marshal(reply, status)) { + ZLOGE("Marshal status failed, status: %{public}d", status); + return E_WRITE_PARCEL_ERROR; + } + return E_OK; +} + } // namespace UDMF } // namespace OHOS \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/udmf/udmf_service_stub.h b/datamgr_service/services/distributeddataservice/service/udmf/udmf_service_stub.h index 0cd2879f72d4c48927c70e0e74ebd0fbdef855f7..e3a66a588f875d877c951f4681b68f746827aca8 100644 --- a/datamgr_service/services/distributeddataservice/service/udmf/udmf_service_stub.h +++ b/datamgr_service/services/distributeddataservice/service/udmf/udmf_service_stub.h @@ -48,6 +48,8 @@ private: int32_t OnSetAppShareOption(MessageParcel &data, MessageParcel &reply); int32_t OnGetAppShareOption(MessageParcel &data, MessageParcel &reply); int32_t OnRemoveAppShareOption(MessageParcel &data, MessageParcel &reply); + int32_t OnObtainAsynProcess(MessageParcel &data, MessageParcel &reply); + int32_t OnClearAsynProcess(MessageParcel &data, MessageParcel &reply); using Handler = int32_t (UdmfServiceStub::*)(MessageParcel &data, MessageParcel &reply); static constexpr Handler HANDLERS[static_cast(UdmfServiceInterfaceCode::CODE_BUTT)] = { @@ -62,7 +64,9 @@ private: &UdmfServiceStub::OnIsRemoteData, &UdmfServiceStub::OnSetAppShareOption, &UdmfServiceStub::OnGetAppShareOption, - &UdmfServiceStub::OnRemoveAppShareOption + &UdmfServiceStub::OnRemoveAppShareOption, + &UdmfServiceStub::OnObtainAsynProcess, + &UdmfServiceStub::OnClearAsynProcess }; }; } // namespace UDMF diff --git a/datamgr_service/services/distributeddataservice/service/waterversion/water_version_manager.cpp b/datamgr_service/services/distributeddataservice/service/waterversion/water_version_manager.cpp index 3a41a383dda087bdadd1b07b8380508a5830414f..4101a168ffeadef294eaf7bc4ae3a885fc9f0550 100644 --- a/datamgr_service/services/distributeddataservice/service/waterversion/water_version_manager.cpp +++ b/datamgr_service/services/distributeddataservice/service/waterversion/water_version_manager.cpp @@ -17,14 +17,14 @@ #include "checker/checker_manager.h" #include "cloud/cloud_sync_finished_event.h" -#include "device_matrix.h" -#include "store/auto_cache.h" #include "device_manager_adapter.h" +#include "device_matrix.h" #include "eventcenter/event_center.h" #include "log_print.h" #include "metadata/matrix_meta_data.h" #include "metadata/meta_data_manager.h" #include "metadata/store_meta_data.h" +#include "store/auto_cache.h" #include "utils/anonymous.h" #include "utils/constant.h" @@ -39,7 +39,7 @@ WaterVersionManager &WaterVersionManager::GetInstance() } WaterVersionManager::WaterVersionManager() : waterVersions_(BUTT) { - for (int i = 0; i < BUTT; ++i) { + for (int i = 0; i < static_cast(BUTT); ++i) { waterVersions_[i].SetType(static_cast(i)); } } @@ -58,7 +58,7 @@ void WaterVersionManager::Init() } MetaDataManager::GetInstance().LoadMeta(WaterVersionMetaData::GetPrefix(), metas, true); for (auto &meta : metas) { - if (meta.type < 0 || meta.type > BUTT) { + if (meta.type < BEGIN || meta.type > BUTT) { ZLOGW("error meta:%{public}s", meta.ToAnonymousString().c_str()); continue; } @@ -90,7 +90,7 @@ std::string WaterVersionManager::GenerateWaterVersion(const std::string &bundleN if (CheckerManager::GetInstance().IsStatic(info)) { type = STATIC; } - if (type < 0 || type >= BUTT || bundleName.empty() || storeName.empty()) { + if (type < BEGIN || type >= BUTT || bundleName.empty() || storeName.empty()) { ZLOGE("invalid args. bundleName:%{public}s, storeName:%{public}s, type:%{public}d", bundleName.c_str(), Anonymous::Change(storeName).c_str(), type); return ""; @@ -111,7 +111,7 @@ std::string WaterVersionManager::GetWaterVersion(const std::string &bundleName, if (CheckerManager::GetInstance().IsStatic(info)) { type = STATIC; } - if (type < 0 || type >= BUTT || bundleName.empty() || storeName.empty()) { + if (type < BEGIN || type >= BUTT || bundleName.empty() || storeName.empty()) { ZLOGE("invalid args. bundleName:%{public}s, storeName:%{public}s, type:%{public}d", bundleName.c_str(), Anonymous::Change(storeName).c_str(), type); return ""; @@ -137,7 +137,7 @@ std::string WaterVersionManager::GetWaterVersion(const std::string &bundleName, std::pair WaterVersionManager::GetVersion(const std::string &deviceId, WaterVersionManager::Type type) { - if (type < 0 || type >= BUTT || deviceId.empty()) { + if (type < BEGIN || type >= BUTT || deviceId.empty()) { ZLOGE("invalid args, type:%{public}d", type); return { false, 0 }; } @@ -147,7 +147,7 @@ std::pair WaterVersionManager::GetVersion(const std::string &dev std::string WaterVersionManager::GetWaterVersion(const std::string &deviceId, WaterVersionManager::Type type) { - if (type < 0 || type >= BUTT || deviceId.empty()) { + if (type < BEGIN || type >= BUTT || deviceId.empty()) { ZLOGE("invalid args, type:%{public}d", type); return { false, 0 }; } @@ -181,7 +181,7 @@ bool WaterVersionManager::DelWaterVersion(const std::string &deviceId) bool WaterVersionManager::InitMeta(WaterVersionMetaData &metaData) { - metaData.waterVersion = 0; + metaData.waterVersion = WaterVersionMetaData::DEFAULT_VERSION; std::string uuid = DMAdapter::GetInstance().GetLocalDevice().uuid; for (size_t i = 0; i < metaData.keys.size(); ++i) { auto key = metaData.keys[i]; @@ -326,7 +326,7 @@ bool WaterVersionMetaData::Unmarshal(const Serializable::json &node) GetValue(node, GET_NAME(waterVersion), waterVersion); int32_t tmp = -1; GetValue(node, GET_NAME(type), tmp); - if (tmp < 0 || tmp >= BUTT) { + if (tmp < BEGIN || tmp >= BUTT) { return false; } type = static_cast(tmp); @@ -360,7 +360,7 @@ std::string WaterVersionMetaData::GetPrefix() bool WaterVersionMetaData::IsValid() { - if (type < 0 || type >= BUTT) { + if (type < BEGIN || type >= BUTT) { return false; } if (keys.size() != infos.size()) { diff --git a/datamgr_service/services/distributeddataservice/service/waterversion/water_version_manager.h b/datamgr_service/services/distributeddataservice/service/waterversion/water_version_manager.h index bdf83e9fdc99973ca65607c9fa51c57a3b36907d..7e77513fa9978e529372d4a589fa32a880b7a201 100644 --- a/datamgr_service/services/distributeddataservice/service/waterversion/water_version_manager.h +++ b/datamgr_service/services/distributeddataservice/service/waterversion/water_version_manager.h @@ -25,7 +25,8 @@ namespace DistributedData { class WaterVersionManager { public: enum Type { - DYNAMIC, + BEGIN, + DYNAMIC = BEGIN, STATIC, BUTT }; diff --git a/googletest/BUILD.bazel b/googletest/BUILD.bazel index 965c518d7a7c4e2a4f642706e8fc57a9542ca14f..ac62251e10172614d93b385777e52defc187cac4 100644 --- a/googletest/BUILD.bazel +++ b/googletest/BUILD.bazel @@ -30,19 +30,32 @@ # # Bazel Build for Google C++ Testing Framework(Google Test) -load("@rules_cc//cc:defs.bzl", "cc_library", "cc_test") - package(default_visibility = ["//visibility:public"]) licenses(["notice"]) exports_files(["LICENSE"]) +config_setting( + name = "qnx", + constraint_values = ["@platforms//os:qnx"], +) + config_setting( name = "windows", constraint_values = ["@platforms//os:windows"], ) +config_setting( + name = "freebsd", + constraint_values = ["@platforms//os:freebsd"], +) + +config_setting( + name = "openbsd", + constraint_values = ["@platforms//os:openbsd"], +) + config_setting( name = "msvc_compiler", flag_values = { @@ -86,6 +99,7 @@ cc_library( "googlemock/include/gmock/*.h", ]), copts = select({ + ":qnx": [], ":windows": [], "//conditions:default": ["-pthread"], }), @@ -104,7 +118,16 @@ cc_library( "googletest/include", ], linkopts = select({ + ":qnx": ["-lregex"], ":windows": [], + ":freebsd": [ + "-lm", + "-pthread", + ], + ":openbsd": [ + "-lm", + "-pthread", + ], "//conditions:default": ["-pthread"], }), deps = select({ @@ -112,10 +135,15 @@ cc_library( "@com_google_absl//absl/debugging:failure_signal_handler", "@com_google_absl//absl/debugging:stacktrace", "@com_google_absl//absl/debugging:symbolize", + "@com_google_absl//absl/flags:flag", + "@com_google_absl//absl/flags:parse", + "@com_google_absl//absl/flags:reflection", + "@com_google_absl//absl/flags:usage", "@com_google_absl//absl/strings", "@com_google_absl//absl/types:any", "@com_google_absl//absl/types:optional", "@com_google_absl//absl/types:variant", + "@com_googlesource_code_re2//:re2", ], "//conditions:default": [], }), diff --git a/googletest/BUILD.gn b/googletest/BUILD.gn index f890da313f08df81408399e7c6388c94a640c8f6..ec835ee7af80c60e564adb4051b7529280e96ab4 100644 --- a/googletest/BUILD.gn +++ b/googletest/BUILD.gn @@ -7,68 +7,100 @@ config("gtest_private_config") { include_dirs = [ "googletest" ] } +config("gtest_private_config_rtti") { + visibility = [ ":*" ] + include_dirs = [ "googletest" ] + cflags = [ "-frtti" ] + cflags_objcc = [ "-frtti" ] + cflags_cc = [ "-frtti" ] +} + config("gtest_config") { include_dirs = [ "googletest/include" ] + cflags_cc = [ + "-std=c++17", + "-Wno-float-equal", + "-Wno-sign-compare", + "-Wno-reorder-init-list", + ] if (is_mingw) { - cflags_cc = [ + cflags_cc += [ "-Wno-unused-const-variable", "-Wno-unused-private-field", ] } } +sources_files = [ + "googletest/include/gtest/gtest-death-test.h", + "googletest/include/gtest/gtest-matchers.h", + "googletest/include/gtest/gtest-message.h", + "googletest/include/gtest/gtest-param-test.h", + "googletest/include/gtest/gtest-printers.h", + "googletest/include/gtest/gtest-test-part.h", + "googletest/include/gtest/gtest-typed-test.h", + "googletest/include/gtest/gtest_pred_impl.h", + "googletest/include/gtest/gtest_prod.h", + "googletest/include/gtest/hwext/gtest-ext.h", + "googletest/include/gtest/hwext/gtest-filter.h", + "googletest/include/gtest/hwext/gtest-multithread.h", + "googletest/include/gtest/hwext/gtest-tag.h", + "googletest/include/gtest/hwext/utils.h", + "googletest/include/gtest/internal/custom/gtest-port.h", + "googletest/include/gtest/internal/custom/gtest-printers.h", + "googletest/include/gtest/internal/custom/gtest.h", + "googletest/include/gtest/internal/gtest-death-test-internal.h", + "googletest/include/gtest/internal/gtest-filepath.h", + "googletest/include/gtest/internal/gtest-internal.h", + "googletest/include/gtest/internal/gtest-param-util.h", + "googletest/include/gtest/internal/gtest-port-arch.h", + "googletest/include/gtest/internal/gtest-port.h", + "googletest/include/gtest/internal/gtest-string.h", + "googletest/include/gtest/internal/gtest-type-util.h", + "googletest/src/gtest-all.cc", + "googletest/src/gtest-assertion-result.cc", + "googletest/src/gtest-death-test.cc", + "googletest/src/gtest-filepath.cc", + "googletest/src/gtest-internal-inl.h", + "googletest/src/gtest-matchers.cc", + "googletest/src/gtest-port.cc", + "googletest/src/gtest-printers.cc", + "googletest/src/gtest-test-part.cc", + "googletest/src/gtest-typed-test.cc", + "googletest/src/gtest.cc", + "googletest/src/hwext/gtest-ext.cc", + "googletest/src/hwext/gtest-filter.cc", + "googletest/src/hwext/gtest-multithread.cpp", + "googletest/src/hwext/gtest-tag.cc", + "googletest/src/hwext/gtest-utils.cc", +] + static_library("gtest") { testonly = true public = [ "googletest/include/gtest/gtest-spi.h", "googletest/include/gtest/gtest.h", ] - sources = [ - "googletest/include/gtest/gtest-death-test.h", - "googletest/include/gtest/gtest-matchers.h", - "googletest/include/gtest/gtest-message.h", - "googletest/include/gtest/gtest-param-test.h", - "googletest/include/gtest/gtest-printers.h", - "googletest/include/gtest/gtest-test-part.h", - "googletest/include/gtest/gtest-typed-test.h", - "googletest/include/gtest/gtest_pred_impl.h", - "googletest/include/gtest/gtest_prod.h", - "googletest/include/gtest/hwext/gtest-ext.h", - "googletest/include/gtest/hwext/gtest-filter.h", - "googletest/include/gtest/hwext/gtest-tag.h", - "googletest/include/gtest/hwext/utils.h", - "googletest/include/gtest/internal/custom/gtest-port.h", - "googletest/include/gtest/internal/custom/gtest-printers.h", - "googletest/include/gtest/internal/custom/gtest.h", - "googletest/include/gtest/internal/gtest-death-test-internal.h", - "googletest/include/gtest/internal/gtest-filepath.h", - "googletest/include/gtest/internal/gtest-internal.h", - "googletest/include/gtest/internal/gtest-param-util.h", - "googletest/include/gtest/internal/gtest-port-arch.h", - "googletest/include/gtest/internal/gtest-port.h", - "googletest/include/gtest/internal/gtest-string.h", - "googletest/include/gtest/internal/gtest-type-util.h", - "googletest/src/gtest-all.cc", - "googletest/src/gtest-death-test.cc", - "googletest/src/gtest-filepath.cc", - "googletest/src/gtest-internal-inl.h", - "googletest/src/gtest-matchers.cc", - "googletest/src/gtest-port.cc", - "googletest/src/gtest-printers.cc", - "googletest/src/gtest-test-part.cc", - "googletest/src/gtest-typed-test.cc", - "googletest/src/gtest.cc", - "googletest/src/hwext/gtest-ext.cc", - "googletest/src/hwext/gtest-filter.cc", - "googletest/src/hwext/gtest-tag.cc", - "googletest/src/hwext/gtest-utils.cc", - ] + sources = sources_files sources -= [ "googletest/src/gtest-all.cc" ] public_configs = [ ":gtest_config" ] configs += [ ":gtest_private_config" ] configs -= [ "//build/config/coverage:default_coverage" ] } +static_library("gtest_rtti") { + testonly = true + public = [ + "googletest/include/gtest/gtest-spi.h", + "googletest/include/gtest/gtest.h", + ] + sources = sources_files + sources -= [ "googletest/src/gtest-all.cc" ] + public_configs = [ ":gtest_config" ] + configs += [ ":gtest_private_config_rtti" ] + configs -= [ "//build/config/coverage:default_coverage" ] +} + static_library("gtest_main") { testonly = true sources = [ "googletest/src/gtest_main.cc" ] @@ -81,6 +113,14 @@ config("gmock_private_config") { include_dirs = [ "googlemock" ] } +config("gmock_private_config_rtti") { + visibility = [ ":*" ] + include_dirs = [ "googlemock/include" ] + cflags = [ "-frtti" ] + cflags_objcc = [ "-frtti" ] + cflags_cc = [ "-frtti" ] +} + config("gmock_config") { include_dirs = [ "googlemock/include" ] @@ -94,31 +134,33 @@ config("gmock_config") { ] } +gmock_sources_files = [ + "googlemock/include/gmock/gmock-actions.h", + "googlemock/include/gmock/gmock-cardinalities.h", + "googlemock/include/gmock/gmock-function-mocker.h", + "googlemock/include/gmock/gmock-matchers.h", + "googlemock/include/gmock/gmock-more-actions.h", + "googlemock/include/gmock/gmock-more-matchers.h", + "googlemock/include/gmock/gmock-nice-strict.h", + "googlemock/include/gmock/gmock-spec-builders.h", + "googlemock/include/gmock/internal/custom/gmock-generated-actions.h", + "googlemock/include/gmock/internal/custom/gmock-matchers.h", + "googlemock/include/gmock/internal/custom/gmock-port.h", + "googlemock/include/gmock/internal/gmock-internal-utils.h", + "googlemock/include/gmock/internal/gmock-port.h", + "googlemock/include/gmock/internal/gmock-pp.h", + "googlemock/src/gmock-all.cc", + "googlemock/src/gmock-cardinalities.cc", + "googlemock/src/gmock-internal-utils.cc", + "googlemock/src/gmock-matchers.cc", + "googlemock/src/gmock-spec-builders.cc", + "googlemock/src/gmock.cc", +] + static_library("gmock") { testonly = true public = [ "googlemock/include/gmock/gmock.h" ] - sources = [ - "googlemock/include/gmock/gmock-actions.h", - "googlemock/include/gmock/gmock-cardinalities.h", - "googlemock/include/gmock/gmock-function-mocker.h", - "googlemock/include/gmock/gmock-matchers.h", - "googlemock/include/gmock/gmock-more-actions.h", - "googlemock/include/gmock/gmock-more-matchers.h", - "googlemock/include/gmock/gmock-nice-strict.h", - "googlemock/include/gmock/gmock-spec-builders.h", - "googlemock/include/gmock/internal/custom/gmock-generated-actions.h", - "googlemock/include/gmock/internal/custom/gmock-matchers.h", - "googlemock/include/gmock/internal/custom/gmock-port.h", - "googlemock/include/gmock/internal/gmock-internal-utils.h", - "googlemock/include/gmock/internal/gmock-port.h", - "googlemock/include/gmock/internal/gmock-pp.h", - "googlemock/src/gmock-all.cc", - "googlemock/src/gmock-cardinalities.cc", - "googlemock/src/gmock-internal-utils.cc", - "googlemock/src/gmock-matchers.cc", - "googlemock/src/gmock-spec-builders.cc", - "googlemock/src/gmock.cc", - ] + sources = gmock_sources_files sources -= [ "googlemock/src/gmock-all.cc" ] public_configs = [ ":gmock_config" ] configs += [ ":gmock_private_config" ] @@ -126,6 +168,17 @@ static_library("gmock") { deps = [ ":gtest" ] } +static_library("gmock_rtti") { + testonly = true + public = [ "googlemock/include/gmock/gmock.h" ] + sources = gmock_sources_files + sources -= [ "googlemock/src/gmock-all.cc" ] + public_configs = [ ":gmock_config" ] + configs += [ ":gmock_private_config_rtti" ] + configs -= [ "//build/config/coverage:default_coverage" ] + deps = [ ":gtest_rtti" ] +} + static_library("gmock_main") { testonly = true sources = [ "googlemock/src/gmock_main.cc" ] diff --git a/googletest/CMakeLists.txt b/googletest/CMakeLists.txt index ea81ab1292d0b9099ac389b6c71885b0e6a1d034..6af414371f7a1c038d5834dc8707a6ac34bed7b5 100644 --- a/googletest/CMakeLists.txt +++ b/googletest/CMakeLists.txt @@ -1,19 +1,25 @@ # Note: CMake support is community-based. The maintainers do not use CMake # internally. -cmake_minimum_required(VERSION 2.8.12) +cmake_minimum_required(VERSION 3.5) if (POLICY CMP0048) cmake_policy(SET CMP0048 NEW) endif (POLICY CMP0048) +if (POLICY CMP0069) + cmake_policy(SET CMP0069 NEW) +endif (POLICY CMP0069) + +if (POLICY CMP0077) + cmake_policy(SET CMP0077 NEW) +endif (POLICY CMP0077) + project(googletest-distribution) -set(GOOGLETEST_VERSION 1.11.0) +set(GOOGLETEST_VERSION 1.13.0) -if (CMAKE_VERSION VERSION_GREATER "3.0.2") - if(NOT CYGWIN AND NOT MSYS AND NOT ${CMAKE_SYSTEM_NAME} STREQUAL QNX) - set(CMAKE_CXX_EXTENSIONS OFF) - endif() +if(NOT CYGWIN AND NOT MSYS AND NOT ${CMAKE_SYSTEM_NAME} STREQUAL QNX) + set(CMAKE_CXX_EXTENSIONS OFF) endif() enable_testing() @@ -24,6 +30,7 @@ include(GNUInstallDirs) #Note that googlemock target already builds googletest option(BUILD_GMOCK "Builds the googlemock subproject" ON) option(INSTALL_GTEST "Enable installation of googletest. (Projects embedding googletest may want to turn this OFF.)" ON) +option(GTEST_HAS_ABSL "Use Abseil and RE2. Requires Abseil and RE2 to be separately added to the build." OFF) if(BUILD_GMOCK) add_subdirectory( googlemock ) diff --git a/googletest/CONTRIBUTING.md b/googletest/CONTRIBUTING.md index da45e4450ce7f155f809f058b6f8a9d05d7642ce..de14c8159b17e367dd0098c7202e13439a06ff89 100644 --- a/googletest/CONTRIBUTING.md +++ b/googletest/CONTRIBUTING.md @@ -21,8 +21,8 @@ accept your pull requests. ## Are you a Googler? -If you are a Googler, please make an attempt to submit an internal change rather -than a GitHub Pull Request. If you are not able to submit an internal change a +If you are a Googler, please make an attempt to submit an internal contribution +rather than a GitHub Pull Request. If you are not able to submit internally, a PR is acceptable as an alternative. ## Contributing A Patch @@ -36,7 +36,8 @@ PR is acceptable as an alternative. This ensures that work isn't being duplicated and communicating your plan early also generally leads to better patches. 4. If your proposed change is accepted, and you haven't already done so, sign a - Contributor License Agreement (see details above). + Contributor License Agreement + ([see details above](#contributor-license-agreements)). 5. Fork the desired repo, develop and test your code changes. 6. Ensure that your code adheres to the existing style in the sample to which you are contributing. @@ -79,8 +80,8 @@ fairly rigid coding style, as defined by the [google-styleguide](https://github.com/google/styleguide) project. All patches will be expected to conform to the style outlined [here](https://google.github.io/styleguide/cppguide.html). Use -[.clang-format](https://github.com/google/googletest/blob/master/.clang-format) -to check your formatting. +[.clang-format](https://github.com/google/googletest/blob/main/.clang-format) to +check your formatting. ## Requirements for Contributors diff --git a/googletest/CONTRIBUTORS b/googletest/CONTRIBUTORS index 76db0b40ffb3fe70d5f321d78eade1d1e226fc43..77397a5b53fea5352f8af38bdb1c4a0ce0e30d66 100644 --- a/googletest/CONTRIBUTORS +++ b/googletest/CONTRIBUTORS @@ -34,6 +34,7 @@ Manuel Klimek Mario Tanev Mark Paskin Markus Heule +Martijn Vels Matthew Simmons Mika Raento Mike Bland @@ -55,6 +56,7 @@ Russ Rufer Sean Mcafee Sigurður Ásgeirsson Sverre Sundsdal +Szymon Sobik Takeshi Yoshino Tracy Bialik Vadim Berman diff --git a/googletest/OAT.xml b/googletest/OAT.xml index 79905db41139117bf9c6e76cc3557747e7b42163..c876d65fb8e91a0de3a3a20afe3890f97fc778ef 100644 --- a/googletest/OAT.xml +++ b/googletest/OAT.xml @@ -64,12 +64,9 @@ Note:If the text contains special characters, please escape them according to th - - - - - - + + + \ No newline at end of file diff --git a/googletest/README.OpenSource b/googletest/README.OpenSource index b7b7997fbd79b7af2c19d8428b4e8999613cc9cc..625a7c0218d489558691447758b7d7bdda8abc5d 100644 --- a/googletest/README.OpenSource +++ b/googletest/README.OpenSource @@ -3,9 +3,9 @@ "Name": "googletest", "License": "BSD 3-Clause License", "License File": "LICENSE", - "Version Number": "1.11.0", - "Owner": "zhangchunbao@huawei.com", - "Upstream URL": "https://github.com/google/googletest/releases/tag/release-1.11.0", - "Description": "The 1.11.x is the last release supporting pre-C++11 compilers. The 1.11.x will not accept any requests for any new features and any bugfix requests will only be accepted if proven critical" + "Version Number": "1.13.0", + "Owner": "", + "Upstream URL": "https://github.com/google/googletest/archive/refs/tags/v1.13.0.tar.gz", + "Description": "The 1.13.x only supports compilers above C++14. The 1.13.x will not accept any requests for any new features and any bugfix requests will only be accepted if proven critical" } -] +] \ No newline at end of file diff --git a/googletest/README.md b/googletest/README.md index 7d872a57ed456934329d0872d42fb5e6c30def7e..cd89abb2d2daea7d0feef40f2496106a9bfd31f4 100644 --- a/googletest/README.md +++ b/googletest/README.md @@ -6,7 +6,8 @@ GoogleTest now follows the [Abseil Live at Head philosophy](https://abseil.io/about/philosophy#upgrade-support). -We recommend using the latest commit in the `master` branch in your projects. +We recommend +[updating to the latest commit in the `main` branch as often as possible](https://github.com/abseil/abseil-cpp/blob/master/FAQ.md#what-is-live-at-head-and-how-do-i-do-it). #### Documentation Updates @@ -14,11 +15,14 @@ Our documentation is now live on GitHub Pages at https://google.github.io/googletest/. We recommend browsing the documentation on GitHub Pages rather than directly in the repository. -#### Release 1.10.x +#### Release 1.12.1 -[Release 1.10.x](https://github.com/google/googletest/releases/tag/release-1.10.0) +[Release 1.12.1](https://github.com/google/googletest/releases/tag/release-1.12.1) is now available. +The 1.12.x branch will be the last to support C++11. Future releases will +require at least C++14. + #### Coming Soon * We are planning to take a dependency on @@ -55,39 +59,12 @@ More information about building GoogleTest can be found at ## Supported Platforms -GoogleTest requires a codebase and compiler compliant with the C++11 standard or -newer. - -The GoogleTest code is officially supported on the following platforms. -Operating systems or tools not listed below are community-supported. For -community-supported platforms, patches that do not complicate the code may be -considered. - -If you notice any problems on your platform, please file an issue on the -[GoogleTest GitHub Issue Tracker](https://github.com/google/googletest/issues). -Pull requests containing fixes are welcome! - -### Operating Systems - -* Linux -* macOS -* Windows - -### Compilers - -* gcc 5.0+ -* clang 5.0+ -* MSVC 2015+ - -**macOS users:** Xcode 9.3+ provides clang 5.0+. - -### Build Systems - -* [Bazel](https://bazel.build/) -* [CMake](https://cmake.org/) - -**Note:** Bazel is the build system used by the team internally and in tests. -CMake is supported on a best-effort basis and by the community. +GoogleTest follows Google's +[Foundational C++ Support Policy](https://opensource.google/documentation/policies/cplusplus-support). +See +[this table](https://github.com/google/oss-policies-info/blob/main/foundational-cxx-support-matrix.md) +for a list of currently supported versions compilers, platforms, and build +tools. ## Who Is Using GoogleTest? @@ -109,8 +86,8 @@ Windows and Linux platforms. [GoogleTest UI](https://github.com/ospector/gtest-gbar) is a test runner that runs your test binary, allows you to track its progress via a progress bar, and -displays a list of test failures. Clicking on one shows failure text. Google -Test UI is written in C#. +displays a list of test failures. Clicking on one shows failure text. GoogleTest +UI is written in C#. [GTest TAP Listener](https://github.com/kinow/gtest-tap-listener) is an event listener for GoogleTest that implements the @@ -121,11 +98,11 @@ result output. If your test runner understands TAP, you may find it useful. runs tests from your binary in parallel to provide significant speed-up. [GoogleTest Adapter](https://marketplace.visualstudio.com/items?itemName=DavidSchuldenfrei.gtest-adapter) -is a VS Code extension allowing to view GoogleTest in a tree view, and run/debug +is a VS Code extension allowing to view GoogleTest in a tree view and run/debug your tests. [C++ TestMate](https://github.com/matepek/vscode-catch2-test-adapter) is a VS -Code extension allowing to view GoogleTest in a tree view, and run/debug your +Code extension allowing to view GoogleTest in a tree view and run/debug your tests. [Cornichon](https://pypi.org/project/cornichon/) is a small Gherkin DSL parser @@ -134,7 +111,7 @@ that generates stub code for GoogleTest. ## Contributing Changes Please read -[`CONTRIBUTING.md`](https://github.com/google/googletest/blob/master/CONTRIBUTING.md) +[`CONTRIBUTING.md`](https://github.com/google/googletest/blob/main/CONTRIBUTING.md) for details on how to contribute to this project. Happy testing! diff --git a/googletest/WORKSPACE b/googletest/WORKSPACE index 614f55778e6e1f33235300fe60cbe167c2c34845..0f10a6a9a8691036391e8acd814e500a33f5a7bf 100644 --- a/googletest/WORKSPACE +++ b/googletest/WORKSPACE @@ -3,22 +3,38 @@ workspace(name = "com_google_googletest") load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive") http_archive( - name = "com_google_absl", - urls = ["https://github.com/abseil/abseil-cpp/archive/7971fb358ae376e016d2d4fc9327aad95659b25e.zip"], # 2021-05-20T02:59:16Z - strip_prefix = "abseil-cpp-7971fb358ae376e016d2d4fc9327aad95659b25e", - sha256 = "aeba534f7307e36fe084b452299e49b97420667a8d28102cf9a0daeed340b859", + name = "com_google_absl", # 2023-01-10T21:08:25Z + sha256 = "f9a4e749f42c386a32a90fddf0e2913ed408d10c42f7f33ccf4c59ac4f0d1d05", + strip_prefix = "abseil-cpp-52835439ca90d86b27bf8cd1708296e95604d724", + urls = ["https://github.com/abseil/abseil-cpp/archive/52835439ca90d86b27bf8cd1708296e95604d724.zip"], ) +# Note this must use a commit from the `abseil` branch of the RE2 project. +# https://github.com/google/re2/tree/abseil http_archive( - name = "rules_cc", - urls = ["https://github.com/bazelbuild/rules_cc/archive/68cb652a71e7e7e2858c50593e5a9e3b94e5b9a9.zip"], # 2021-05-14T14:51:14Z - strip_prefix = "rules_cc-68cb652a71e7e7e2858c50593e5a9e3b94e5b9a9", - sha256 = "1e19e9a3bc3d4ee91d7fcad00653485ee6c798efbbf9588d40b34cbfbded143d", + name = "com_googlesource_code_re2", # 2022-12-21T14:29:10Z + sha256 = "b9ce3a51beebb38534d11d40f8928d40509b9e18a735f6a4a97ad3d014c87cb5", + strip_prefix = "re2-d0b1f8f2ecc2ea74956c7608b6f915175314ff0e", + urls = ["https://github.com/google/re2/archive/d0b1f8f2ecc2ea74956c7608b6f915175314ff0e.zip"], ) http_archive( - name = "rules_python", - urls = ["https://github.com/bazelbuild/rules_python/archive/ed6cc8f2c3692a6a7f013ff8bc185ba77eb9b4d2.zip"], # 2021-05-17T00:24:16Z - strip_prefix = "rules_python-ed6cc8f2c3692a6a7f013ff8bc185ba77eb9b4d2", - sha256 = "98b3c592faea9636ac8444bfd9de7f3fb4c60590932d6e6ac5946e3f8dbd5ff6", + name = "rules_python", # 2023-01-10T22:00:51Z + sha256 = "5de54486a60ad8948dabe49605bb1c08053e04001a431ab3e96745b4d97a4419", + strip_prefix = "rules_python-70cce26432187a60b4e950118791385e6fb3c26f", + urls = ["https://github.com/bazelbuild/rules_python/archive/70cce26432187a60b4e950118791385e6fb3c26f.zip"], +) + +http_archive( + name = "bazel_skylib", # 2022-11-16T18:29:32Z + sha256 = "a22290c26d29d3ecca286466f7f295ac6cbe32c0a9da3a91176a90e0725e3649", + strip_prefix = "bazel-skylib-5bfcb1a684550626ce138fe0fe8f5f702b3764c3", + urls = ["https://github.com/bazelbuild/bazel-skylib/archive/5bfcb1a684550626ce138fe0fe8f5f702b3764c3.zip"], +) + +http_archive( + name = "platforms", # 2022-11-09T19:18:22Z + sha256 = "b4a3b45dc4202e2b3e34e3bc49d2b5b37295fc23ea58d88fb9e01f3642ad9b55", + strip_prefix = "platforms-3fbc687756043fb58a407c2ea8c944bc2fe1d922", + urls = ["https://github.com/bazelbuild/platforms/archive/3fbc687756043fb58a407c2ea8c944bc2fe1d922.zip"], ) diff --git a/googletest/bundle.json b/googletest/bundle.json index 002bd1d6bb09afb58f073424096e63f5464793d5..a82e37e2ff65da76441fec08af35f0274a69c059 100644 --- a/googletest/bundle.json +++ b/googletest/bundle.json @@ -10,11 +10,14 @@ "dirs": {}, "scripts": {}, "component": { - "name": "thirdparty_googletest", - "subsystem": "", + "name": "googletest", + "subsystem": "thirdparty", "syscap": [], "features": [], - "adapted_system_type": [], + "adapted_system_type": [ + "small", + "standard" + ], "rom": "", "ram": "", "deps": { @@ -23,8 +26,24 @@ }, "build": { "sub_component": [], - "inner_kits": [], + "inner_kits": [ + { + "name": "//third_party/googletest:gtest" + }, + { + "name": "//third_party/googletest:gmock" + }, + { + "name": "//third_party/googletest:gtest_main" + }, + { + "name": "//third_party/googletest:gmock_main" + }, + { + "name": "//third_party/googletest:gtest_rtti" + } + ], "test": [] } } -} \ No newline at end of file +} diff --git a/googletest/ci/linux-presubmit.sh b/googletest/ci/linux-presubmit.sh index 6bea1cde26aff516d6b7a3780fcdecacb5376388..4eb5bbe4a1dac8923fc0aa2f2d49cc38f258ec4c 100644 --- a/googletest/ci/linux-presubmit.sh +++ b/googletest/ci/linux-presubmit.sh @@ -31,15 +31,15 @@ set -euox pipefail -readonly LINUX_LATEST_CONTAINER="gcr.io/google.com/absl-177019/linux_hybrid-latest:20210525" -readonly LINUX_GCC_FLOOR_CONTAINER="gcr.io/google.com/absl-177019/linux_gcc-floor:20201015" +readonly LINUX_LATEST_CONTAINER="gcr.io/google.com/absl-177019/linux_hybrid-latest:20220217" +readonly LINUX_GCC_FLOOR_CONTAINER="gcr.io/google.com/absl-177019/linux_gcc-floor:20220621" if [[ -z ${GTEST_ROOT:-} ]]; then GTEST_ROOT="$(realpath $(dirname ${0})/..)" fi if [[ -z ${STD:-} ]]; then - STD="c++11 c++14 c++17 c++20" + STD="c++14 c++17 c++20" fi # Test the CMake build @@ -55,7 +55,7 @@ for cc in /usr/local/bin/gcc /opt/llvm/clang/bin/clang; do ${LINUX_LATEST_CONTAINER} \ /bin/bash -c " cmake /src \ - -DCMAKE_CXX_STANDARD=11 \ + -DCMAKE_CXX_STANDARD=14 \ -Dgtest_build_samples=ON \ -Dgtest_build_tests=ON \ -Dgmock_build_tests=ON \ @@ -72,11 +72,15 @@ time docker run \ --workdir="/src" \ --rm \ --env="CC=/usr/local/bin/gcc" \ + --env="BAZEL_CXXOPTS=-std=c++14" \ ${LINUX_GCC_FLOOR_CONTAINER} \ /usr/local/bin/bazel test ... \ --copt="-Wall" \ --copt="-Werror" \ + --copt="-Wuninitialized" \ --copt="-Wno-error=pragmas" \ + --distdir="/bazel-distdir" \ + --features=external_include_paths \ --keep_going \ --show_timestamps \ --test_output=errors @@ -94,8 +98,10 @@ for std in ${STD}; do /usr/local/bin/bazel test ... \ --copt="-Wall" \ --copt="-Werror" \ + --copt="-Wuninitialized" \ --define="absl=${absl}" \ --distdir="/bazel-distdir" \ + --features=external_include_paths \ --keep_going \ --show_timestamps \ --test_output=errors @@ -116,8 +122,10 @@ for std in ${STD}; do --copt="--gcc-toolchain=/usr/local" \ --copt="-Wall" \ --copt="-Werror" \ + --copt="-Wuninitialized" \ --define="absl=${absl}" \ --distdir="/bazel-distdir" \ + --features=external_include_paths \ --keep_going \ --linkopt="--gcc-toolchain=/usr/local" \ --show_timestamps \ diff --git a/googletest/ci/macos-presubmit.sh b/googletest/ci/macos-presubmit.sh index d6423faacc3f425dd083f5771b4a42db9f9fbd5e..8f35df58d2baa1b278f468608deb517d05150a3a 100644 --- a/googletest/ci/macos-presubmit.sh +++ b/googletest/ci/macos-presubmit.sh @@ -40,7 +40,7 @@ for cmake_off_on in OFF ON; do BUILD_DIR=$(mktemp -d build_dir.XXXXXXXX) cd ${BUILD_DIR} time cmake ${GTEST_ROOT} \ - -DCMAKE_CXX_STANDARD=11 \ + -DCMAKE_CXX_STANDARD=14 \ -Dgtest_build_samples=ON \ -Dgtest_build_tests=ON \ -Dgmock_build_tests=ON \ @@ -53,7 +53,7 @@ done # Test the Bazel build # If we are running on Kokoro, check for a versioned Bazel binary. -KOKORO_GFILE_BAZEL_BIN="bazel-3.7.0-darwin-x86_64" +KOKORO_GFILE_BAZEL_BIN="bazel-5.1.1-darwin-x86_64" if [[ ${KOKORO_GFILE_DIR:-} ]] && [[ -f ${KOKORO_GFILE_DIR}/${KOKORO_GFILE_BAZEL_BIN} ]]; then BAZEL_BIN="${KOKORO_GFILE_DIR}/${KOKORO_GFILE_BAZEL_BIN}" chmod +x ${BAZEL_BIN} @@ -66,7 +66,9 @@ for absl in 0 1; do ${BAZEL_BIN} test ... \ --copt="-Wall" \ --copt="-Werror" \ + --cxxopt="-std=c++14" \ --define="absl=${absl}" \ + --features=external_include_paths \ --keep_going \ --show_timestamps \ --test_output=errors diff --git a/googletest/ci/windows-presubmit.bat b/googletest/ci/windows-presubmit.bat new file mode 100644 index 0000000000000000000000000000000000000000..0c822d5e519793bd46140723af97e42ea827afed --- /dev/null +++ b/googletest/ci/windows-presubmit.bat @@ -0,0 +1,71 @@ +@echo off +@rem Copyright 2024 googletest authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem http://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. + +SETLOCAL ENABLEDELAYEDEXPANSION + +SET BAZEL_EXE=%KOKORO_GFILE_DIR%\bazel-5.1.1-windows-x86_64.exe + +SET PATH=C:\Python37;%PATH% +SET BAZEL_PYTHON=C:\python37\python.exe +SET BAZEL_SH=C:\tools\msys64\usr\bin\bash.exe +SET CMAKE_BIN="C:\Program Files\CMake\bin\cmake.exe" +SET CTEST_BIN="C:\Program Files\CMake\bin\ctest.exe" +SET CTEST_OUTPUT_ON_FAILURE=1 + +IF EXIST git\googletest ( + CD git\googletest +) ELSE IF EXIST github\googletest ( + CD github\googletest +) + +IF %errorlevel% neq 0 EXIT /B 1 + +:: ---------------------------------------------------------------------------- +:: CMake Visual Studio 15 2017 Win64 +MKDIR cmake_msvc2017 +CD cmake_msvc2017 + +%CMAKE_BIN% .. ^ + -G "Visual Studio 15 2017 Win64" ^ + -DPYTHON_EXECUTABLE:FILEPATH=c:\python37\python.exe ^ + -DPYTHON_INCLUDE_DIR:PATH=c:\python37\include ^ + -DPYTHON_LIBRARY:FILEPATH=c:\python37\lib\site-packages\pip ^ + -Dgtest_build_samples=ON ^ + -Dgtest_build_tests=ON ^ + -Dgmock_build_tests=ON +IF %errorlevel% neq 0 EXIT /B 1 + +%CMAKE_BIN% --build . --target ALL_BUILD --config Debug -- -maxcpucount +IF %errorlevel% neq 0 EXIT /B 1 + +%CTEST_BIN% -C Debug --timeout 600 +IF %errorlevel% neq 0 EXIT /B 1 + +CD .. +RMDIR /S /Q cmake_msvc2017 + +:: ---------------------------------------------------------------------------- +:: Bazel Visual Studio 15 2017 Win64 + +SET BAZEL_VC=C:\Program Files (x86)\Microsoft Visual Studio\2017\BuildTools\VC +%BAZEL_EXE% test ... ^ + --compilation_mode=dbg ^ + --copt=/std:c++14 ^ + --copt=/WX ^ + --features=external_include_paths ^ + --keep_going ^ + --test_output=errors ^ + --test_tag_filters=-no_test_msvc2017 +IF %errorlevel% neq 0 EXIT /B 1 diff --git a/googletest/docs/_layouts/default.html b/googletest/docs/_layouts/default.html index dcb42d9191342a42429c197623b0f8df9faded91..c7f331b87d7ddd4102791fd4d5b4122bfb0dd4b3 100644 --- a/googletest/docs/_layouts/default.html +++ b/googletest/docs/_layouts/default.html @@ -48,7 +48,7 @@ diff --git a/googletest/docs/advanced.md b/googletest/docs/advanced.md index 8dff5ba1508085ae5b26a2716985eb669a90ebd8..f16382fe04fcd6fe91edb48e7e2748d3963a45e4 100644 --- a/googletest/docs/advanced.md +++ b/googletest/docs/advanced.md @@ -157,8 +157,11 @@ that can be used in the predicate assertion macro example: ```c++ -EXPECT_PRED_FORMAT2(testing::FloatLE, val1, val2); -EXPECT_PRED_FORMAT2(testing::DoubleLE, val1, val2); +using ::testing::FloatLE; +using ::testing::DoubleLE; +... +EXPECT_PRED_FORMAT2(FloatLE, val1, val2); +EXPECT_PRED_FORMAT2(DoubleLE, val1, val2); ``` The above code verifies that `val1` is less than, or approximately equal to, @@ -202,10 +205,9 @@ You can call the function to assert that types `T1` and `T2` are the same. The function does nothing if the assertion is satisfied. If the types are different, the function call will -fail to compile, the compiler error message will say that -`T1 and T2 are not the same type` and most likely (depending on the compiler) -show you the actual values of `T1` and `T2`. This is mainly useful inside -template code. +fail to compile, the compiler error message will say that `T1 and T2 are not the +same type` and most likely (depending on the compiler) show you the actual +values of `T1` and `T2`. This is mainly useful inside template code. **Caveat**: When used inside a member function of a class template or a function template, `StaticAssertTypeEq()` is effective only if the function is @@ -383,10 +385,10 @@ EXPECT_TRUE(IsCorrectBarIntVector(bar_ints)) ## Death Tests In many applications, there are assertions that can cause application failure if -a condition is not met. These sanity checks, which ensure that the program is in -a known good state, are there to fail at the earliest possible time after some -program state is corrupted. If the assertion checks the wrong condition, then -the program may proceed in an erroneous state, which could lead to memory +a condition is not met. These consistency checks, which ensure that the program +is in a known good state, are there to fail at the earliest possible time after +some program state is corrupted. If the assertion checks the wrong condition, +then the program may proceed in an erroneous state, which could lead to memory corruption, security holes, or worse. Hence it is vitally important to test that such assertion statements work as expected. @@ -480,10 +482,12 @@ TEST_F(FooDeathTest, DoesThat) { ### Regular Expression Syntax -On POSIX systems (e.g. Linux, Cygwin, and Mac), googletest uses the +When built with Bazel and using Abseil, googletest uses the +[RE2](https://github.com/google/re2/wiki/Syntax) syntax. Otherwise, for POSIX +systems (Linux, Cygwin, Mac), googletest uses the [POSIX extended regular expression](http://www.opengroup.org/onlinepubs/009695399/basedefs/xbd_chap09.html#tag_09_04) -syntax. To learn about this syntax, you may want to read this -[Wikipedia entry](http://en.wikipedia.org/wiki/Regular_expression#POSIX_Extended_Regular_Expressions). +syntax. To learn about POSIX syntax, you may want to read this +[Wikipedia entry](http://en.wikipedia.org/wiki/Regular_expression#POSIX_extended). On Windows, googletest uses its own simple regular expression implementation. It lacks many features. For example, we don't support union (`"x|y"`), grouping @@ -558,7 +562,7 @@ The automated testing framework does not set the style flag. You can choose a particular style of death tests by setting the flag programmatically: ```c++ -testing::FLAGS_gtest_death_test_style="threadsafe" +GTEST_FLAG_SET(death_test_style, "threadsafe") ``` You can do this in `main()` to set the style for all death tests in the binary, @@ -568,12 +572,12 @@ restored afterwards, so you need not do that yourself. For example: ```c++ int main(int argc, char** argv) { testing::InitGoogleTest(&argc, argv); - testing::FLAGS_gtest_death_test_style = "fast"; + GTEST_FLAG_SET(death_test_style, "fast"); return RUN_ALL_TESTS(); } TEST(MyDeathTest, TestOne) { - testing::FLAGS_gtest_death_test_style = "threadsafe"; + GTEST_FLAG_SET(death_test_style, "threadsafe"); // This test is run in the "threadsafe" style: ASSERT_DEATH(ThisShouldDie(), ""); } @@ -610,15 +614,14 @@ Despite the improved thread safety afforded by the "threadsafe" style of death test, thread problems such as deadlock are still possible in the presence of handlers registered with `pthread_atfork(3)`. - ## Using Assertions in Sub-routines {: .callout .note} Note: If you want to put a series of test assertions in a subroutine to check for a complex condition, consider using -[a custom GMock matcher](gmock_cook_book.md#NewMatchers) -instead. This lets you provide a more readable error message in case of failure -and avoid all of the issues described below. +[a custom GMock matcher](gmock_cook_book.md#NewMatchers) instead. This lets you +provide a more readable error message in case of failure and avoid all of the +issues described below. ### Adding Traces to Assertions @@ -631,6 +634,7 @@ the `SCOPED_TRACE` macro or the `ScopedTrace` utility: ```c++ SCOPED_TRACE(message); ``` + ```c++ ScopedTrace trace("file_path", line_number, message); ``` @@ -837,7 +841,7 @@ will output XML like this: ```xml ... - + ... ``` @@ -888,6 +892,12 @@ preceding or following another. Also, the tests must either not modify the state of any shared resource, or, if they do modify the state, they must restore the state to its original value before passing control to the next test. +Note that `SetUpTestSuite()` may be called multiple times for a test fixture +class that has derived classes, so you should not expect code in the function +body to be run only once. Also, derived classes still have access to shared +resources defined as static members, so careful consideration is needed when +managing shared resources to avoid memory leaks. + Here's an example of per-test-suite set-up and tear-down: ```c++ @@ -897,7 +907,10 @@ class FooTest : public testing::Test { // Called before the first test in this test suite. // Can be omitted if not needed. static void SetUpTestSuite() { - shared_resource_ = new ...; + // Avoid reallocating static objects if called in subclasses of FooTest. + if (shared_resource_ == nullptr) { + shared_resource_ = new ...; + } } // Per-test-suite tear-down. @@ -1082,6 +1095,11 @@ instantiation of the test suite. The next argument is the name of the test pattern, and the last is the [parameter generator](reference/testing.md#param-generators). +The parameter generator expression is not evaluated until GoogleTest is +initialized (via `InitGoogleTest()`). Any prior initialization done in the +`main` function will be accessible from the parameter generator, for example, +the results of flag parsing. + You can instantiate a test pattern more than once, so to distinguish different instances of the pattern, the instantiation name is added as a prefix to the actual test suite name. Remember to pick unique prefixes for different @@ -1129,8 +1147,8 @@ GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(FooTest); You can see [sample7_unittest.cc] and [sample8_unittest.cc] for more examples. -[sample7_unittest.cc]: https://github.com/google/googletest/blob/master/googletest/samples/sample7_unittest.cc "Parameterized Test example" -[sample8_unittest.cc]: https://github.com/google/googletest/blob/master/googletest/samples/sample8_unittest.cc "Parameterized Test example with multiple parameters" +[sample7_unittest.cc]: https://github.com/google/googletest/blob/main/googletest/samples/sample7_unittest.cc "Parameterized Test example" +[sample8_unittest.cc]: https://github.com/google/googletest/blob/main/googletest/samples/sample8_unittest.cc "Parameterized Test example with multiple parameters" ### Creating Value-Parameterized Abstract Tests @@ -1281,7 +1299,7 @@ TYPED_TEST(FooTest, HasPropertyA) { ... } You can see [sample6_unittest.cc] for a complete example. -[sample6_unittest.cc]: https://github.com/google/googletest/blob/master/googletest/samples/sample6_unittest.cc "Typed Test example" +[sample6_unittest.cc]: https://github.com/google/googletest/blob/main/googletest/samples/sample6_unittest.cc "Typed Test example" ## Type-Parameterized Tests @@ -1302,6 +1320,7 @@ First, define a fixture class template, as we did with typed tests: ```c++ template class FooTest : public testing::Test { + void DoSomethingInteresting(); ... }; ``` @@ -1319,6 +1338,9 @@ this as many times as you want: TYPED_TEST_P(FooTest, DoesBlah) { // Inside a test, refer to TypeParam to get the type parameter. TypeParam n = 0; + + // You will need to use `this` explicitly to refer to fixture members. + this->DoSomethingInteresting() ... } @@ -1481,8 +1503,8 @@ In frameworks that report a failure by throwing an exception, you could catch the exception and assert on it. But googletest doesn't use exceptions, so how do we test that a piece of code generates an expected failure? -`"gtest/gtest-spi.h"` contains some constructs to do this. After #including this header, -you can use +`"gtest/gtest-spi.h"` contains some constructs to do this. +After #including this header, you can use ```c++ EXPECT_FATAL_FAILURE(statement, substring); @@ -1586,12 +1608,14 @@ void RegisterMyTests(const std::vector& values) { } ... int main(int argc, char** argv) { + testing::InitGoogleTest(&argc, argv); std::vector values_to_test = LoadValuesFromConfig(); RegisterMyTests(values_to_test); ... return RUN_ALL_TESTS(); } ``` + ## Getting the Current Test's Name Sometimes a function may need to know the name of the currently running test. @@ -1714,7 +1738,7 @@ You can do so by adding one line: Now, sit back and enjoy a completely different output from your tests. For more details, see [sample9_unittest.cc]. -[sample9_unittest.cc]: https://github.com/google/googletest/blob/master/googletest/samples/sample9_unittest.cc "Event listener example" +[sample9_unittest.cc]: https://github.com/google/googletest/blob/main/googletest/samples/sample9_unittest.cc "Event listener example" You may append more than one listener to the list. When an `On*Start()` or `OnTestPartResult()` event is fired, the listeners will receive it in the order @@ -1741,7 +1765,7 @@ by the former. See [sample10_unittest.cc] for an example of a failure-raising listener. -[sample10_unittest.cc]: https://github.com/google/googletest/blob/master/googletest/samples/sample10_unittest.cc "Failure-raising listener example" +[sample10_unittest.cc]: https://github.com/google/googletest/blob/main/googletest/samples/sample10_unittest.cc "Failure-raising listener example" ## Running Test Programs: Advanced Options @@ -1816,8 +1840,7 @@ By default, a googletest program runs all tests the user has defined. In some cases (e.g. iterative test development & execution) it may be desirable stop test execution upon first failure (trading improved latency for completeness). If `GTEST_FAIL_FAST` environment variable or `--gtest_fail_fast` flag is set, -the test runner will stop execution as soon as the first test failure is -found. +the test runner will stop execution as soon as the first test failure is found. #### Temporarily Disabling Tests @@ -1890,8 +1913,12 @@ Repeat the tests whose name matches the filter 1000 times. If your test program contains [global set-up/tear-down](#global-set-up-and-tear-down) code, it will be -repeated in each iteration as well, as the flakiness may be in it. You can also -specify the repeat count by setting the `GTEST_REPEAT` environment variable. +repeated in each iteration as well, as the flakiness may be in it. To avoid +repeating global set-up/tear-down, specify +`--gtest_recreate_environments_when_repeating=false`{.nowrap}. + +You can also specify the repeat count by setting the `GTEST_REPEAT` environment +variable. ### Shuffling the Tests @@ -1911,6 +1938,58 @@ time. If you combine this with `--gtest_repeat=N`, googletest will pick a different random seed and re-shuffle the tests in each iteration. +### Distributing Test Functions to Multiple Machines + +If you have more than one machine you can use to run a test program, you might +want to run the test functions in parallel and get the result faster. We call +this technique *sharding*, where each machine is called a *shard*. + +GoogleTest is compatible with test sharding. To take advantage of this feature, +your test runner (not part of GoogleTest) needs to do the following: + +1. Allocate a number of machines (shards) to run the tests. +1. On each shard, set the `GTEST_TOTAL_SHARDS` environment variable to the total + number of shards. It must be the same for all shards. +1. On each shard, set the `GTEST_SHARD_INDEX` environment variable to the index + of the shard. Different shards must be assigned different indices, which + must be in the range `[0, GTEST_TOTAL_SHARDS - 1]`. +1. Run the same test program on all shards. When GoogleTest sees the above two + environment variables, it will select a subset of the test functions to run. + Across all shards, each test function in the program will be run exactly + once. +1. Wait for all shards to finish, then collect and report the results. + +Your project may have tests that were written without GoogleTest and thus don't +understand this protocol. In order for your test runner to figure out which test +supports sharding, it can set the environment variable `GTEST_SHARD_STATUS_FILE` +to a non-existent file path. If a test program supports sharding, it will create +this file to acknowledge that fact; otherwise it will not create it. The actual +contents of the file are not important at this time, although we may put some +useful information in it in the future. + +Here's an example to make it clear. Suppose you have a test program `foo_test` +that contains the following 5 test functions: + +``` +TEST(A, V) +TEST(A, W) +TEST(B, X) +TEST(B, Y) +TEST(B, Z) +``` + +Suppose you have 3 machines at your disposal. To run the test functions in +parallel, you would set `GTEST_TOTAL_SHARDS` to 3 on all machines, and set +`GTEST_SHARD_INDEX` to 0, 1, and 2 on the machines respectively. Then you would +run the same `foo_test` on each machine. + +GoogleTest reserves the right to change how the work is distributed across the +shards, but here's one possible scenario: + +* Machine #0 runs `A.V` and `B.X`. +* Machine #1 runs `A.W` and `B.Y`. +* Machine #2 runs `B.Z`. + ### Controlling Test Output #### Colored Terminal Output @@ -1965,8 +2044,6 @@ text because, for example, you don't have an UTF-8 compatible output medium, run the test program with `--gtest_print_utf8=0` or set the `GTEST_PRINT_UTF8` environment variable to `0`. - - #### Generating an XML Report googletest can emit a detailed XML report to a file in addition to its normal @@ -2020,15 +2097,15 @@ could generate this report: - + ... ... - + - + @@ -2046,6 +2123,9 @@ Things to note: * The `timestamp` attribute records the local date and time of the test execution. +* The `file` and `line` attributes record the source file location, where the + test was defined. + * Each `` element corresponds to a single failed googletest assertion. @@ -2085,6 +2165,8 @@ The report format conforms to the following JSON Schema: "type": "object", "properties": { "name": { "type": "string" }, + "file": { "type": "string" }, + "line": { "type": "integer" }, "status": { "type": "string", "enum": ["RUN", "NOTRUN"] @@ -2162,6 +2244,8 @@ message TestCase { message TestInfo { string name = 1; + string file = 6; + int32 line = 7; enum Status { RUN = 0; NOTRUN = 1; @@ -2205,6 +2289,8 @@ could generate this report: "testsuite": [ { "name": "Addition", + "file": "test.cpp", + "line": 1, "status": "RUN", "time": "0.007s", "classname": "", @@ -2221,6 +2307,8 @@ could generate this report: }, { "name": "Subtraction", + "file": "test.cpp", + "line": 2, "status": "RUN", "time": "0.005s", "classname": "" @@ -2236,6 +2324,8 @@ could generate this report: "testsuite": [ { "name": "NonContradiction", + "file": "test.cpp", + "line": 3, "status": "RUN", "time": "0.005s", "classname": "" @@ -2253,12 +2343,11 @@ IMPORTANT: The exact format of the JSON document is subject to change. #### Detecting Test Premature Exit -Google Test implements the _premature-exit-file_ protocol for test runners -to catch any kind of unexpected exits of test programs. Upon start, -Google Test creates the file which will be automatically deleted after -all work has been finished. Then, the test runner can check if this file -exists. In case the file remains undeleted, the inspected test has exited -prematurely. +Google Test implements the _premature-exit-file_ protocol for test runners to +catch any kind of unexpected exits of test programs. Upon start, Google Test +creates the file which will be automatically deleted after all work has been +finished. Then, the test runner can check if this file exists. In case the file +remains undeleted, the inspected test has exited prematurely. This feature is enabled only if the `TEST_PREMATURE_EXIT_FILE` environment variable has been set. diff --git a/googletest/docs/faq.md b/googletest/docs/faq.md index 9042da1efb43a6bf0893275bb8c84e544c01c2a1..1928097292a238a81269a01c8e6bd16c96c61b9b 100644 --- a/googletest/docs/faq.md +++ b/googletest/docs/faq.md @@ -1,9 +1,9 @@ -# Googletest FAQ +# GoogleTest FAQ ## Why should test suite names and test names not contain underscore? {: .callout .note} -Note: Googletest reserves underscore (`_`) for special purpose keywords, such as +Note: GoogleTest reserves underscore (`_`) for special purpose keywords, such as [the `DISABLED_` prefix](advanced.md#temporarily-disabling-tests), in addition to the following rationale. @@ -50,15 +50,15 @@ Now, the two `TEST`s will both generate the same class So for simplicity, we just ask the users to avoid `_` in `TestSuiteName` and `TestName`. The rule is more constraining than necessary, but it's simple and -easy to remember. It also gives googletest some wiggle room in case its +easy to remember. It also gives GoogleTest some wiggle room in case its implementation needs to change in the future. If you violate the rule, there may not be immediate consequences, but your test may (just may) break with a new compiler (or a new version of the compiler you -are using) or with a new version of googletest. Therefore it's best to follow +are using) or with a new version of GoogleTest. Therefore it's best to follow the rule. -## Why does googletest support `EXPECT_EQ(NULL, ptr)` and `ASSERT_EQ(NULL, ptr)` but not `EXPECT_NE(NULL, ptr)` and `ASSERT_NE(NULL, ptr)`? +## Why does GoogleTest support `EXPECT_EQ(NULL, ptr)` and `ASSERT_EQ(NULL, ptr)` but not `EXPECT_NE(NULL, ptr)` and `ASSERT_NE(NULL, ptr)`? First of all, you can use `nullptr` with each of these macros, e.g. `EXPECT_EQ(ptr, nullptr)`, `EXPECT_NE(ptr, nullptr)`, `ASSERT_EQ(ptr, nullptr)`, @@ -68,7 +68,7 @@ because `nullptr` does not have the type problems that `NULL` does. Due to some peculiarity of C++, it requires some non-trivial template meta programming tricks to support using `NULL` as an argument of the `EXPECT_XX()` and `ASSERT_XX()` macros. Therefore we only do it where it's most needed -(otherwise we make the implementation of googletest harder to maintain and more +(otherwise we make the implementation of GoogleTest harder to maintain and more error-prone than necessary). Historically, the `EXPECT_EQ()` macro took the *expected* value as its first @@ -162,7 +162,7 @@ methods, the parent process will think the calls have never occurred. Therefore, you may want to move your `EXPECT_CALL` statements inside the `EXPECT_DEATH` macro. -## EXPECT_EQ(htonl(blah), blah_blah) generates weird compiler errors in opt mode. Is this a googletest bug? +## EXPECT_EQ(htonl(blah), blah_blah) generates weird compiler errors in opt mode. Is this a GoogleTest bug? Actually, the bug is in `htonl()`. @@ -199,7 +199,7 @@ const int Foo::kBar; // No initializer here. ``` Otherwise your code is **invalid C++**, and may break in unexpected ways. In -particular, using it in googletest comparison assertions (`EXPECT_EQ`, etc) will +particular, using it in GoogleTest comparison assertions (`EXPECT_EQ`, etc) will generate an "undefined reference" linker error. The fact that "it used to work" doesn't mean it's valid. It just means that you were lucky. :-) @@ -225,7 +225,7 @@ cases may want to use the same or slightly different fixtures. For example, you may want to make sure that all of a GUI library's test suites don't leak important system resources like fonts and brushes. -In googletest, you share a fixture among test suites by putting the shared logic +In GoogleTest, you share a fixture among test suites by putting the shared logic in a base test fixture, then deriving from that base a separate fixture for each test suite that wants to use this common logic. You then use `TEST_F()` to write tests using each derived fixture. @@ -264,10 +264,10 @@ TEST_F(FooTest, Baz) { ... } ``` If necessary, you can continue to derive test fixtures from a derived fixture. -googletest has no limit on how deep the hierarchy can be. +GoogleTest has no limit on how deep the hierarchy can be. For a complete example using derived test fixtures, see -[sample5_unittest.cc](https://github.com/google/googletest/blob/master/googletest/samples/sample5_unittest.cc). +[sample5_unittest.cc](https://github.com/google/googletest/blob/main/googletest/samples/sample5_unittest.cc). ## My compiler complains "void value not ignored as it ought to be." What does this mean? @@ -278,7 +278,7 @@ disabled by our build system. Please see more details ## My death test hangs (or seg-faults). How do I fix it? -In googletest, death tests are run in a child process and the way they work is +In GoogleTest, death tests are run in a child process and the way they work is delicate. To write death tests you really need to understand how they work—see the details at [Death Assertions](reference/assertions.md#death) in the Assertions Reference. @@ -305,8 +305,8 @@ bullet - sorry! ## Should I use the constructor/destructor of the test fixture or SetUp()/TearDown()? {#CtorVsSetUp} -The first thing to remember is that googletest does **not** reuse the same test -fixture object across multiple tests. For each `TEST_F`, googletest will create +The first thing to remember is that GoogleTest does **not** reuse the same test +fixture object across multiple tests. For each `TEST_F`, GoogleTest will create a **fresh** test fixture object, immediately call `SetUp()`, run the test body, call `TearDown()`, and then delete the test fixture object. @@ -328,7 +328,7 @@ You may still want to use `SetUp()/TearDown()` in the following cases: * C++ does not allow virtual function calls in constructors and destructors. You can call a method declared as virtual, but it will not use dynamic - dispatch, it will use the definition from the class the constructor of which + dispatch. It will use the definition from the class the constructor of which is currently executing. This is because calling a virtual method before the derived class constructor has a chance to run is very dangerous - the virtual method might operate on uninitialized data. Therefore, if you need @@ -345,11 +345,11 @@ You may still want to use `SetUp()/TearDown()` in the following cases: that many standard libraries (like STL) may throw when exceptions are enabled in the compiler. Therefore you should prefer `TearDown()` if you want to write portable tests that work with or without exceptions. -* The googletest team is considering making the assertion macros throw on +* The GoogleTest team is considering making the assertion macros throw on platforms where exceptions are enabled (e.g. Windows, Mac OS, and Linux client-side), which will eliminate the need for the user to propagate failures from a subroutine to its caller. Therefore, you shouldn't use - googletest assertions in a destructor if your code could run on such a + GoogleTest assertions in a destructor if your code could run on such a platform. ## The compiler complains "no matching function to call" when I use ASSERT_PRED*. How do I fix it? @@ -375,7 +375,7 @@ they write This is **wrong and dangerous**. The testing services needs to see the return value of `RUN_ALL_TESTS()` in order to determine if a test has passed. If your `main()` function ignores it, your test will be considered successful even if it -has a googletest assertion failure. Very bad. +has a GoogleTest assertion failure. Very bad. We have decided to fix this (thanks to Michael Chastain for the idea). Now, your code will no longer be able to ignore `RUN_ALL_TESTS()` when compiled with @@ -410,7 +410,6 @@ C++ is case-sensitive. Did you spell it as `Setup()`? Similarly, sometimes people spell `SetUpTestSuite()` as `SetupTestSuite()` and wonder why it's never called. - ## I have several test suites which share the same test fixture logic, do I have to define a new test fixture class for each of them? This seems pretty tedious. You don't have to. Instead of @@ -441,14 +440,14 @@ TEST_F(BarTest, Abc) { ... } TEST_F(BarTest, Def) { ... } ``` -## googletest output is buried in a whole bunch of LOG messages. What do I do? +## GoogleTest output is buried in a whole bunch of LOG messages. What do I do? -The googletest output is meant to be a concise and human-friendly report. If -your test generates textual output itself, it will mix with the googletest +The GoogleTest output is meant to be a concise and human-friendly report. If +your test generates textual output itself, it will mix with the GoogleTest output, making it hard to read. However, there is an easy solution to this problem. -Since `LOG` messages go to stderr, we decided to let googletest output go to +Since `LOG` messages go to stderr, we decided to let GoogleTest output go to stdout. This way, you can easily separate the two using redirection. For example: @@ -521,7 +520,7 @@ TEST(MyDeathTest, CompoundStatement) { ## I have a fixture class `FooTest`, but `TEST_F(FooTest, Bar)` gives me error ``"no matching function for call to `FooTest::FooTest()'"``. Why? -Googletest needs to be able to create objects of your test fixture class, so it +GoogleTest needs to be able to create objects of your test fixture class, so it must have a default constructor. Normally the compiler will define one for you. However, there are cases where you have to define your own: @@ -546,11 +545,11 @@ The new NPTL thread library doesn't suffer from this problem, as it doesn't create a manager thread. However, if you don't control which machine your test runs on, you shouldn't depend on this. -## Why does googletest require the entire test suite, instead of individual tests, to be named *DeathTest when it uses ASSERT_DEATH? +## Why does GoogleTest require the entire test suite, instead of individual tests, to be named *DeathTest when it uses ASSERT_DEATH? -googletest does not interleave tests from different test suites. That is, it +GoogleTest does not interleave tests from different test suites. That is, it runs all tests in one test suite first, and then runs all tests in the next test -suite, and so on. googletest does this because it needs to set up a test suite +suite, and so on. GoogleTest does this because it needs to set up a test suite before the first test in it is run, and tear it down afterwards. Splitting up the test case would require multiple set-up and tear-down processes, which is inefficient and makes the semantics unclean. @@ -589,11 +588,11 @@ TEST_F(FooDeathTest, Uvw) { ... EXPECT_DEATH(...) ... } TEST_F(FooDeathTest, Xyz) { ... ASSERT_DEATH(...) ... } ``` -## googletest prints the LOG messages in a death test's child process only when the test fails. How can I see the LOG messages when the death test succeeds? +## GoogleTest prints the LOG messages in a death test's child process only when the test fails. How can I see the LOG messages when the death test succeeds? Printing the LOG messages generated by the statement inside `EXPECT_DEATH()` makes it harder to search for real problems in the parent's log. Therefore, -googletest only prints them when the death test has failed. +GoogleTest only prints them when the death test has failed. If you really need to see such LOG messages, a workaround is to temporarily break the death test (e.g. by changing the regex pattern it is expected to @@ -612,7 +611,7 @@ needs to be defined in the *same* name space. See ## How do I suppress the memory leak messages on Windows? -Since the statically initialized googletest singleton requires allocations on +Since the statically initialized GoogleTest singleton requires allocations on the heap, the Visual C++ memory leak detector will report memory leaks at the end of the program run. The easiest way to avoid this is to use the `_CrtMemCheckpoint` and `_CrtMemDumpAllObjectsSince` calls to not report any @@ -626,7 +625,7 @@ things accordingly, you are leaking test-only logic into production code and there is no easy way to ensure that the test-only code paths aren't run by mistake in production. Such cleverness also leads to [Heisenbugs](https://en.wikipedia.org/wiki/Heisenbug). Therefore we strongly -advise against the practice, and googletest doesn't provide a way to do it. +advise against the practice, and GoogleTest doesn't provide a way to do it. In general, the recommended way to cause the code to behave differently under test is [Dependency Injection](http://en.wikipedia.org/wiki/Dependency_injection). You can inject @@ -673,7 +672,7 @@ TEST(CoolTest, DoSomething) { ``` However, the following code is **not allowed** and will produce a runtime error -from googletest because the test methods are using different test fixture +from GoogleTest because the test methods are using different test fixture classes with the same test suite name. ```c++ diff --git a/googletest/docs/gmock_cheat_sheet.md b/googletest/docs/gmock_cheat_sheet.md index 17ed7a54d80933ec8fce9a0691c958809c2dedb5..2fb0403e616a79a46294a6dd5c8489f1f1dd2a78 100644 --- a/googletest/docs/gmock_cheat_sheet.md +++ b/googletest/docs/gmock_cheat_sheet.md @@ -8,7 +8,7 @@ Given ```cpp class Foo { - ... + public: virtual ~Foo(); virtual int GetSize() const = 0; virtual string Describe(const char* name) = 0; @@ -23,7 +23,7 @@ class Foo { #include "gmock/gmock.h" class MockFoo : public Foo { - ... + public: MOCK_METHOD(int, GetSize, (), (const, override)); MOCK_METHOD(string, Describe, (const char* name), (override)); MOCK_METHOD(string, Describe, (int type), (override)); @@ -58,7 +58,7 @@ To mock ```cpp template class StackInterface { - ... + public: virtual ~StackInterface(); virtual int GetSize() const = 0; virtual void Push(const Elem& x) = 0; @@ -71,7 +71,7 @@ class StackInterface { ```cpp template class MockStack : public StackInterface { - ... + public: MOCK_METHOD(int, GetSize, (), (const, override)); MOCK_METHOD(void, Push, (const Elem& x), (override)); }; @@ -140,7 +140,7 @@ To customize the default action for functions with return type `T`, use // Sets the default action for return type std::unique_ptr to // creating a new Buzz every time. DefaultValue>::SetFactory( - [] { return MakeUnique(AccessLevel::kInternal); }); + [] { return std::make_unique(AccessLevel::kInternal); }); // When this fires, the default action of MakeBuzz() will run, which // will return a new Buzz object. @@ -230,7 +230,7 @@ class MockFunction { }; ``` -See this [recipe](gmock_cook_book.md#using-check-points) for one application of +See this [recipe](gmock_cook_book.md#UsingCheckPoints) for one application of it. ## Flags diff --git a/googletest/docs/gmock_cook_book.md b/googletest/docs/gmock_cook_book.md index c08958eb16ab892787db493ac667b83736b1a369..fc7db35b82c769fea0c34cf875bf6529d58cbaab 100644 --- a/googletest/docs/gmock_cook_book.md +++ b/googletest/docs/gmock_cook_book.md @@ -392,8 +392,7 @@ Old macros and their new equivalents: If a mock method has no `EXPECT_CALL` spec but is called, we say that it's an "uninteresting call", and the default action (which can be specified using `ON_CALL()`) of the method will be taken. Currently, an uninteresting call will -also by default cause gMock to print a warning. (In the future, we might remove -this warning by default.) +also by default cause gMock to print a warning. However, sometimes you may want to ignore these uninteresting calls, and sometimes you may want to treat them as errors. gMock lets you make the decision @@ -905,7 +904,7 @@ using ::testing::Contains; using ::testing::Property; inline constexpr auto HasFoo = [](const auto& f) { - return Property(&MyClass::foo, Contains(f)); + return Property("foo", &MyClass::foo, Contains(f)); }; ... EXPECT_THAT(x, HasFoo("blah")); @@ -1084,7 +1083,7 @@ using ::testing::Lt; ``` says that `Blah` will be called with arguments `x`, `y`, and `z` where `x < y < -z`. Note that in this example, it wasn't necessary specify the positional +z`. Note that in this example, it wasn't necessary to specify the positional matchers. As a convenience and example, gMock provides some matchers for 2-tuples, @@ -1159,7 +1158,7 @@ int IsEven(int n) { return (n % 2) == 0 ? 1 : 0; } ``` Note that the predicate function / functor doesn't have to return `bool`. It -works as long as the return value can be used as the condition in in statement +works as long as the return value can be used as the condition in the statement `if (condition) ...`. ### Matching Arguments that Are Not Copyable @@ -1300,23 +1299,27 @@ What if you have a pointer to pointer? You guessed it - you can use nested `Pointee(Pointee(Lt(3)))` matches a pointer that points to a pointer that points to a number less than 3 (what a mouthful...). -### Testing a Certain Property of an Object +### Defining a Custom Matcher Class {#CustomMatcherClass} -Sometimes you want to specify that an object argument has a certain property, -but there is no existing matcher that does this. If you want good error -messages, you should [define a matcher](#NewMatchers). If you want to do it -quick and dirty, you could get away with writing an ordinary function. +Most matchers can be simply defined using [the MATCHER* macros](#NewMatchers), +which are terse and flexible, and produce good error messages. However, these +macros are not very explicit about the interfaces they create and are not always +suitable, especially for matchers that will be widely reused. -Let's say you have a mock function that takes an object of type `Foo`, which has -an `int bar()` method and an `int baz()` method, and you want to constrain that -the argument's `bar()` value plus its `baz()` value is a given number. Here's -how you can define a matcher to do it: +For more advanced cases, you may need to define your own matcher class. A custom +matcher allows you to test a specific invariant property of that object. Let's +take a look at how to do so. -```cpp -using ::testing::Matcher; +Imagine you have a mock function that takes an object of type `Foo`, which has +an `int bar()` method and an `int baz()` method. You want to constrain that the +argument's `bar()` value plus its `baz()` value is a given number. (This is an +invariant.) Here's how we can write and use a matcher class to do so: +```cpp class BarPlusBazEqMatcher { public: + using is_gtest_matcher = void; + explicit BarPlusBazEqMatcher(int expected_sum) : expected_sum_(expected_sum) {} @@ -1325,23 +1328,24 @@ class BarPlusBazEqMatcher { return (foo.bar() + foo.baz()) == expected_sum_; } - void DescribeTo(std::ostream& os) const { - os << "bar() + baz() equals " << expected_sum_; + void DescribeTo(std::ostream* os) const { + *os << "bar() + baz() equals " << expected_sum_; } - void DescribeNegationTo(std::ostream& os) const { - os << "bar() + baz() does not equal " << expected_sum_; + void DescribeNegationTo(std::ostream* os) const { + *os << "bar() + baz() does not equal " << expected_sum_; } private: const int expected_sum_; }; -Matcher BarPlusBazEq(int expected_sum) { +::testing::Matcher BarPlusBazEq(int expected_sum) { return BarPlusBazEqMatcher(expected_sum); } ... - EXPECT_CALL(..., DoThis(BarPlusBazEq(5)))...; + Foo foo; + EXPECT_THAT(foo, BarPlusBazEq(5))...; ``` ### Matching Containers @@ -1420,11 +1424,12 @@ Use `Pair` when comparing maps or other associative containers. {% raw %} ```cpp -using testing::ElementsAre; -using testing::Pair; +using ::testing::UnorderedElementsAre; +using ::testing::Pair; ... - std::map m = {{"a", 1}, {"b", 2}, {"c", 3}}; - EXPECT_THAT(m, ElementsAre(Pair("a", 1), Pair("b", 2), Pair("c", 3))); + absl::flat_hash_map m = {{"a", 1}, {"b", 2}, {"c", 3}}; + EXPECT_THAT(m, UnorderedElementsAre( + Pair("a", 1), Pair("b", 2), Pair("c", 3))); ``` {% endraw %} @@ -1441,8 +1446,8 @@ using testing::Pair; * If the container is passed by pointer instead of by reference, just write `Pointee(ElementsAre*(...))`. * The order of elements *matters* for `ElementsAre*()`. If you are using it - with containers whose element order are undefined (e.g. `hash_map`) you - should use `WhenSorted` around `ElementsAre`. + with containers whose element order are undefined (such as a + `std::unordered_map`) you should use `UnorderedElementsAre`. ### Sharing Matchers @@ -1452,7 +1457,7 @@ the pointer is copied. When the last matcher that references the implementation object dies, the implementation object will be deleted. Therefore, if you have some complex matcher that you want to use again and -again, there is no need to build it everytime. Just assign it to a matcher +again, there is no need to build it every time. Just assign it to a matcher variable and use that variable repeatedly! For example, ```cpp @@ -1754,7 +1759,7 @@ specifies the following DAG (where `s1` is `A -> B`, and `s2` is `A -> C -> D`): | A ---| | - +---> C ---> D + +---> C ---> D ``` This means that A must occur before B and C, and C must occur before D. There's @@ -1899,7 +1904,7 @@ using testing::ReturnPointee; ### Combining Actions Want to do more than one thing when a function is called? That's fine. `DoAll()` -allow you to do sequence of actions every time. Only the return value of the +allows you to do a sequence of actions every time. Only the return value of the last action in the sequence will be used. ```cpp @@ -1980,6 +1985,7 @@ If the mock method also needs to return a value as well, you can chain ```cpp using ::testing::_; +using ::testing::DoAll; using ::testing::Return; using ::testing::SetArgPointee; @@ -2033,10 +2039,7 @@ class MockRolodex : public Rolodex { } ... MockRolodex rolodex; - vector names; - names.push_back("George"); - names.push_back("John"); - names.push_back("Thomas"); + vector names = {"George", "John", "Thomas"}; EXPECT_CALL(rolodex, GetNames(_)) .WillOnce(SetArrayArgument<0>(names.begin(), names.end())); ``` @@ -2604,7 +2607,7 @@ efficient. When the last action that references the implementation object dies, the implementation object will be deleted. If you have some complex action that you want to use again and again, you may -not have to build it from scratch everytime. If the action doesn't have an +not have to build it from scratch every time. If the action doesn't have an internal state (i.e. if it always does the same thing no matter how many times it has been called), you can assign it to an action variable and use that variable repeatedly. For example: @@ -2781,7 +2784,7 @@ If you just need to return a pre-defined move-only value, you can use the // When this fires, the unique_ptr<> specified by ByMove(...) will // be returned. EXPECT_CALL(mock_buzzer_, MakeBuzz("world")) - .WillOnce(Return(ByMove(MakeUnique(AccessLevel::kInternal)))); + .WillOnce(Return(ByMove(std::make_unique(AccessLevel::kInternal)))); EXPECT_NE(nullptr, mock_buzzer_.MakeBuzz("world")); ``` @@ -2802,7 +2805,7 @@ pretty much anything you want: ```cpp EXPECT_CALL(mock_buzzer_, MakeBuzz("x")) .WillRepeatedly([](StringPiece text) { - return MakeUnique(AccessLevel::kInternal); + return std::make_unique(AccessLevel::kInternal); }); EXPECT_NE(nullptr, mock_buzzer_.MakeBuzz("x")); @@ -2821,7 +2824,7 @@ can always use `Return`, or a [lambda or functor](#FunctionsAsActions): using ::testing::Unused; EXPECT_CALL(mock_buzzer_, ShareBuzz(NotNull(), _)).WillOnce(Return(true)); - EXPECT_TRUE(mock_buzzer_.ShareBuzz(MakeUnique(AccessLevel::kInternal)), + EXPECT_TRUE(mock_buzzer_.ShareBuzz(std::make_unique(AccessLevel::kInternal)), 0); EXPECT_CALL(mock_buzzer_, ShareBuzz(_, _)).WillOnce( @@ -2865,7 +2868,7 @@ method: // When one calls ShareBuzz() on the MockBuzzer like this, the call is // forwarded to DoShareBuzz(), which is mocked. Therefore this statement // will trigger the above EXPECT_CALL. - mock_buzzer_.ShareBuzz(MakeUnique(AccessLevel::kInternal), 0); + mock_buzzer_.ShareBuzz(std::make_unique(AccessLevel::kInternal), 0); ``` ### Making the Compilation Faster @@ -3809,22 +3812,19 @@ Cardinality EvenNumber() { .Times(EvenNumber()); ``` -### Writing New Actions Quickly {#QuickNewActions} +### Writing New Actions {#QuickNewActions} If the built-in actions don't work for you, you can easily define your own one. -Just define a functor class with a (possibly templated) call operator, matching -the signature of your action. +All you need is a call operator with a signature compatible with the mocked +function. So you can use a lambda: -```cpp -struct Increment { - template - T operator()(T* arg) { - return ++(*arg); - } -} +``` +MockFunction mock; +EXPECT_CALL(mock, Call).WillOnce([](const int input) { return input * 7; }); +EXPECT_EQ(14, mock.AsStdFunction()(2)); ``` -The same approach works with stateful functors (or any callable, really): +Or a struct with a call operator (even a templated one): ``` struct MultiplyBy { @@ -3832,12 +3832,54 @@ struct MultiplyBy { T operator()(T arg) { return arg * multiplier; } int multiplier; -} +}; // Then use: // EXPECT_CALL(...).WillOnce(MultiplyBy{7}); ``` +It's also fine for the callable to take no arguments, ignoring the arguments +supplied to the mock function: + +``` +MockFunction mock; +EXPECT_CALL(mock, Call).WillOnce([] { return 17; }); +EXPECT_EQ(17, mock.AsStdFunction()(0)); +``` + +When used with `WillOnce`, the callable can assume it will be called at most +once and is allowed to be a move-only type: + +``` +// An action that contains move-only types and has an &&-qualified operator, +// demanding in the type system that it be called at most once. This can be +// used with WillOnce, but the compiler will reject it if handed to +// WillRepeatedly. +struct MoveOnlyAction { + std::unique_ptr move_only_state; + std::unique_ptr operator()() && { return std::move(move_only_state); } +}; + +MockFunction()> mock; +EXPECT_CALL(mock, Call).WillOnce(MoveOnlyAction{std::make_unique(17)}); +EXPECT_THAT(mock.AsStdFunction()(), Pointee(Eq(17))); +``` + +More generally, to use with a mock function whose signature is `R(Args...)` the +object can be anything convertible to `OnceAction` or +`Action. The difference between the two is that `OnceAction` has +weaker requirements (`Action` requires a copy-constructible input that can be +called repeatedly whereas `OnceAction` requires only move-constructible and +supports `&&`-qualified call operators), but can be used only with `WillOnce`. +`OnceAction` is typically relevant only when supporting move-only types or +actions that want a type-system guarantee that they will be called at most once. + +Typically the `OnceAction` and `Action` templates need not be referenced +directly in your actions: a struct or class with a call operator is sufficient, +as in the examples above. But fancier polymorphic actions that need to know the +specific return type of the mock function can define templated conversion +operators to make that possible. See `gmock-actions.h` for examples. + #### Legacy macro-based Actions Before C++11, the functor-based actions were not supported; the old way of @@ -4191,7 +4233,7 @@ This implementation class does *not* need to inherit from any particular class. What matters is that it must have a `Perform()` method template. This method template takes the mock function's arguments as a tuple in a **single** argument, and returns the result of the action. It can be either `const` or not, -but must be invokable with exactly one template argument, which is the result +but must be invocable with exactly one template argument, which is the result type. In other words, you must be able to call `Perform(args)` where `R` is the mock function's return type and `args` is its arguments in a tuple. diff --git a/googletest/docs/gmock_faq.md b/googletest/docs/gmock_faq.md index 2cd9b3f3155966fe078e2f17809eea4b8045c7bd..8f220bf7a8fec033ed9cb827a794397315962fcc 100644 --- a/googletest/docs/gmock_faq.md +++ b/googletest/docs/gmock_faq.md @@ -369,8 +369,8 @@ Usually, if your action is for a particular function type, defining it using different types (e.g. if you are defining `Return(*value*)`), `MakePolymorphicAction()` is easiest. Sometimes you want precise control on what types of functions the action can be used in, and implementing `ActionInterface` -is the way to go here. See the implementation of `Return()` in -`testing/base/public/gmock-actions.h` for an example. +is the way to go here. See the implementation of `Return()` in `gmock-actions.h` +for an example. ### I use SetArgPointee() in WillOnce(), but gcc complains about "conflicting return type specified". What does it mean? diff --git a/googletest/docs/gmock_for_dummies.md b/googletest/docs/gmock_for_dummies.md index 1f4cc246c483109a494adc7c0b3d0981e061c77b..b7264d3587f71ada659741bd6c47ac015ff46e99 100644 --- a/googletest/docs/gmock_for_dummies.md +++ b/googletest/docs/gmock_for_dummies.md @@ -190,10 +190,10 @@ Some people put it in a `_test.cc`. This is fine when the interface being mocked `Foo` changes it, your test could break. (You can't really expect `Foo`'s maintainer to fix every test that uses `Foo`, can you?) -So, the rule of thumb is: if you need to mock `Foo` and it's owned by others, -define the mock class in `Foo`'s package (better, in a `testing` sub-package -such that you can clearly separate production code and testing utilities), put -it in a `.h` and a `cc_library`. Then everyone can reference them from their +Generally, you should not mock classes you don't own. If you must mock such a +class owned by others, define the mock class in `Foo`'s Bazel package (usually +the same directory or a `testing` sub-directory), and put it in a `.h` and a +`cc_library` with `testonly=True`. Then everyone can reference them from their tests. If `Foo` ever changes, there is only one copy of `MockFoo` to change, and only tests that depend on the changed methods need to be fixed. @@ -480,8 +480,8 @@ the *default* action for the function every time (unless, of course, you have a `WillRepeatedly()`.). What can we do inside `WillOnce()` besides `Return()`? You can return a -reference using `ReturnRef(*variable*)`, or invoke a pre-defined function, among -[others](gmock_cook_book.md#using-actions). +reference using `ReturnRef(`*`variable`*`)`, or invoke a pre-defined function, +among [others](gmock_cook_book.md#using-actions). **Important note:** The `EXPECT_CALL()` statement evaluates the action clause only once, even though the action may be performed many times. Therefore you diff --git a/googletest/docs/pkgconfig.md b/googletest/docs/pkgconfig.md index 768e9b4c2673977f4f459dbd76c569ad490978ee..18a2546a3846acde26b930a5ee30a00cce96a570 100644 --- a/googletest/docs/pkgconfig.md +++ b/googletest/docs/pkgconfig.md @@ -105,7 +105,7 @@ includedir=/usr/include Name: gtest Description: GoogleTest (without main() function) -Version: 1.10.0 +Version: 1.11.0 URL: https://github.com/google/googletest Libs: -L${libdir} -lgtest -lpthread Cflags: -I${includedir} -DGTEST_HAS_PTHREAD=1 -lpthread diff --git a/googletest/docs/primer.md b/googletest/docs/primer.md index 6d8fdf443923cacc83425cf45d5102d9889f6241..2ffbf53bc8dff6337e8f4c4d33d6f7b4df767bbe 100644 --- a/googletest/docs/primer.md +++ b/googletest/docs/primer.md @@ -162,9 +162,9 @@ TEST(TestSuiteName, TestName) { `TEST()` arguments go from general to specific. The *first* argument is the name of the test suite, and the *second* argument is the test's name within the test -suite. Both names must be valid C++ identifiers, and they should not contain -any underscores (`_`). A test's *full name* consists of its containing test suite and -its individual name. Tests from different test suites can have the same +suite. Both names must be valid C++ identifiers, and they should not contain any +underscores (`_`). A test's *full name* consists of its containing test suite +and its individual name. Tests from different test suites can have the same individual name. For example, let's take a simple integer function: @@ -245,8 +245,8 @@ Also, you must first define a test fixture class before using it in a declaration`". For each test defined with `TEST_F()`, googletest will create a *fresh* test -fixture at runtime, immediately initialize it via `SetUp()`, run the test, -clean up by calling `TearDown()`, and then delete the test fixture. Note that +fixture at runtime, immediately initialize it via `SetUp()`, run the test, clean +up by calling `TearDown()`, and then delete the test fixture. Note that different tests in the same test suite have different test fixture objects, and googletest always deletes a test fixture before it creates the next one. googletest does **not** reuse the same test fixture for multiple tests. Any @@ -274,6 +274,7 @@ First, define a fixture class. By convention, you should give it the name class QueueTest : public ::testing::Test { protected: void SetUp() override { + // q0_ remains empty q1_.Enqueue(1); q2_.Enqueue(2); q2_.Enqueue(3); @@ -342,8 +343,8 @@ your defined tests in order to run them. After defining your tests, you can run them with `RUN_ALL_TESTS()`, which returns `0` if all the tests are successful, or `1` otherwise. Note that -`RUN_ALL_TESTS()` runs *all tests* in your link unit--they can be from -different test suites, or even different source files. +`RUN_ALL_TESTS()` runs *all tests* in your link unit--they can be from different +test suites, or even different source files. When invoked, the `RUN_ALL_TESTS()` macro: @@ -456,8 +457,8 @@ int main(int argc, char **argv) { The `::testing::InitGoogleTest()` function parses the command line for googletest flags, and removes all recognized flags. This allows the user to -control a test program's behavior via various flags, which we'll cover in -the [AdvancedGuide](advanced.md). You **must** call this function before calling +control a test program's behavior via various flags, which we'll cover in the +[AdvancedGuide](advanced.md). You **must** call this function before calling `RUN_ALL_TESTS()`, or the flags won't be properly initialized. On Windows, `InitGoogleTest()` also works with wide strings, so it can be used diff --git a/googletest/docs/quickstart-bazel.md b/googletest/docs/quickstart-bazel.md index 362ee6d0506eb04b85fa1b40e57db3ef1c38c09a..15c27a22ed9c63eeb234e35db8f02bb63ba8c9b8 100644 --- a/googletest/docs/quickstart-bazel.md +++ b/googletest/docs/quickstart-bazel.md @@ -9,7 +9,7 @@ we recommend this tutorial as a starting point. To complete this tutorial, you'll need: * A compatible operating system (e.g. Linux, macOS, Windows). -* A compatible C++ compiler that supports at least C++11. +* A compatible C++ compiler that supports at least C++14. * [Bazel](https://bazel.build/), the preferred build system used by the GoogleTest team. @@ -17,16 +17,15 @@ See [Supported Platforms](platforms.md) for more information about platforms compatible with GoogleTest. If you don't already have Bazel installed, see the -[Bazel installation guide](https://docs.bazel.build/versions/master/install.html). +[Bazel installation guide](https://bazel.build/install). -{: .callout .note} -Note: The terminal commands in this tutorial show a Unix shell prompt, but the -commands work on the Windows command line as well. +{: .callout .note} Note: The terminal commands in this tutorial show a Unix +shell prompt, but the commands work on the Windows command line as well. ## Set up a Bazel workspace A -[Bazel workspace](https://docs.bazel.build/versions/master/build-ref.html#workspace) +[Bazel workspace](https://docs.bazel.build/versions/main/build-ref.html#workspace) is a directory on your filesystem that you use to manage source files for the software you want to build. Each workspace directory has a text file named `WORKSPACE` which may be empty, or may contain references to external @@ -40,9 +39,9 @@ $ mkdir my_workspace && cd my_workspace Next, you’ll create the `WORKSPACE` file to specify dependencies. A common and recommended way to depend on GoogleTest is to use a -[Bazel external dependency](https://docs.bazel.build/versions/master/external.html) +[Bazel external dependency](https://docs.bazel.build/versions/main/external.html) via the -[`http_archive` rule](https://docs.bazel.build/versions/master/repo/http.html#http_archive). +[`http_archive` rule](https://docs.bazel.build/versions/main/repo/http.html#http_archive). To do this, in the root directory of your workspace (`my_workspace/`), create a file named `WORKSPACE` with the following contents: @@ -51,28 +50,16 @@ load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive") http_archive( name = "com_google_googletest", - urls = ["https://github.com/google/googletest/archive/609281088cfefc76f9d0ce82e1ff6c30cc3591e5.zip"], - strip_prefix = "googletest-609281088cfefc76f9d0ce82e1ff6c30cc3591e5", + urls = ["https://github.com/google/googletest/archive/5ab508a01f9eb089207ee87fd547d290da39d015.zip"], + strip_prefix = "googletest-5ab508a01f9eb089207ee87fd547d290da39d015", ) ``` The above configuration declares a dependency on GoogleTest which is downloaded as a ZIP archive from GitHub. In the above example, -`609281088cfefc76f9d0ce82e1ff6c30cc3591e5` is the Git commit hash of the +`5ab508a01f9eb089207ee87fd547d290da39d015` is the Git commit hash of the GoogleTest version to use; we recommend updating the hash often to point to the -latest version. - -Bazel also needs a dependency on the -[`rules_cc` repository](https://github.com/bazelbuild/rules_cc) to build C++ -code, so add the following to the `WORKSPACE` file: - -``` -http_archive( - name = "rules_cc", - urls = ["https://github.com/bazelbuild/rules_cc/archive/40548a2974f1aea06215272d9c2b47a14a24e556.zip"], - strip_prefix = "rules_cc-40548a2974f1aea06215272d9c2b47a14a24e556", -) -``` +latest version. Use a recent hash on the `main` branch. Now you're ready to build C++ code that uses GoogleTest. @@ -104,8 +91,6 @@ To build the code, create a file named `BUILD` in the same directory with the following contents: ``` -load("@rules_cc//cc:defs.bzl", "cc_test") - cc_test( name = "hello_test", size = "small", @@ -118,7 +103,7 @@ This `cc_test` rule declares the C++ test binary you want to build, and links to GoogleTest (`//:gtest_main`) using the prefix you specified in the `WORKSPACE` file (`@com_google_googletest`). For more information about Bazel `BUILD` files, see the -[Bazel C++ Tutorial](https://docs.bazel.build/versions/master/tutorial/cpp.html). +[Bazel C++ Tutorial](https://docs.bazel.build/versions/main/tutorial/cpp.html). Now you can build and run your test: diff --git a/googletest/docs/quickstart-cmake.md b/googletest/docs/quickstart-cmake.md index 420f1d3a3c245e978dbf4c56c56660b25c4b8137..5abe50441294bd3183c3d1d9f1934f7fea03f88f 100644 --- a/googletest/docs/quickstart-cmake.md +++ b/googletest/docs/quickstart-cmake.md @@ -10,7 +10,7 @@ this tutorial as a starting point. If your project uses Bazel, see the To complete this tutorial, you'll need: * A compatible operating system (e.g. Linux, macOS, Windows). -* A compatible C++ compiler that supports at least C++11. +* A compatible C++ compiler that supports at least C++14. * [CMake](https://cmake.org/) and a compatible build tool for building the project. * Compatible build tools include @@ -52,13 +52,13 @@ To do this, in your project directory (`my_project`), create a file named cmake_minimum_required(VERSION 3.14) project(my_project) -# GoogleTest requires at least C++11 -set(CMAKE_CXX_STANDARD 11) +# GoogleTest requires at least C++14 +set(CMAKE_CXX_STANDARD 14) include(FetchContent) FetchContent_Declare( googletest - URL https://github.com/google/googletest/archive/609281088cfefc76f9d0ce82e1ff6c30cc3591e5.zip + URL https://github.com/google/googletest/archive/03597a01ee50ed33e9dfd640b249b4be3799d395.zip ) # For Windows: Prevent overriding the parent project's compiler/linker settings set(gtest_force_shared_crt ON CACHE BOOL "" FORCE) @@ -66,7 +66,7 @@ FetchContent_MakeAvailable(googletest) ``` The above configuration declares a dependency on GoogleTest which is downloaded -from GitHub. In the above example, `609281088cfefc76f9d0ce82e1ff6c30cc3591e5` is +from GitHub. In the above example, `03597a01ee50ed33e9dfd640b249b4be3799d395` is the Git commit hash of the GoogleTest version to use; we recommend updating the hash often to point to the latest version. @@ -108,7 +108,7 @@ add_executable( ) target_link_libraries( hello_test - gtest_main + GTest::gtest_main ) include(GoogleTest) diff --git a/googletest/docs/reference/actions.md b/googletest/docs/reference/actions.md index 166d2a897a44465c75a2f3fb9ad34025c8fc98d1..ab81a129eff692d513b27c155abed96dd30f8db6 100644 --- a/googletest/docs/reference/actions.md +++ b/googletest/docs/reference/actions.md @@ -6,7 +6,7 @@ provided by GoogleTest. All actions are defined in the `::testing` namespace. ## Returning a Value -| | | +| Action | Description | | :-------------------------------- | :-------------------------------------------- | | `Return()` | Return from a `void` mock function. | | `Return(value)` | Return `value`. If the type of `value` is different to the mock function's return type, `value` is converted to the latter type at the time the expectation is set, not when the action is executed. | @@ -20,7 +20,7 @@ provided by GoogleTest. All actions are defined in the `::testing` namespace. ## Side Effects -| | | +| Action | Description | | :--------------------------------- | :-------------------------------------- | | `Assign(&variable, value)` | Assign `value` to variable. | | `DeleteArg()` | Delete the `N`-th (0-based) argument, which must be a pointer. | @@ -38,9 +38,9 @@ provided by GoogleTest. All actions are defined in the `::testing` namespace. In the following, by "callable" we mean a free function, `std::function`, functor, or lambda. -| | | +| Action | Description | | :---------------------------------- | :------------------------------------- | -| `f` | Invoke f with the arguments passed to the mock function, where f is a callable. | +| `f` | Invoke `f` with the arguments passed to the mock function, where `f` is a callable. | | `Invoke(f)` | Invoke `f` with the arguments passed to the mock function, where `f` can be a global/static function or a functor. | | `Invoke(object_pointer, &class::method)` | Invoke the method on the object with the arguments passed to the mock function. | | `InvokeWithoutArgs(f)` | Invoke `f`, which can be a global/static function or a functor. `f` must take no arguments. | @@ -86,7 +86,7 @@ value, and `foo` by reference. ## Default Action -| Matcher | Description | +| Action | Description | | :------------ | :----------------------------------------------------- | | `DoDefault()` | Do the default action (specified by `ON_CALL()` or the built-in one). | @@ -96,7 +96,7 @@ composite action - trying to do so will result in a run-time error. ## Composite Actions -| | | +| Action | Description | | :----------------------------- | :------------------------------------------ | | `DoAll(a1, a2, ..., an)` | Do all actions `a1` to `an` and return the result of `an` in each invocation. The first `n - 1` sub-actions must return void and will receive a readonly view of the arguments. | | `IgnoreResult(a)` | Perform action `a` and ignore its result. `a` must not return void. | @@ -106,7 +106,7 @@ composite action - trying to do so will result in a run-time error. ## Defining Actions -| | | +| Macro | Description | | :--------------------------------- | :-------------------------------------- | | `ACTION(Sum) { return arg0 + arg1; }` | Defines an action `Sum()` to return the sum of the mock function's argument #0 and #1. | | `ACTION_P(Plus, n) { return arg0 + n; }` | Defines an action `Plus(n)` to return the sum of the mock function's argument #0 and `n`. | diff --git a/googletest/docs/reference/matchers.md b/googletest/docs/reference/matchers.md index 9e40cab70454a68fa8a9d708b6fa2fe87e498a76..9fb159275131504ec920303268297a373502ab49 100644 --- a/googletest/docs/reference/matchers.md +++ b/googletest/docs/reference/matchers.md @@ -8,9 +8,13 @@ A **matcher** matches a *single* argument. You can use it inside `ON_CALL()` or | `EXPECT_THAT(actual_value, matcher)` | Asserts that `actual_value` matches `matcher`. | | `ASSERT_THAT(actual_value, matcher)` | The same as `EXPECT_THAT(actual_value, matcher)`, except that it generates a **fatal** failure. | -{: .callout .note} -**Note:** Although equality matching via `EXPECT_THAT(actual_value, -expected_value)` is supported, prefer to make the comparison explicit via +{: .callout .warning} +**WARNING:** Equality matching via `EXPECT_THAT(actual_value, expected_value)` +is supported, however note that implicit conversions can cause surprising +results. For example, `EXPECT_THAT(some_bool, "some string")` will compile and +may pass unintentionally. + +**BEST PRACTICE:** Prefer to make the comparison explicit via `EXPECT_THAT(actual_value, Eq(expected_value))` or `EXPECT_EQ(actual_value, expected_value)`. @@ -88,16 +92,17 @@ The `argument` can be either a C string or a C++ string object: | Matcher | Description | | :---------------------- | :------------------------------------------------- | -| `ContainsRegex(string)` | `argument` matches the given regular expression. | -| `EndsWith(suffix)` | `argument` ends with string `suffix`. | -| `HasSubstr(string)` | `argument` contains `string` as a sub-string. | -| `IsEmpty()` | `argument` is an empty string. | -| `MatchesRegex(string)` | `argument` matches the given regular expression with the match starting at the first character and ending at the last character. | -| `StartsWith(prefix)` | `argument` starts with string `prefix`. | -| `StrCaseEq(string)` | `argument` is equal to `string`, ignoring case. | -| `StrCaseNe(string)` | `argument` is not equal to `string`, ignoring case. | -| `StrEq(string)` | `argument` is equal to `string`. | -| `StrNe(string)` | `argument` is not equal to `string`. | +| `ContainsRegex(string)` | `argument` matches the given regular expression. | +| `EndsWith(suffix)` | `argument` ends with string `suffix`. | +| `HasSubstr(string)` | `argument` contains `string` as a sub-string. | +| `IsEmpty()` | `argument` is an empty string. | +| `MatchesRegex(string)` | `argument` matches the given regular expression with the match starting at the first character and ending at the last character. | +| `StartsWith(prefix)` | `argument` starts with string `prefix`. | +| `StrCaseEq(string)` | `argument` is equal to `string`, ignoring case. | +| `StrCaseNe(string)` | `argument` is not equal to `string`, ignoring case. | +| `StrEq(string)` | `argument` is equal to `string`. | +| `StrNe(string)` | `argument` is not equal to `string`. | +| `WhenBase64Unescaped(m)` | `argument` is a base-64 escaped string whose unescaped string matches `m`. | `ContainsRegex()` and `MatchesRegex()` take ownership of the `RE` object. They use the regular expression syntax defined @@ -116,6 +121,7 @@ messages, you can use: | `BeginEndDistanceIs(m)` | `argument` is a container whose `begin()` and `end()` iterators are separated by a number of increments matching `m`. E.g. `BeginEndDistanceIs(2)` or `BeginEndDistanceIs(Lt(2))`. For containers that define a `size()` method, `SizeIs(m)` may be more efficient. | | `ContainerEq(container)` | The same as `Eq(container)` except that the failure message also includes which elements are in one container but not the other. | | `Contains(e)` | `argument` contains an element that matches `e`, which can be either a value or a matcher. | +| `Contains(e).Times(n)` | `argument` contains elements that match `e`, which can be either a value or a matcher, and the number of matches is `n`, which can be either a value or a matcher. Unlike the plain `Contains` and `Each` this allows to check for arbitrary occurrences including testing for absence with `Contains(e).Times(0)`. | | `Each(e)` | `argument` is a container where *every* element matches `e`, which can be either a value or a matcher. | | `ElementsAre(e0, e1, ..., en)` | `argument` has `n + 1` elements, where the *i*-th element matches `ei`, which can be a value or a matcher. | | `ElementsAreArray({e0, e1, ..., en})`, `ElementsAreArray(a_container)`, `ElementsAreArray(begin, end)`, `ElementsAreArray(array)`, or `ElementsAreArray(array, count)` | The same as `ElementsAre()` except that the expected element values/matchers come from an initializer list, STL-style container, iterator range, or C-style array. | @@ -146,7 +152,6 @@ messages, you can use: one might write: ```cpp - using ::std::get; MATCHER(FooEq, "") { return std::get<0>(arg).Equals(std::get<1>(arg)); } @@ -193,6 +198,7 @@ messages, you can use: | Matcher | Description | | :--------------- | :------------------------------------------------ | | `ResultOf(f, m)` | `f(argument)` matches matcher `m`, where `f` is a function or functor. | +| `ResultOf(result_description, f, m)` | The same as the two-parameter version, but provides a better error message. ## Pointer Matchers @@ -237,6 +243,7 @@ You can make a matcher from one or more other matchers: | `AnyOf(m1, m2, ..., mn)` | `argument` matches at least one of the matchers `m1` to `mn`. | | `AnyOfArray({m0, m1, ..., mn})`, `AnyOfArray(a_container)`, `AnyOfArray(begin, end)`, `AnyOfArray(array)`, or `AnyOfArray(array, count)` | The same as `AnyOf()` except that the matchers come from an initializer list, STL-style container, iterator range, or C-style array. | | `Not(m)` | `argument` doesn't match matcher `m`. | +| `Conditional(cond, m1, m2)` | Matches matcher `m1` if `cond` evaluates to true, else matches `m2`.| ## Adapters for Matchers @@ -259,7 +266,7 @@ which must be a permanent callback. ## Defining Matchers -| Matcher | Description | +| Macro | Description | | :----------------------------------- | :------------------------------------ | | `MATCHER(IsEven, "") { return (arg % 2) == 0; }` | Defines a matcher `IsEven()` to match an even number. | | `MATCHER_P(IsDivisibleBy, n, "") { *result_listener << "where the remainder is " << (arg % n); return (arg % n) == 0; }` | Defines a matcher `IsDivisibleBy(n)` to match a number divisible by `n`. | diff --git a/googletest/docs/reference/mocking.md b/googletest/docs/reference/mocking.md index c29f71603f41367094f9e6c53db2485a9a8b5bd3..e414ffbd0dea39b9a97989f2939943a4a87362bd 100644 --- a/googletest/docs/reference/mocking.md +++ b/googletest/docs/reference/mocking.md @@ -248,7 +248,9 @@ EXPECT_CALL(my_mock, GetNumber()) .WillOnce(Return(3)); ``` -The `WillOnce` clause can be used any number of times on an expectation. +The `WillOnce` clause can be used any number of times on an expectation. Unlike +`WillRepeatedly`, the action fed to each `WillOnce` call will be called at most +once, so may be a move-only type and/or have an `&&`-qualified call operator. #### WillRepeatedly {#EXPECT_CALL.WillRepeatedly} diff --git a/googletest/docs/reference/testing.md b/googletest/docs/reference/testing.md index 554d6c95840eee3f131d33ecd7eaa4f0e68dd03b..62cdcc1c6555542856533412608e2173e7ea9a0d 100644 --- a/googletest/docs/reference/testing.md +++ b/googletest/docs/reference/testing.md @@ -109,7 +109,7 @@ namespace: | `ValuesIn(container)` or `ValuesIn(begin,end)` | Yields values from a C-style array, an STL-style container, or an iterator range `[begin, end)`. | | `Bool()` | Yields sequence `{false, true}`. | | `Combine(g1, g2, ..., gN)` | Yields as `std::tuple` *n*-tuples all combinations (Cartesian product) of the values generated by the given *n* generators `g1`, `g2`, ..., `gN`. | - +| `ConvertGenerator(g)` | Yields values generated by generator `g`, `static_cast` to `T`. | The optional last argument *`name_generator`* is a function or functor that generates custom test name suffixes based on the test parameters. The function must accept an argument of type @@ -518,8 +518,8 @@ Logs a property for the current test, test suite, or entire invocation of the test program. Only the last value for a given key is logged. The key must be a valid XML attribute name, and cannot conflict with the ones -already used by GoogleTest (`name`, `status`, `time`, `classname`, `type_param`, -and `value_param`). +already used by GoogleTest (`name`, `file`, `line`, `status`, `time`, +`classname`, `type_param`, and `value_param`). `RecordProperty` is `public static` so it can be called from utility functions that are not members of the test fixture. diff --git a/googletest/docs/samples.md b/googletest/docs/samples.md index 2d97ca55b2c36b42bd8fb6d14d344fa66e82d6e5..dedc59098df5ae6a318bae5992694dc11b6daf62 100644 --- a/googletest/docs/samples.md +++ b/googletest/docs/samples.md @@ -1,7 +1,7 @@ # Googletest Samples If you're like us, you'd like to look at -[googletest samples.](https://github.com/google/googletest/tree/master/googletest/samples) +[googletest samples.](https://github.com/google/googletest/blob/main/googletest/samples) The sample directory has a number of well-commented samples showing how to use a variety of googletest features. diff --git a/googletest/googlemock/CMakeLists.txt b/googletest/googlemock/CMakeLists.txt index aedbaa382746cb27e46d353e950e82d6c926b464..5c1f0dafea8bfa9d6e3af07508437b29f4e7489f 100644 --- a/googletest/googlemock/CMakeLists.txt +++ b/googletest/googlemock/CMakeLists.txt @@ -94,7 +94,6 @@ if (MSVC) src/gmock-all.cc src/gmock_main.cc) else() - cxx_library(gmock "${cxx_strict}" src/gmock-all.cc) target_link_libraries(gmock PUBLIC gtest) set_target_properties(gmock PROPERTIES VERSION ${GOOGLETEST_VERSION}) @@ -106,11 +105,12 @@ endif() # to the targets for when we are part of a parent build (ie being pulled # in via add_subdirectory() rather than being a standalone build). if (DEFINED CMAKE_VERSION AND NOT "${CMAKE_VERSION}" VERSION_LESS "2.8.11") + string(REPLACE ";" "$" dirs "${gmock_build_include_dirs}") target_include_directories(gmock SYSTEM INTERFACE - "$" + "$" "$/${CMAKE_INSTALL_INCLUDEDIR}>") target_include_directories(gmock_main SYSTEM INTERFACE - "$" + "$" "$/${CMAKE_INSTALL_INCLUDEDIR}>") endif() @@ -151,7 +151,10 @@ if (gmock_build_tests) cxx_test(gmock_ex_test gmock_main) cxx_test(gmock-function-mocker_test gmock_main) cxx_test(gmock-internal-utils_test gmock_main) - cxx_test(gmock-matchers_test gmock_main) + cxx_test(gmock-matchers-arithmetic_test gmock_main) + cxx_test(gmock-matchers-comparisons_test gmock_main) + cxx_test(gmock-matchers-containers_test gmock_main) + cxx_test(gmock-matchers-misc_test gmock_main) cxx_test(gmock-more-actions_test gmock_main) cxx_test(gmock-nice-strict_test gmock_main) cxx_test(gmock-port_test gmock_main) diff --git a/googletest/googlemock/README.md b/googletest/googlemock/README.md index ead688325d2c603575148543bd0f1b136412c207..7da60655dba8b8e91ec66a9a65f97139af03ee9b 100644 --- a/googletest/googlemock/README.md +++ b/googletest/googlemock/README.md @@ -35,10 +35,6 @@ Details and examples can be found here: * [gMock Cookbook](https://google.github.io/googletest/gmock_cook_book.html) * [gMock Cheat Sheet](https://google.github.io/googletest/gmock_cheat_sheet.html) -Please note that code under scripts/generator/ is from the -[cppclean project](http://code.google.com/p/cppclean/) and under the Apache -License, which is different from GoogleMock's license. - GoogleMock is a part of [GoogleTest C++ testing framework](http://github.com/google/googletest/) and a subject to the same requirements. diff --git a/googletest/googlemock/include/gmock/gmock-actions.h b/googletest/googlemock/include/gmock/gmock-actions.h index f2393bd3afadaba8506261b18a32040395a28267..aad07d51cc1a26f0b55d12633c374b45b2eff49d 100644 --- a/googletest/googlemock/include/gmock/gmock-actions.h +++ b/googletest/googlemock/include/gmock/gmock-actions.h @@ -27,7 +27,6 @@ // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - // Google Mock - a framework for writing C++ mock classes. // // The ACTION* family of macros can be used in a namespace scope to @@ -123,15 +122,16 @@ // MORE INFORMATION: // // To learn more about using these macros, please search for 'ACTION' on -// https://github.com/google/googletest/blob/master/docs/gmock_cook_book.md +// https://github.com/google/googletest/blob/main/docs/gmock_cook_book.md -// GOOGLETEST_CM0002 DO NOT DELETE +// IWYU pragma: private, include "gmock/gmock.h" +// IWYU pragma: friend gmock/.* #ifndef GOOGLEMOCK_INCLUDE_GMOCK_GMOCK_ACTIONS_H_ #define GOOGLEMOCK_INCLUDE_GMOCK_GMOCK_ACTIONS_H_ #ifndef _WIN32_WCE -# include +#include #endif #include @@ -147,8 +147,8 @@ #include "gmock/internal/gmock-pp.h" #ifdef _MSC_VER -# pragma warning(push) -# pragma warning(disable:4100) +#pragma warning(push) +#pragma warning(disable : 4100) #endif namespace testing { @@ -196,9 +196,7 @@ class BuiltInDefaultValue { public: // This function returns true if and only if type T has a built-in default // value. - static bool Exists() { - return ::std::is_default_constructible::value; - } + static bool Exists() { return ::std::is_default_constructible::value; } static T Get() { return BuiltInDefaultValueGetter< @@ -227,11 +225,11 @@ class BuiltInDefaultValue { // The following specializations define the default values for // specific types we care about. #define GMOCK_DEFINE_DEFAULT_ACTION_FOR_RETURN_TYPE_(type, value) \ - template <> \ - class BuiltInDefaultValue { \ - public: \ - static bool Exists() { return true; } \ - static type Get() { return value; } \ + template <> \ + class BuiltInDefaultValue { \ + public: \ + static bool Exists() { return true; } \ + static type Get() { return value; } \ } GMOCK_DEFINE_DEFAULT_ACTION_FOR_RETURN_TYPE_(void, ); // NOLINT @@ -255,21 +253,309 @@ GMOCK_DEFINE_DEFAULT_ACTION_FOR_RETURN_TYPE_(unsigned short, 0U); // NOLINT GMOCK_DEFINE_DEFAULT_ACTION_FOR_RETURN_TYPE_(signed short, 0); // NOLINT GMOCK_DEFINE_DEFAULT_ACTION_FOR_RETURN_TYPE_(unsigned int, 0U); GMOCK_DEFINE_DEFAULT_ACTION_FOR_RETURN_TYPE_(signed int, 0); -GMOCK_DEFINE_DEFAULT_ACTION_FOR_RETURN_TYPE_(unsigned long, 0UL); // NOLINT -GMOCK_DEFINE_DEFAULT_ACTION_FOR_RETURN_TYPE_(signed long, 0L); // NOLINT +GMOCK_DEFINE_DEFAULT_ACTION_FOR_RETURN_TYPE_(unsigned long, 0UL); // NOLINT +GMOCK_DEFINE_DEFAULT_ACTION_FOR_RETURN_TYPE_(signed long, 0L); // NOLINT GMOCK_DEFINE_DEFAULT_ACTION_FOR_RETURN_TYPE_(unsigned long long, 0); // NOLINT -GMOCK_DEFINE_DEFAULT_ACTION_FOR_RETURN_TYPE_(signed long long, 0); // NOLINT +GMOCK_DEFINE_DEFAULT_ACTION_FOR_RETURN_TYPE_(signed long long, 0); // NOLINT GMOCK_DEFINE_DEFAULT_ACTION_FOR_RETURN_TYPE_(float, 0); GMOCK_DEFINE_DEFAULT_ACTION_FOR_RETURN_TYPE_(double, 0); #undef GMOCK_DEFINE_DEFAULT_ACTION_FOR_RETURN_TYPE_ -// Simple two-arg form of std::disjunction. -template -using disjunction = typename ::std::conditional::type; +// Partial implementations of metaprogramming types from the standard library +// not available in C++11. + +template +struct negation + // NOLINTNEXTLINE + : std::integral_constant {}; + +// Base case: with zero predicates the answer is always true. +template +struct conjunction : std::true_type {}; + +// With a single predicate, the answer is that predicate. +template +struct conjunction : P1 {}; + +// With multiple predicates the answer is the first predicate if that is false, +// and we recurse otherwise. +template +struct conjunction + : std::conditional, P1>::type {}; + +template +struct disjunction : std::false_type {}; + +template +struct disjunction : P1 {}; + +template +struct disjunction + // NOLINTNEXTLINE + : std::conditional, P1>::type {}; + +template +using void_t = void; + +// Detects whether an expression of type `From` can be implicitly converted to +// `To` according to [conv]. In C++17, [conv]/3 defines this as follows: +// +// An expression e can be implicitly converted to a type T if and only if +// the declaration T t=e; is well-formed, for some invented temporary +// variable t ([dcl.init]). +// +// [conv]/2 implies we can use function argument passing to detect whether this +// initialization is valid. +// +// Note that this is distinct from is_convertible, which requires this be valid: +// +// To test() { +// return declval(); +// } +// +// In particular, is_convertible doesn't give the correct answer when `To` and +// `From` are the same non-moveable type since `declval` will be an rvalue +// reference, defeating the guaranteed copy elision that would otherwise make +// this function work. +// +// REQUIRES: `From` is not cv void. +template +struct is_implicitly_convertible { + private: + // A function that accepts a parameter of type T. This can be called with type + // U successfully only if U is implicitly convertible to T. + template + static void Accept(T); + + // A function that creates a value of type T. + template + static T Make(); + + // An overload be selected when implicit conversion from T to To is possible. + template (Make()))> + static std::true_type TestImplicitConversion(int); + + // A fallback overload selected in all other cases. + template + static std::false_type TestImplicitConversion(...); + + public: + using type = decltype(TestImplicitConversion(0)); + static constexpr bool value = type::value; +}; + +// Like std::invoke_result_t from C++17, but works only for objects with call +// operators (not e.g. member function pointers, which we don't need specific +// support for in OnceAction because std::function deals with them). +template +using call_result_t = decltype(std::declval()(std::declval()...)); + +template +struct is_callable_r_impl : std::false_type {}; + +// Specialize the struct for those template arguments where call_result_t is +// well-formed. When it's not, the generic template above is chosen, resulting +// in std::false_type. +template +struct is_callable_r_impl>, R, F, Args...> + : std::conditional< + std::is_void::value, // + std::true_type, // + is_implicitly_convertible, R>>::type {}; + +// Like std::is_invocable_r from C++17, but works only for objects with call +// operators. See the note on call_result_t. +template +using is_callable_r = is_callable_r_impl; + +// Like std::as_const from C++17. +template +typename std::add_const::type& as_const(T& t) { + return t; +} } // namespace internal +// Specialized for function types below. +template +class OnceAction; + +// An action that can only be used once. +// +// This is accepted by WillOnce, which doesn't require the underlying action to +// be copy-constructible (only move-constructible), and promises to invoke it as +// an rvalue reference. This allows the action to work with move-only types like +// std::move_only_function in a type-safe manner. +// +// For example: +// +// // Assume we have some API that needs to accept a unique pointer to some +// // non-copyable object Foo. +// void AcceptUniquePointer(std::unique_ptr foo); +// +// // We can define an action that provides a Foo to that API. Because It +// // has to give away its unique pointer, it must not be called more than +// // once, so its call operator is &&-qualified. +// struct ProvideFoo { +// std::unique_ptr foo; +// +// void operator()() && { +// AcceptUniquePointer(std::move(Foo)); +// } +// }; +// +// // This action can be used with WillOnce. +// EXPECT_CALL(mock, Call) +// .WillOnce(ProvideFoo{std::make_unique(...)}); +// +// // But a call to WillRepeatedly will fail to compile. This is correct, +// // since the action cannot correctly be used repeatedly. +// EXPECT_CALL(mock, Call) +// .WillRepeatedly(ProvideFoo{std::make_unique(...)}); +// +// A less-contrived example would be an action that returns an arbitrary type, +// whose &&-qualified call operator is capable of dealing with move-only types. +template +class OnceAction final { + private: + // True iff we can use the given callable type (or lvalue reference) directly + // via StdFunctionAdaptor. + template + using IsDirectlyCompatible = internal::conjunction< + // It must be possible to capture the callable in StdFunctionAdaptor. + std::is_constructible::type, Callable>, + // The callable must be compatible with our signature. + internal::is_callable_r::type, + Args...>>; + + // True iff we can use the given callable type via StdFunctionAdaptor once we + // ignore incoming arguments. + template + using IsCompatibleAfterIgnoringArguments = internal::conjunction< + // It must be possible to capture the callable in a lambda. + std::is_constructible::type, Callable>, + // The callable must be invocable with zero arguments, returning something + // convertible to Result. + internal::is_callable_r::type>>; + + public: + // Construct from a callable that is directly compatible with our mocked + // signature: it accepts our function type's arguments and returns something + // convertible to our result type. + template ::type>>, + IsDirectlyCompatible> // + ::value, + int>::type = 0> + OnceAction(Callable&& callable) // NOLINT + : function_(StdFunctionAdaptor::type>( + {}, std::forward(callable))) {} + + // As above, but for a callable that ignores the mocked function's arguments. + template ::type>>, + // Exclude callables for which the overload above works. + // We'd rather provide the arguments if possible. + internal::negation>, + IsCompatibleAfterIgnoringArguments>::value, + int>::type = 0> + OnceAction(Callable&& callable) // NOLINT + // Call the constructor above with a callable + // that ignores the input arguments. + : OnceAction(IgnoreIncomingArguments::type>{ + std::forward(callable)}) {} + + // We are naturally copyable because we store only an std::function, but + // semantically we should not be copyable. + OnceAction(const OnceAction&) = delete; + OnceAction& operator=(const OnceAction&) = delete; + OnceAction(OnceAction&&) = default; + + // Invoke the underlying action callable with which we were constructed, + // handing it the supplied arguments. + Result Call(Args... args) && { + return function_(std::forward(args)...); + } + + private: + // An adaptor that wraps a callable that is compatible with our signature and + // being invoked as an rvalue reference so that it can be used as an + // StdFunctionAdaptor. This throws away type safety, but that's fine because + // this is only used by WillOnce, which we know calls at most once. + // + // Once we have something like std::move_only_function from C++23, we can do + // away with this. + template + class StdFunctionAdaptor final { + public: + // A tag indicating that the (otherwise universal) constructor is accepting + // the callable itself, instead of e.g. stealing calls for the move + // constructor. + struct CallableTag final {}; + + template + explicit StdFunctionAdaptor(CallableTag, F&& callable) + : callable_(std::make_shared(std::forward(callable))) {} + + // Rather than explicitly returning Result, we return whatever the wrapped + // callable returns. This allows for compatibility with existing uses like + // the following, when the mocked function returns void: + // + // EXPECT_CALL(mock_fn_, Call) + // .WillOnce([&] { + // [...] + // return 0; + // }); + // + // Such a callable can be turned into std::function. If we use an + // explicit return type of Result here then it *doesn't* work with + // std::function, because we'll get a "void function should not return a + // value" error. + // + // We need not worry about incompatible result types because the SFINAE on + // OnceAction already checks this for us. std::is_invocable_r_v itself makes + // the same allowance for void result types. + template + internal::call_result_t operator()( + ArgRefs&&... args) const { + return std::move(*callable_)(std::forward(args)...); + } + + private: + // We must put the callable on the heap so that we are copyable, which + // std::function needs. + std::shared_ptr callable_; + }; + + // An adaptor that makes a callable that accepts zero arguments callable with + // our mocked arguments. + template + struct IgnoreIncomingArguments { + internal::call_result_t operator()(Args&&...) { + return std::move(callable)(); + } + + Callable callable; + }; + + std::function function_; +}; + // When an unexpected function call is encountered, Google Mock will // let it return a default value if the user has specified one for its // return type, or if the return type has a built-in default value; @@ -339,7 +625,8 @@ class DefaultValue { private: const T value_; - GTEST_DISALLOW_COPY_AND_ASSIGN_(FixedValueProducer); + FixedValueProducer(const FixedValueProducer&) = delete; + FixedValueProducer& operator=(const FixedValueProducer&) = delete; }; class FactoryValueProducer : public ValueProducer { @@ -350,7 +637,8 @@ class DefaultValue { private: const FactoryFunction factory_; - GTEST_DISALLOW_COPY_AND_ASSIGN_(FactoryValueProducer); + FactoryValueProducer(const FactoryValueProducer&) = delete; + FactoryValueProducer& operator=(const FactoryValueProducer&) = delete; }; static ValueProducer* producer_; @@ -424,28 +712,34 @@ class ActionInterface { virtual Result Perform(const ArgumentTuple& args) = 0; private: - GTEST_DISALLOW_COPY_AND_ASSIGN_(ActionInterface); + ActionInterface(const ActionInterface&) = delete; + ActionInterface& operator=(const ActionInterface&) = delete; }; -// An Action is a copyable and IMMUTABLE (except by assignment) -// object that represents an action to be taken when a mock function -// of type F is called. The implementation of Action is just a -// std::shared_ptr to const ActionInterface. Don't inherit from Action! -// You can view an object implementing ActionInterface as a -// concrete action (including its current state), and an Action -// object as a handle to it. template -class Action { +class Action; + +// An Action is a copyable and IMMUTABLE (except by assignment) +// object that represents an action to be taken when a mock function of type +// R(Args...) is called. The implementation of Action is just a +// std::shared_ptr to const ActionInterface. Don't inherit from Action! You +// can view an object implementing ActionInterface as a concrete action +// (including its current state), and an Action object as a handle to it. +template +class Action { + private: + using F = R(Args...); + // Adapter class to allow constructing Action from a legacy ActionInterface. // New code should create Actions from functors instead. struct ActionAdapter { // Adapter must be copyable to satisfy std::function requirements. ::std::shared_ptr> impl_; - template - typename internal::Function::Result operator()(Args&&... args) { + template + typename internal::Function::Result operator()(InArgs&&... args) { return impl_->Perform( - ::std::forward_as_tuple(::std::forward(args)...)); + ::std::forward_as_tuple(::std::forward(args)...)); } }; @@ -480,7 +774,8 @@ class Action { // Action, as long as F's arguments can be implicitly converted // to Func's and Func's return type can be implicitly converted to F's. template - explicit Action(const Action& action) : fun_(action.fun_) {} + Action(const Action& action) // NOLINT + : fun_(action.fun_) {} // Returns true if and only if this is the DoDefault() action. bool IsDoDefault() const { return fun_ == nullptr; } @@ -498,6 +793,24 @@ class Action { return internal::Apply(fun_, ::std::move(args)); } + // An action can be used as a OnceAction, since it's obviously safe to call it + // once. + operator OnceAction() const { // NOLINT + // Return a OnceAction-compatible callable that calls Perform with the + // arguments it is provided. We could instead just return fun_, but then + // we'd need to handle the IsDoDefault() case separately. + struct OA { + Action action; + + R operator()(Args... args) && { + return action.Perform( + std::forward_as_tuple(std::forward(args)...)); + } + }; + + return OA{*this}; + } + private: template friend class Action; @@ -514,8 +827,8 @@ class Action { template struct IgnoreArgs { - template - Result operator()(const Args&...) const { + template + Result operator()(const InArgs&...) const { return function_impl(); } @@ -606,118 +919,198 @@ struct ByMoveWrapper { T payload; }; -// Implements the polymorphic Return(x) action, which can be used in -// any function that returns the type of x, regardless of the argument -// types. -// -// Note: The value passed into Return must be converted into -// Function::Result when this action is cast to Action rather than -// when that action is performed. This is important in scenarios like -// -// MOCK_METHOD1(Method, T(U)); -// ... -// { -// Foo foo; -// X x(&foo); -// EXPECT_CALL(mock, Method(_)).WillOnce(Return(x)); -// } -// -// In the example above the variable x holds reference to foo which leaves -// scope and gets destroyed. If copying X just copies a reference to foo, -// that copy will be left with a hanging reference. If conversion to T -// makes a copy of foo, the above code is safe. To support that scenario, we -// need to make sure that the type conversion happens inside the EXPECT_CALL -// statement, and conversion of the result of Return to Action is a -// good place for that. -// -// The real life example of the above scenario happens when an invocation -// of gtl::Container() is passed into Return. -// +// The general implementation of Return(R). Specializations follow below. template -class ReturnAction { +class ReturnAction final { public: - // Constructs a ReturnAction object from the value to be returned. - // 'value' is passed by value instead of by const reference in order - // to allow Return("string literal") to compile. - explicit ReturnAction(R value) : value_(new R(std::move(value))) {} + explicit ReturnAction(R value) : value_(std::move(value)) {} + + template >, // + negation>, // + std::is_convertible, // + std::is_move_constructible>::value>::type> + operator OnceAction() && { // NOLINT + return Impl(std::move(value_)); + } - // This template type conversion operator allows Return(x) to be - // used in ANY function that returns x's type. - template - operator Action() const { // NOLINT - // Assert statement belongs here because this is the best place to verify - // conditions on F. It produces the clearest error messages - // in most compilers. - // Impl really belongs in this scope as a local class but can't - // because MSVC produces duplicate symbols in different translation units - // in this case. Until MS fixes that bug we put Impl into the class scope - // and put the typedef both here (for use in assert statement) and - // in the Impl class. But both definitions must be the same. - typedef typename Function::Result Result; - GTEST_COMPILE_ASSERT_( - !std::is_reference::value, - use_ReturnRef_instead_of_Return_to_return_a_reference); - static_assert(!std::is_void::value, - "Can't use Return() on an action expected to return `void`."); - return Action(new Impl(value_)); + template >, // + negation>, // + std::is_convertible, // + std::is_copy_constructible>::value>::type> + operator Action() const { // NOLINT + return Impl(value_); } private: - // Implements the Return(x) action for a particular function type F. - template - class Impl : public ActionInterface { + // Implements the Return(x) action for a mock function that returns type U. + template + class Impl final { public: - typedef typename Function::Result Result; - typedef typename Function::ArgumentTuple ArgumentTuple; + // The constructor used when the return value is allowed to move from the + // input value (i.e. we are converting to OnceAction). + explicit Impl(R&& input_value) + : state_(new State(std::move(input_value))) {} - // The implicit cast is necessary when Result has more than one - // single-argument constructor (e.g. Result is std::vector) and R - // has a type conversion operator template. In that case, value_(value) - // won't compile as the compiler doesn't known which constructor of - // Result to call. ImplicitCast_ forces the compiler to convert R to - // Result without considering explicit constructors, thus resolving the - // ambiguity. value_ is then initialized using its copy constructor. - explicit Impl(const std::shared_ptr& value) - : value_before_cast_(*value), - value_(ImplicitCast_(value_before_cast_)) {} + // The constructor used when the return value is not allowed to move from + // the input value (i.e. we are converting to Action). + explicit Impl(const R& input_value) : state_(new State(input_value)) {} - Result Perform(const ArgumentTuple&) override { return value_; } + U operator()() && { return std::move(state_->value); } + U operator()() const& { return state_->value; } private: - GTEST_COMPILE_ASSERT_(!std::is_reference::value, - Result_cannot_be_a_reference_type); - // We save the value before casting just in case it is being cast to a - // wrapper type. - R value_before_cast_; - Result value_; - - GTEST_DISALLOW_COPY_AND_ASSIGN_(Impl); + // We put our state on the heap so that the compiler-generated copy/move + // constructors work correctly even when U is a reference-like type. This is + // necessary only because we eagerly create State::value (see the note on + // that symbol for details). If we instead had only the input value as a + // member then the default constructors would work fine. + // + // For example, when R is std::string and U is std::string_view, value is a + // reference to the string backed by input_value. The copy constructor would + // copy both, so that we wind up with a new input_value object (with the + // same contents) and a reference to the *old* input_value object rather + // than the new one. + struct State { + explicit State(const R& input_value_in) + : input_value(input_value_in), + // Make an implicit conversion to Result before initializing the U + // object we store, avoiding calling any explicit constructor of U + // from R. + // + // This simulates the language rules: a function with return type U + // that does `return R()` requires R to be implicitly convertible to + // U, and uses that path for the conversion, even U Result has an + // explicit constructor from R. + value(ImplicitCast_(internal::as_const(input_value))) {} + + // As above, but for the case where we're moving from the ReturnAction + // object because it's being used as a OnceAction. + explicit State(R&& input_value_in) + : input_value(std::move(input_value_in)), + // For the same reason as above we make an implicit conversion to U + // before initializing the value. + // + // Unlike above we provide the input value as an rvalue to the + // implicit conversion because this is a OnceAction: it's fine if it + // wants to consume the input value. + value(ImplicitCast_(std::move(input_value))) {} + + // A copy of the value originally provided by the user. We retain this in + // addition to the value of the mock function's result type below in case + // the latter is a reference-like type. See the std::string_view example + // in the documentation on Return. + R input_value; + + // The value we actually return, as the type returned by the mock function + // itself. + // + // We eagerly initialize this here, rather than lazily doing the implicit + // conversion automatically each time Perform is called, for historical + // reasons: in 2009-11, commit a070cbd91c (Google changelist 13540126) + // made the Action conversion operator eagerly convert the R value to + // U, but without keeping the R alive. This broke the use case discussed + // in the documentation for Return, making reference-like types such as + // std::string_view not safe to use as U where the input type R is a + // value-like type such as std::string. + // + // The example the commit gave was not very clear, nor was the issue + // thread (https://github.com/google/googlemock/issues/86), but it seems + // the worry was about reference-like input types R that flatten to a + // value-like type U when being implicitly converted. An example of this + // is std::vector::reference, which is often a proxy type with an + // reference to the underlying vector: + // + // // Helper method: have the mock function return bools according + // // to the supplied script. + // void SetActions(MockFunction& mock, + // const std::vector& script) { + // for (size_t i = 0; i < script.size(); ++i) { + // EXPECT_CALL(mock, Call(i)).WillOnce(Return(script[i])); + // } + // } + // + // TEST(Foo, Bar) { + // // Set actions using a temporary vector, whose operator[] + // // returns proxy objects that references that will be + // // dangling once the call to SetActions finishes and the + // // vector is destroyed. + // MockFunction mock; + // SetActions(mock, {false, true}); + // + // EXPECT_FALSE(mock.AsStdFunction()(0)); + // EXPECT_TRUE(mock.AsStdFunction()(1)); + // } + // + // This eager conversion helps with a simple case like this, but doesn't + // fully make these types work in general. For example the following still + // uses a dangling reference: + // + // TEST(Foo, Baz) { + // MockFunction()> mock; + // + // // Return the same vector twice, and then the empty vector + // // thereafter. + // auto action = Return(std::initializer_list{ + // "taco", "burrito", + // }); + // + // EXPECT_CALL(mock, Call) + // .WillOnce(action) + // .WillOnce(action) + // .WillRepeatedly(Return(std::vector{})); + // + // EXPECT_THAT(mock.AsStdFunction()(), + // ElementsAre("taco", "burrito")); + // EXPECT_THAT(mock.AsStdFunction()(), + // ElementsAre("taco", "burrito")); + // EXPECT_THAT(mock.AsStdFunction()(), IsEmpty()); + // } + // + U value; + }; + + const std::shared_ptr state_; }; - // Partially specialize for ByMoveWrapper. This version of ReturnAction will - // move its contents instead. - template - class Impl, F> : public ActionInterface { - public: - typedef typename Function::Result Result; - typedef typename Function::ArgumentTuple ArgumentTuple; + R value_; +}; + +// A specialization of ReturnAction when R is ByMoveWrapper for some T. +// +// This version applies the type system-defeating hack of moving from T even in +// the const call operator, checking at runtime that it isn't called more than +// once, since the user has declared their intent to do so by using ByMove. +template +class ReturnAction> final { + public: + explicit ReturnAction(ByMoveWrapper wrapper) + : state_(new State(std::move(wrapper.payload))) {} - explicit Impl(const std::shared_ptr& wrapper) - : performed_(false), wrapper_(wrapper) {} + T operator()() const { + GTEST_CHECK_(!state_->called) + << "A ByMove() action must be performed at most once."; - Result Perform(const ArgumentTuple&) override { - GTEST_CHECK_(!performed_) - << "A ByMove() action should only be performed once."; - performed_ = true; - return std::move(wrapper_->payload); - } + state_->called = true; + return std::move(state_->value); + } - private: - bool performed_; - const std::shared_ptr wrapper_; + private: + // We store our state on the heap so that we are copyable as required by + // Action, despite the fact that we are stateful and T may not be copyable. + struct State { + explicit State(T&& value_in) : value(std::move(value_in)) {} + + T value; + bool called = false; }; - const std::shared_ptr value_; + const std::shared_ptr state_; }; // Implements the ReturnNull() action. @@ -759,8 +1152,8 @@ class ReturnRefAction { // Asserts that the function return type is a reference. This // catches the user error of using ReturnRef(x) when Return(x) // should be used, and generates some helpful error message. - GTEST_COMPILE_ASSERT_(std::is_reference::value, - use_Return_instead_of_ReturnRef_to_return_a_value); + static_assert(std::is_reference::value, + "use Return instead of ReturnRef to return a value"); return Action(new Impl(ref_)); } @@ -801,9 +1194,8 @@ class ReturnRefOfCopyAction { // Asserts that the function return type is a reference. This // catches the user error of using ReturnRefOfCopy(x) when Return(x) // should be used, and generates some helpful error message. - GTEST_COMPILE_ASSERT_( - std::is_reference::value, - use_Return_instead_of_ReturnRefOfCopy_to_return_a_value); + static_assert(std::is_reference::value, + "use Return instead of ReturnRefOfCopy to return a value"); return Action(new Impl(value_)); } @@ -839,7 +1231,7 @@ class ReturnRoundRobinAction { template T operator()(Args&&...) const { - return state_->Next(); + return state_->Next(); } private: @@ -862,7 +1254,9 @@ class DoDefaultAction { // This template type conversion operator allows DoDefault() to be // used in any function. template - operator Action() const { return Action(); } // NOLINT + operator Action() const { + return Action(); + } // NOLINT }; // Implements the Assign action to set a given pointer referent to a @@ -890,8 +1284,7 @@ template class SetErrnoAndReturnAction { public: SetErrnoAndReturnAction(int errno_value, T result) - : errno_(errno_value), - result_(result) {} + : errno_(errno_value), result_(result) {} template Result Perform(const ArgumentTuple& /* args */) const { errno = errno_; @@ -1002,8 +1395,8 @@ class IgnoreResultAction { private: // Type OriginalFunction is the same as F except that its return // type is IgnoredValue. - typedef typename internal::Function::MakeResultIgnoredValue - OriginalFunction; + typedef + typename internal::Function::MakeResultIgnoredValue OriginalFunction; const Action action_; }; @@ -1013,55 +1406,243 @@ class IgnoreResultAction { template struct WithArgsAction { - InnerAction action; + InnerAction inner_action; - // The inner action could be anything convertible to Action. - // We use the conversion operator to detect the signature of the inner Action. + // The signature of the function as seen by the inner action, given an out + // action with the given result and argument types. template + using InnerSignature = + R(typename std::tuple_element>::type...); + + // Rather than a call operator, we must define conversion operators to + // particular action types. This is necessary for embedded actions like + // DoDefault(), which rely on an action conversion operators rather than + // providing a call operator because even with a particular set of arguments + // they don't have a fixed return type. + + template >...)>>::value, + int>::type = 0> + operator OnceAction() && { // NOLINT + struct OA { + OnceAction> inner_action; + + R operator()(Args&&... args) && { + return std::move(inner_action) + .Call(std::get( + std::forward_as_tuple(std::forward(args)...))...); + } + }; + + return OA{std::move(inner_action)}; + } + + template >...)>>::value, + int>::type = 0> operator Action() const { // NOLINT - using TupleType = std::tuple; - Action::type...)> - converted(action); + Action> converted(inner_action); - return [converted](Args... args) -> R { + return [converted](Args&&... args) -> R { return converted.Perform(std::forward_as_tuple( - std::get(std::forward_as_tuple(std::forward(args)...))...)); + std::get(std::forward_as_tuple(std::forward(args)...))...)); }; } }; template -struct DoAllAction { - private: +class DoAllAction; + +// Base case: only a single action. +template +class DoAllAction { + public: + struct UserConstructorTag {}; + template - using NonFinalType = - typename std::conditional::value, T, const T&>::type; + explicit DoAllAction(UserConstructorTag, T&& action) + : final_action_(std::forward(action)) {} + + // Rather than a call operator, we must define conversion operators to + // particular action types. This is necessary for embedded actions like + // DoDefault(), which rely on an action conversion operators rather than + // providing a call operator because even with a particular set of arguments + // they don't have a fixed return type. + + template >::value, + int>::type = 0> + operator OnceAction() && { // NOLINT + return std::move(final_action_); + } - template - std::vector Convert(IndexSequence) const { - return {ActionT(std::get(actions))...}; + template < + typename R, typename... Args, + typename std::enable_if< + std::is_convertible>::value, + int>::type = 0> + operator Action() const { // NOLINT + return final_action_; } + private: + FinalAction final_action_; +}; + +// Recursive case: support N actions by calling the initial action and then +// calling through to the base class containing N-1 actions. +template +class DoAllAction + : private DoAllAction { + private: + using Base = DoAllAction; + + // The type of reference that should be provided to an initial action for a + // mocked function parameter of type T. + // + // There are two quirks here: + // + // * Unlike most forwarding functions, we pass scalars through by value. + // This isn't strictly necessary because an lvalue reference would work + // fine too and be consistent with other non-reference types, but it's + // perhaps less surprising. + // + // For example if the mocked function has signature void(int), then it + // might seem surprising for the user's initial action to need to be + // convertible to Action. This is perhaps less + // surprising for a non-scalar type where there may be a performance + // impact, or it might even be impossible, to pass by value. + // + // * More surprisingly, `const T&` is often not a const reference type. + // By the reference collapsing rules in C++17 [dcl.ref]/6, if T refers to + // U& or U&& for some non-scalar type U, then InitialActionArgType is + // U&. In other words, we may hand over a non-const reference. + // + // So for example, given some non-scalar type Obj we have the following + // mappings: + // + // T InitialActionArgType + // ------- ----------------------- + // Obj const Obj& + // Obj& Obj& + // Obj&& Obj& + // const Obj const Obj& + // const Obj& const Obj& + // const Obj&& const Obj& + // + // In other words, the initial actions get a mutable view of an non-scalar + // argument if and only if the mock function itself accepts a non-const + // reference type. They are never given an rvalue reference to an + // non-scalar type. + // + // This situation makes sense if you imagine use with a matcher that is + // designed to write through a reference. For example, if the caller wants + // to fill in a reference argument and then return a canned value: + // + // EXPECT_CALL(mock, Call) + // .WillOnce(DoAll(SetArgReferee<0>(17), Return(19))); + // + template + using InitialActionArgType = + typename std::conditional::value, T, const T&>::type; + public: - std::tuple actions; + struct UserConstructorTag {}; + + template + explicit DoAllAction(UserConstructorTag, T&& initial_action, + U&&... other_actions) + : Base({}, std::forward(other_actions)...), + initial_action_(std::forward(initial_action)) {} + + template ...)>>, + std::is_convertible>>::value, + int>::type = 0> + operator OnceAction() && { // NOLINT + // Return an action that first calls the initial action with arguments + // filtered through InitialActionArgType, then forwards arguments directly + // to the base class to deal with the remaining actions. + struct OA { + OnceAction...)> initial_action; + OnceAction remaining_actions; + + R operator()(Args... args) && { + std::move(initial_action) + .Call(static_cast>(args)...); + + return std::move(remaining_actions).Call(std::forward(args)...); + } + }; - template + return OA{ + std::move(initial_action_), + std::move(static_cast(*this)), + }; + } + + template < + typename R, typename... Args, + typename std::enable_if< + conjunction< + // Both the initial action and the rest must support conversion to + // Action. + std::is_convertible...)>>, + std::is_convertible>>::value, + int>::type = 0> operator Action() const { // NOLINT - struct Op { - std::vector...)>> converted; - Action last; + // Return an action that first calls the initial action with arguments + // filtered through InitialActionArgType, then forwards arguments directly + // to the base class to deal with the remaining actions. + struct OA { + Action...)> initial_action; + Action remaining_actions; + R operator()(Args... args) const { - auto tuple_args = std::forward_as_tuple(std::forward(args)...); - for (auto& a : converted) { - a.Perform(tuple_args); - } - return last.Perform(std::move(tuple_args)); + initial_action.Perform(std::forward_as_tuple( + static_cast>(args)...)); + + return remaining_actions.Perform( + std::forward_as_tuple(std::forward(args)...)); } }; - return Op{Convert...)>>( - MakeIndexSequence()), - std::get(actions)}; + + return OA{ + initial_action_, + static_cast(*this), + }; } + + private: + InitialAction initial_action_; }; template @@ -1078,10 +1659,11 @@ struct ReturnNewAction { template struct ReturnArgAction { - template - auto operator()(const Args&... args) const -> - typename std::tuple_element>::type { - return std::get(std::tie(args...)); + template ::type> + auto operator()(Args&&... args) const -> decltype(std::get( + std::forward_as_tuple(std::forward(args)...))) { + return std::get(std::forward_as_tuple(std::forward(args)...)); } }; @@ -1203,7 +1785,8 @@ typedef internal::IgnoredValue Unused; template internal::DoAllAction::type...> DoAll( Action&&... action) { - return {std::forward_as_tuple(std::forward(action)...)}; + return internal::DoAllAction::type...>( + {}, std::forward(action)...); } // WithArg(an_action) creates an action that passes the k-th @@ -1212,8 +1795,8 @@ internal::DoAllAction::type...> DoAll( // multiple arguments. For convenience, we also provide // WithArgs(an_action) (defined below) as a synonym. template -internal::WithArgsAction::type, k> -WithArg(InnerAction&& action) { +internal::WithArgsAction::type, k> WithArg( + InnerAction&& action) { return {std::forward(action)}; } @@ -1232,14 +1815,35 @@ WithArgs(InnerAction&& action) { // argument. In other words, it adapts an action accepting no // argument to one that accepts (and ignores) arguments. template -internal::WithArgsAction::type> -WithoutArgs(InnerAction&& action) { +internal::WithArgsAction::type> WithoutArgs( + InnerAction&& action) { return {std::forward(action)}; } -// Creates an action that returns 'value'. 'value' is passed by value -// instead of const reference - otherwise Return("string literal") -// will trigger a compiler error about using array as initializer. +// Creates an action that returns a value. +// +// The returned type can be used with a mock function returning a non-void, +// non-reference type U as follows: +// +// * If R is convertible to U and U is move-constructible, then the action can +// be used with WillOnce. +// +// * If const R& is convertible to U and U is copy-constructible, then the +// action can be used with both WillOnce and WillRepeatedly. +// +// The mock expectation contains the R value from which the U return value is +// constructed (a move/copy of the argument to Return). This means that the R +// value will survive at least until the mock object's expectations are cleared +// or the mock object is destroyed, meaning that U can safely be a +// reference-like type such as std::string_view: +// +// // The mock function returns a view of a copy of the string fed to +// // Return. The view is valid even after the action is performed. +// MockFunction mock; +// EXPECT_CALL(mock, Call).WillOnce(Return(std::string("taco"))); +// const std::string_view result = mock.AsStdFunction()(); +// EXPECT_EQ("taco", result); +// template internal::ReturnAction Return(R value) { return internal::ReturnAction(std::move(value)); @@ -1273,6 +1877,8 @@ inline internal::ReturnRefOfCopyAction ReturnRefOfCopy(const R& x) { return internal::ReturnRefOfCopyAction(x); } +// DEPRECATED: use Return(x) directly with WillOnce. +// // Modifies the parent action (a Return() action) to perform a move of the // argument instead of a copy. // Return(ByMove()) actions can only be executed once and will assert this @@ -1319,7 +1925,7 @@ internal::SetArgumentPointeeAction SetArgumentPointee(T value) { // Creates an action that sets a pointer referent to a given value. template -PolymorphicAction > Assign(T1* ptr, T2 val) { +PolymorphicAction> Assign(T1* ptr, T2 val) { return MakePolymorphicAction(internal::AssignAction(ptr, val)); } @@ -1327,8 +1933,8 @@ PolymorphicAction > Assign(T1* ptr, T2 val) { // Creates an action that sets errno and returns the appropriate error. template -PolymorphicAction > -SetErrnoAndReturn(int errval, T result) { +PolymorphicAction> SetErrnoAndReturn( + int errval, T result) { return MakePolymorphicAction( internal::SetErrnoAndReturnAction(errval, result)); } @@ -1482,7 +2088,8 @@ struct ExcessiveArg {}; // Builds an implementation of an Action<> for some particular signature, using // a class defined by an ACTION* macro. -template struct ActionImpl; +template +struct ActionImpl; template struct ImplBase { @@ -1502,7 +2109,7 @@ struct ActionImpl : ImplBase::type { using args_type = std::tuple; ActionImpl() = default; // Only defined if appropriate for Base. - explicit ActionImpl(std::shared_ptr impl) : Base{std::move(impl)} { } + explicit ActionImpl(std::shared_ptr impl) : Base{std::move(impl)} {} R operator()(Args&&... arg) const { static constexpr size_t kMaxArgs = @@ -1521,12 +2128,14 @@ struct ActionImpl : ImplBase::type { // args_type get passed, followed by a dummy of unspecified type for the // remainder up to 10 explicit args. static constexpr ExcessiveArg kExcessArg{}; - return static_cast(*this).template gmock_PerformImpl< - /*function_type=*/function_type, /*return_type=*/R, - /*args_type=*/args_type, - /*argN_type=*/typename std::tuple_element::type...>( - /*args=*/args, std::get(args)..., - ((void)excess_id, kExcessArg)...); + return static_cast(*this) + .template gmock_PerformImpl< + /*function_type=*/function_type, /*return_type=*/R, + /*args_type=*/args_type, + /*argN_type=*/ + typename std::tuple_element::type...>( + /*args=*/args, std::get(args)..., + ((void)excess_id, kExcessArg)...); } }; @@ -1545,7 +2154,7 @@ template #define GMOCK_INTERNAL_ARG_UNUSED(i, data, el) \ , const arg##i##_type& arg##i GTEST_ATTRIBUTE_UNUSED_ -#define GMOCK_ACTION_ARG_TYPES_AND_NAMES_UNUSED_ \ +#define GMOCK_ACTION_ARG_TYPES_AND_NAMES_UNUSED_ \ const args_type& args GTEST_ATTRIBUTE_UNUSED_ GMOCK_PP_REPEAT( \ GMOCK_INTERNAL_ARG_UNUSED, , 10) @@ -1584,42 +2193,47 @@ template #define GMOCK_ACTION_FIELD_PARAMS_(params) \ GMOCK_PP_FOR_EACH(GMOCK_INTERNAL_FIELD_PARAM, , params) -#define GMOCK_INTERNAL_ACTION(name, full_name, params) \ - template \ - class full_name { \ - public: \ - explicit full_name(GMOCK_ACTION_TYPE_GVALUE_PARAMS_(params)) \ - : impl_(std::make_shared( \ - GMOCK_ACTION_GVALUE_PARAMS_(params))) { } \ - full_name(const full_name&) = default; \ - full_name(full_name&&) noexcept = default; \ - template \ - operator ::testing::Action() const { \ - return ::testing::internal::MakeAction(impl_); \ - } \ - private: \ - class gmock_Impl { \ - public: \ - explicit gmock_Impl(GMOCK_ACTION_TYPE_GVALUE_PARAMS_(params)) \ - : GMOCK_ACTION_INIT_PARAMS_(params) {} \ - template \ - return_type gmock_PerformImpl(GMOCK_ACTION_ARG_TYPES_AND_NAMES_) const; \ - GMOCK_ACTION_FIELD_PARAMS_(params) \ - }; \ - std::shared_ptr impl_; \ - }; \ - template \ - inline full_name name( \ - GMOCK_ACTION_TYPE_GVALUE_PARAMS_(params)) { \ - return full_name( \ - GMOCK_ACTION_GVALUE_PARAMS_(params)); \ - } \ - template \ - template \ - return_type full_name::gmock_Impl:: \ - gmock_PerformImpl(GMOCK_ACTION_ARG_TYPES_AND_NAMES_UNUSED_) const +#define GMOCK_INTERNAL_ACTION(name, full_name, params) \ + template \ + class full_name { \ + public: \ + explicit full_name(GMOCK_ACTION_TYPE_GVALUE_PARAMS_(params)) \ + : impl_(std::make_shared( \ + GMOCK_ACTION_GVALUE_PARAMS_(params))) {} \ + full_name(const full_name&) = default; \ + full_name(full_name&&) noexcept = default; \ + template \ + operator ::testing::Action() const { \ + return ::testing::internal::MakeAction(impl_); \ + } \ + \ + private: \ + class gmock_Impl { \ + public: \ + explicit gmock_Impl(GMOCK_ACTION_TYPE_GVALUE_PARAMS_(params)) \ + : GMOCK_ACTION_INIT_PARAMS_(params) {} \ + template \ + return_type gmock_PerformImpl(GMOCK_ACTION_ARG_TYPES_AND_NAMES_) const; \ + GMOCK_ACTION_FIELD_PARAMS_(params) \ + }; \ + std::shared_ptr impl_; \ + }; \ + template \ + inline full_name name( \ + GMOCK_ACTION_TYPE_GVALUE_PARAMS_(params)) GTEST_MUST_USE_RESULT_; \ + template \ + inline full_name name( \ + GMOCK_ACTION_TYPE_GVALUE_PARAMS_(params)) { \ + return full_name( \ + GMOCK_ACTION_GVALUE_PARAMS_(params)); \ + } \ + template \ + template \ + return_type \ + full_name::gmock_Impl::gmock_PerformImpl( \ + GMOCK_ACTION_ARG_TYPES_AND_NAMES_UNUSED_) const } // namespace internal @@ -1627,12 +2241,13 @@ template #define ACTION(name) \ class name##Action { \ public: \ - explicit name##Action() noexcept {} \ - name##Action(const name##Action&) noexcept {} \ + explicit name##Action() noexcept {} \ + name##Action(const name##Action&) noexcept {} \ template \ operator ::testing::Action() const { \ return ::testing::internal::MakeAction(); \ } \ + \ private: \ class gmock_Impl { \ public: \ @@ -1681,7 +2296,7 @@ template } // namespace testing #ifdef _MSC_VER -# pragma warning(pop) +#pragma warning(pop) #endif #endif // GOOGLEMOCK_INCLUDE_GMOCK_GMOCK_ACTIONS_H_ diff --git a/googletest/googlemock/include/gmock/gmock-cardinalities.h b/googletest/googlemock/include/gmock/gmock-cardinalities.h index fc7f803a7a6515c21e3fbf9b505b0a76e8b9c670..b6ab648e50a649257120e62fdc404e8e5ba2c1d9 100644 --- a/googletest/googlemock/include/gmock/gmock-cardinalities.h +++ b/googletest/googlemock/include/gmock/gmock-cardinalities.h @@ -27,21 +27,23 @@ // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - // Google Mock - a framework for writing C++ mock classes. // // This file implements some commonly used cardinalities. More // cardinalities can be defined by the user implementing the // CardinalityInterface interface if necessary. -// GOOGLETEST_CM0002 DO NOT DELETE +// IWYU pragma: private, include "gmock/gmock.h" +// IWYU pragma: friend gmock/.* #ifndef GOOGLEMOCK_INCLUDE_GMOCK_GMOCK_CARDINALITIES_H_ #define GOOGLEMOCK_INCLUDE_GMOCK_GMOCK_CARDINALITIES_H_ #include + #include #include // NOLINT + #include "gmock/internal/gmock-port.h" #include "gtest/gtest.h" @@ -116,7 +118,7 @@ class GTEST_API_ Cardinality { // cardinality, i.e. exceed the maximum number of allowed calls. bool IsOverSaturatedByCallCount(int call_count) const { return impl_->IsSaturatedByCallCount(call_count) && - !impl_->IsSatisfiedByCallCount(call_count); + !impl_->IsSatisfiedByCallCount(call_count); } // Describes self to an ostream diff --git a/googletest/googlemock/include/gmock/gmock-function-mocker.h b/googletest/googlemock/include/gmock/gmock-function-mocker.h index 0fc6f6f3f13ccdaf94a4d055783879a57dcf8dc5..9edfd9d52a401c44cc7d13afa1c5f52b82b64d6b 100644 --- a/googletest/googlemock/include/gmock/gmock-function-mocker.h +++ b/googletest/googlemock/include/gmock/gmock-function-mocker.h @@ -31,10 +31,11 @@ // // This file implements MOCK_METHOD. -// GOOGLETEST_CM0002 DO NOT DELETE +// IWYU pragma: private, include "gmock/gmock.h" +// IWYU pragma: friend gmock/.* -#ifndef GOOGLEMOCK_INCLUDE_GMOCK_INTERNAL_GMOCK_FUNCTION_MOCKER_H_ // NOLINT -#define GOOGLEMOCK_INCLUDE_GMOCK_INTERNAL_GMOCK_FUNCTION_MOCKER_H_ // NOLINT +#ifndef GOOGLEMOCK_INCLUDE_GMOCK_GMOCK_FUNCTION_MOCKER_H_ +#define GOOGLEMOCK_INCLUDE_GMOCK_GMOCK_FUNCTION_MOCKER_H_ #include // IWYU pragma: keep #include // IWYU pragma: keep @@ -64,6 +65,39 @@ struct ThisRefAdjuster { } }; +constexpr bool PrefixOf(const char* a, const char* b) { + return *a == 0 || (*a == *b && internal::PrefixOf(a + 1, b + 1)); +} + +template +constexpr bool StartsWith(const char (&prefix)[N], const char (&str)[M]) { + return N <= M && internal::PrefixOf(prefix, str); +} + +template +constexpr bool EndsWith(const char (&suffix)[N], const char (&str)[M]) { + return N <= M && internal::PrefixOf(suffix, str + M - N); +} + +template +constexpr bool Equals(const char (&a)[N], const char (&b)[M]) { + return N == M && internal::PrefixOf(a, b); +} + +template +constexpr bool ValidateSpec(const char (&spec)[N]) { + return internal::Equals("const", spec) || + internal::Equals("override", spec) || + internal::Equals("final", spec) || + internal::Equals("noexcept", spec) || + (internal::StartsWith("noexcept(", spec) && + internal::EndsWith(")", spec)) || + internal::Equals("ref(&)", spec) || + internal::Equals("ref(&&)", spec) || + (internal::StartsWith("Calltype(", spec) && + internal::EndsWith(")", spec)); +} + } // namespace internal // The style guide prohibits "using" statements in a namespace scope @@ -74,8 +108,11 @@ struct ThisRefAdjuster { using internal::FunctionMocker; } // namespace testing -#define MOCK_METHOD(...) \ - GMOCK_PP_VARIADIC_CALL(GMOCK_INTERNAL_MOCK_METHOD_ARG_, __VA_ARGS__) +#define MOCK_METHOD(...) \ + GMOCK_INTERNAL_WARNING_PUSH() \ + GMOCK_INTERNAL_WARNING_CLANG(ignored, "-Wunused-member-function") \ + GMOCK_PP_VARIADIC_CALL(GMOCK_INTERNAL_MOCK_METHOD_ARG_, __VA_ARGS__) \ + GMOCK_INTERNAL_WARNING_POP() #define GMOCK_INTERNAL_MOCK_METHOD_ARG_1(...) \ GMOCK_INTERNAL_WRONG_ARITY(__VA_ARGS__) @@ -86,17 +123,18 @@ using internal::FunctionMocker; #define GMOCK_INTERNAL_MOCK_METHOD_ARG_3(_Ret, _MethodName, _Args) \ GMOCK_INTERNAL_MOCK_METHOD_ARG_4(_Ret, _MethodName, _Args, ()) -#define GMOCK_INTERNAL_MOCK_METHOD_ARG_4(_Ret, _MethodName, _Args, _Spec) \ - GMOCK_INTERNAL_ASSERT_PARENTHESIS(_Args); \ - GMOCK_INTERNAL_ASSERT_PARENTHESIS(_Spec); \ - GMOCK_INTERNAL_ASSERT_VALID_SIGNATURE( \ - GMOCK_PP_NARG0 _Args, GMOCK_INTERNAL_SIGNATURE(_Ret, _Args)); \ - GMOCK_INTERNAL_ASSERT_VALID_SPEC(_Spec) \ - GMOCK_INTERNAL_MOCK_METHOD_IMPL( \ - GMOCK_PP_NARG0 _Args, _MethodName, GMOCK_INTERNAL_HAS_CONST(_Spec), \ - GMOCK_INTERNAL_HAS_OVERRIDE(_Spec), GMOCK_INTERNAL_HAS_FINAL(_Spec), \ - GMOCK_INTERNAL_GET_NOEXCEPT_SPEC(_Spec), \ - GMOCK_INTERNAL_GET_CALLTYPE(_Spec), GMOCK_INTERNAL_GET_REF_SPEC(_Spec), \ +#define GMOCK_INTERNAL_MOCK_METHOD_ARG_4(_Ret, _MethodName, _Args, _Spec) \ + GMOCK_INTERNAL_ASSERT_PARENTHESIS(_Args); \ + GMOCK_INTERNAL_ASSERT_PARENTHESIS(_Spec); \ + GMOCK_INTERNAL_ASSERT_VALID_SIGNATURE( \ + GMOCK_PP_NARG0 _Args, GMOCK_INTERNAL_SIGNATURE(_Ret, _Args)); \ + GMOCK_INTERNAL_ASSERT_VALID_SPEC(_Spec) \ + GMOCK_INTERNAL_MOCK_METHOD_IMPL( \ + GMOCK_PP_NARG0 _Args, _MethodName, GMOCK_INTERNAL_HAS_CONST(_Spec), \ + GMOCK_INTERNAL_HAS_OVERRIDE(_Spec), GMOCK_INTERNAL_HAS_FINAL(_Spec), \ + GMOCK_INTERNAL_GET_NOEXCEPT_SPEC(_Spec), \ + GMOCK_INTERNAL_GET_CALLTYPE_SPEC(_Spec), \ + GMOCK_INTERNAL_GET_REF_SPEC(_Spec), \ (GMOCK_INTERNAL_SIGNATURE(_Ret, _Args))) #define GMOCK_INTERNAL_MOCK_METHOD_ARG_5(...) \ @@ -166,11 +204,11 @@ using internal::FunctionMocker; GMOCK_INTERNAL_A_MATCHER_ARGUMENT, _Signature, _N)); \ } \ mutable ::testing::FunctionMocker \ - GMOCK_MOCKER_(_N, _Constness, _MethodName) + GMOCK_MOCKER_(_N, _Constness, _MethodName) #define GMOCK_INTERNAL_EXPAND(...) __VA_ARGS__ -// Five Valid modifiers. +// Valid modifiers. #define GMOCK_INTERNAL_HAS_CONST(_Tuple) \ GMOCK_PP_HAS_COMMA(GMOCK_PP_FOR_EACH(GMOCK_INTERNAL_DETECT_CONST, ~, _Tuple)) @@ -189,6 +227,14 @@ using internal::FunctionMocker; GMOCK_PP_HAS_COMMA(GMOCK_INTERNAL_DETECT_NOEXCEPT(_i, _, _elem)), \ _elem, ) +#define GMOCK_INTERNAL_GET_CALLTYPE_SPEC(_Tuple) \ + GMOCK_PP_FOR_EACH(GMOCK_INTERNAL_CALLTYPE_SPEC_IF_CALLTYPE, ~, _Tuple) + +#define GMOCK_INTERNAL_CALLTYPE_SPEC_IF_CALLTYPE(_i, _, _elem) \ + GMOCK_PP_IF( \ + GMOCK_PP_HAS_COMMA(GMOCK_INTERNAL_DETECT_CALLTYPE(_i, _, _elem)), \ + GMOCK_PP_CAT(GMOCK_INTERNAL_UNPACK_, _elem), ) + #define GMOCK_INTERNAL_GET_REF_SPEC(_Tuple) \ GMOCK_PP_FOR_EACH(GMOCK_INTERNAL_REF_SPEC_IF_REF, ~, _Tuple) @@ -196,19 +242,25 @@ using internal::FunctionMocker; GMOCK_PP_IF(GMOCK_PP_HAS_COMMA(GMOCK_INTERNAL_DETECT_REF(_i, _, _elem)), \ GMOCK_PP_CAT(GMOCK_INTERNAL_UNPACK_, _elem), ) -#define GMOCK_INTERNAL_GET_CALLTYPE(_Tuple) \ - GMOCK_PP_FOR_EACH(GMOCK_INTERNAL_GET_CALLTYPE_IMPL, ~, _Tuple) - -#define GMOCK_INTERNAL_ASSERT_VALID_SPEC_ELEMENT(_i, _, _elem) \ - static_assert( \ - (GMOCK_PP_HAS_COMMA(GMOCK_INTERNAL_DETECT_CONST(_i, _, _elem)) + \ - GMOCK_PP_HAS_COMMA(GMOCK_INTERNAL_DETECT_OVERRIDE(_i, _, _elem)) + \ - GMOCK_PP_HAS_COMMA(GMOCK_INTERNAL_DETECT_FINAL(_i, _, _elem)) + \ - GMOCK_PP_HAS_COMMA(GMOCK_INTERNAL_DETECT_NOEXCEPT(_i, _, _elem)) + \ - GMOCK_PP_HAS_COMMA(GMOCK_INTERNAL_DETECT_REF(_i, _, _elem)) + \ - GMOCK_INTERNAL_IS_CALLTYPE(_elem)) == 1, \ - GMOCK_PP_STRINGIZE( \ +#ifdef GMOCK_INTERNAL_STRICT_SPEC_ASSERT +#define GMOCK_INTERNAL_ASSERT_VALID_SPEC_ELEMENT(_i, _, _elem) \ + static_assert( \ + ::testing::internal::ValidateSpec(GMOCK_PP_STRINGIZE(_elem)), \ + "Token \'" GMOCK_PP_STRINGIZE( \ + _elem) "\' cannot be recognized as a valid specification " \ + "modifier. Is a ',' missing?"); +#else +#define GMOCK_INTERNAL_ASSERT_VALID_SPEC_ELEMENT(_i, _, _elem) \ + static_assert( \ + (GMOCK_PP_HAS_COMMA(GMOCK_INTERNAL_DETECT_CONST(_i, _, _elem)) + \ + GMOCK_PP_HAS_COMMA(GMOCK_INTERNAL_DETECT_OVERRIDE(_i, _, _elem)) + \ + GMOCK_PP_HAS_COMMA(GMOCK_INTERNAL_DETECT_FINAL(_i, _, _elem)) + \ + GMOCK_PP_HAS_COMMA(GMOCK_INTERNAL_DETECT_NOEXCEPT(_i, _, _elem)) + \ + GMOCK_PP_HAS_COMMA(GMOCK_INTERNAL_DETECT_REF(_i, _, _elem)) + \ + GMOCK_PP_HAS_COMMA(GMOCK_INTERNAL_DETECT_CALLTYPE(_i, _, _elem))) == 1, \ + GMOCK_PP_STRINGIZE( \ _elem) " cannot be recognized as a valid specification modifier."); +#endif // GMOCK_INTERNAL_STRICT_SPEC_ASSERT // Modifiers implementation. #define GMOCK_INTERNAL_DETECT_CONST(_i, _, _elem) \ @@ -238,26 +290,12 @@ using internal::FunctionMocker; #define GMOCK_INTERNAL_UNPACK_ref(x) x -#define GMOCK_INTERNAL_GET_CALLTYPE_IMPL(_i, _, _elem) \ - GMOCK_PP_IF(GMOCK_INTERNAL_IS_CALLTYPE(_elem), \ - GMOCK_INTERNAL_GET_VALUE_CALLTYPE, GMOCK_PP_EMPTY) \ - (_elem) - -// TODO(iserna): GMOCK_INTERNAL_IS_CALLTYPE and -// GMOCK_INTERNAL_GET_VALUE_CALLTYPE needed more expansions to work on windows -// maybe they can be simplified somehow. -#define GMOCK_INTERNAL_IS_CALLTYPE(_arg) \ - GMOCK_INTERNAL_IS_CALLTYPE_I( \ - GMOCK_PP_CAT(GMOCK_INTERNAL_IS_CALLTYPE_HELPER_, _arg)) -#define GMOCK_INTERNAL_IS_CALLTYPE_I(_arg) GMOCK_PP_IS_ENCLOSED_PARENS(_arg) +#define GMOCK_INTERNAL_DETECT_CALLTYPE(_i, _, _elem) \ + GMOCK_PP_CAT(GMOCK_INTERNAL_DETECT_CALLTYPE_I_, _elem) -#define GMOCK_INTERNAL_GET_VALUE_CALLTYPE(_arg) \ - GMOCK_INTERNAL_GET_VALUE_CALLTYPE_I( \ - GMOCK_PP_CAT(GMOCK_INTERNAL_IS_CALLTYPE_HELPER_, _arg)) -#define GMOCK_INTERNAL_GET_VALUE_CALLTYPE_I(_arg) \ - GMOCK_PP_IDENTITY _arg +#define GMOCK_INTERNAL_DETECT_CALLTYPE_I_Calltype , -#define GMOCK_INTERNAL_IS_CALLTYPE_HELPER_Calltype +#define GMOCK_INTERNAL_UNPACK_Calltype(...) __VA_ARGS__ // Note: The use of `identity_t` here allows _Ret to represent return types that // would normally need to be specified in a different way. For example, a method @@ -326,6 +364,8 @@ using internal::FunctionMocker; #define MOCK_METHOD9(m, ...) GMOCK_INTERNAL_MOCK_METHODN(, , m, 9, __VA_ARGS__) #define MOCK_METHOD10(m, ...) \ GMOCK_INTERNAL_MOCK_METHODN(, , m, 10, __VA_ARGS__) +#define MOCK_METHOD11(m, ...) \ + GMOCK_INTERNAL_MOCK_METHODN(, , m, 11, __VA_ARGS__) #define MOCK_CONST_METHOD0(m, ...) \ GMOCK_INTERNAL_MOCK_METHODN(const, , m, 0, __VA_ARGS__) @@ -476,4 +516,4 @@ using internal::FunctionMocker; #define GMOCK_MOCKER_(arity, constness, Method) \ GTEST_CONCAT_TOKEN_(gmock##constness##arity##_##Method##_, __LINE__) -#endif // GOOGLEMOCK_INCLUDE_GMOCK_INTERNAL_GMOCK_FUNCTION_MOCKER_H_ +#endif // GOOGLEMOCK_INCLUDE_GMOCK_GMOCK_FUNCTION_MOCKER_H_ diff --git a/googletest/googlemock/include/gmock/gmock-matchers.h b/googletest/googlemock/include/gmock/gmock-matchers.h index 86be9c176ebcaf8e8e373626d851f4be2f4687c9..9e634f7f1c47b267c2e2ddf5392445cb393ab669 100644 --- a/googletest/googlemock/include/gmock/gmock-matchers.h +++ b/googletest/googlemock/include/gmock/gmock-matchers.h @@ -27,7 +27,6 @@ // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - // Google Mock - a framework for writing C++ mock classes. // // The MATCHER* family of macros can be used in a namespace scope to @@ -241,7 +240,7 @@ // // To learn more about using these macros, please search for 'MATCHER' // on -// https://github.com/google/googletest/blob/master/docs/gmock_cook_book.md +// https://github.com/google/googletest/blob/main/docs/gmock_cook_book.md // // This file also implements some commonly used argument matchers. More // matchers can be defined by the user implementing the @@ -250,7 +249,8 @@ // See googletest/include/gtest/gtest-matchers.h for the definition of class // Matcher, class MatcherInterface, and others. -// GOOGLETEST_CM0002 DO NOT DELETE +// IWYU pragma: private, include "gmock/gmock.h" +// IWYU pragma: friend gmock/.* #ifndef GOOGLEMOCK_INCLUDE_GMOCK_GMOCK_MATCHERS_H_ #define GOOGLEMOCK_INCLUDE_GMOCK_GMOCK_MATCHERS_H_ @@ -258,6 +258,7 @@ #include #include #include +#include #include #include #include @@ -313,7 +314,9 @@ class StringMatchResultListener : public MatchResultListener { private: ::std::stringstream ss_; - GTEST_DISALLOW_COPY_AND_ASSIGN_(StringMatchResultListener); + StringMatchResultListener(const StringMatchResultListener&) = delete; + StringMatchResultListener& operator=(const StringMatchResultListener&) = + delete; }; // Anything inside the 'internal' namespace IS INTERNAL IMPLEMENTATION @@ -396,7 +399,7 @@ class MatcherCastImpl { // is already a Matcher. This only compiles when type T can be // statically converted to type U. template -class MatcherCastImpl > { +class MatcherCastImpl> { public: static Matcher Cast(const Matcher& source_matcher) { return Matcher(new Impl(source_matcher)); @@ -450,7 +453,7 @@ class MatcherCastImpl > { // This even more specialized version is used for efficiently casting // a matcher to its own type. template -class MatcherCastImpl > { +class MatcherCastImpl> { public: static Matcher Cast(const Matcher& matcher) { return matcher; } }; @@ -533,19 +536,18 @@ inline Matcher SafeMatcherCast(const Matcher& matcher) { "T must be implicitly convertible to U"); // Enforce that we are not converting a non-reference type T to a reference // type U. - GTEST_COMPILE_ASSERT_( - std::is_reference::value || !std::is_reference::value, - cannot_convert_non_reference_arg_to_reference); + static_assert(std::is_reference::value || !std::is_reference::value, + "cannot convert non reference arg to reference"); // In case both T and U are arithmetic types, enforce that the // conversion is not lossy. typedef GTEST_REMOVE_REFERENCE_AND_CONST_(T) RawT; typedef GTEST_REMOVE_REFERENCE_AND_CONST_(U) RawU; constexpr bool kTIsOther = GMOCK_KIND_OF_(RawT) == internal::kOther; constexpr bool kUIsOther = GMOCK_KIND_OF_(RawU) == internal::kOther; - GTEST_COMPILE_ASSERT_( + static_assert( kTIsOther || kUIsOther || - (internal::LosslessArithmeticConvertible::value), - conversion_of_arithmetic_types_must_be_lossless); + (internal::LosslessArithmeticConvertible::value), + "conversion of arithmetic types must be lossless"); return MatcherCast(matcher); } @@ -678,9 +680,9 @@ bool TupleMatches(const MatcherTuple& matcher_tuple, const ValueTuple& value_tuple) { // Makes sure that matcher_tuple and value_tuple have the same // number of fields. - GTEST_COMPILE_ASSERT_(std::tuple_size::value == - std::tuple_size::value, - matcher_and_value_have_different_numbers_of_fields); + static_assert(std::tuple_size::value == + std::tuple_size::value, + "matcher and value have different numbers of fields"); return TuplePrefix::value>::Matches(matcher_tuple, value_tuple); } @@ -689,8 +691,7 @@ bool TupleMatches(const MatcherTuple& matcher_tuple, // is no failure, nothing will be streamed to os. template void ExplainMatchFailureTupleTo(const MatcherTuple& matchers, - const ValueTuple& values, - ::std::ostream* os) { + const ValueTuple& values, ::std::ostream* os) { TuplePrefix::value>::ExplainMatchFailuresTo( matchers, values, os); } @@ -714,14 +715,14 @@ class TransformTupleValuesHelper { private: template struct IterateOverTuple { - OutIter operator() (Func f, const Tup& t, OutIter out) const { + OutIter operator()(Func f, const Tup& t, OutIter out) const { *out++ = f(::std::get(t)); return IterateOverTuple()(f, t, out); } }; template struct IterateOverTuple { - OutIter operator() (Func /* f */, const Tup& /* t */, OutIter out) const { + OutIter operator()(Func /* f */, const Tup& /* t */, OutIter out) const { return out; } }; @@ -767,9 +768,7 @@ class IsNullMatcher { } void DescribeTo(::std::ostream* os) const { *os << "is NULL"; } - void DescribeNegationTo(::std::ostream* os) const { - *os << "isn't NULL"; - } + void DescribeNegationTo(::std::ostream* os) const { *os << "isn't NULL"; } }; // Implements the polymorphic NotNull() matcher, which matches any raw or smart @@ -783,9 +782,7 @@ class NotNullMatcher { } void DescribeTo(::std::ostream* os) const { *os << "isn't NULL"; } - void DescribeNegationTo(::std::ostream* os) const { - *os << "is NULL"; - } + void DescribeNegationTo(::std::ostream* os) const { *os << "is NULL"; } }; // Ref(variable) matches any argument that is a reference to @@ -871,8 +868,7 @@ inline bool CaseInsensitiveCStringEquals(const wchar_t* lhs, // String comparison for narrow or wide strings that can have embedded NUL // characters. template -bool CaseInsensitiveStringEquals(const StringType& s1, - const StringType& s2) { +bool CaseInsensitiveStringEquals(const StringType& s1, const StringType& s2) { // Are the heads equal? if (!CaseInsensitiveCStringEquals(s1.c_str(), s2.c_str())) { return false; @@ -933,8 +929,8 @@ class StrEqualityMatcher { bool MatchAndExplain(const MatcheeStringType& s, MatchResultListener* /* listener */) const { const StringType s2(s); - const bool eq = case_sensitive_ ? s2 == string_ : - CaseInsensitiveStringEquals(s2, string_); + const bool eq = case_sensitive_ ? s2 == string_ + : CaseInsensitiveStringEquals(s2, string_); return expect_eq_ == eq; } @@ -1021,8 +1017,7 @@ class HasSubstrMatcher { template class StartsWithMatcher { public: - explicit StartsWithMatcher(const StringType& prefix) : prefix_(prefix) { - } + explicit StartsWithMatcher(const StringType& prefix) : prefix_(prefix) {} #if GTEST_INTERNAL_HAS_STRING_VIEW bool MatchAndExplain(const internal::StringView& s, @@ -1053,7 +1048,7 @@ class StartsWithMatcher { MatchResultListener* /* listener */) const { const StringType& s2(s); return s2.length() >= prefix_.length() && - s2.substr(0, prefix_.length()) == prefix_; + s2.substr(0, prefix_.length()) == prefix_; } void DescribeTo(::std::ostream* os) const { @@ -1107,7 +1102,7 @@ class EndsWithMatcher { MatchResultListener* /* listener */) const { const StringType& s2(s); return s2.length() >= suffix_.length() && - s2.substr(s2.length() - suffix_.length()) == suffix_; + s2.substr(s2.length() - suffix_.length()) == suffix_; } void DescribeTo(::std::ostream* os) const { @@ -1124,6 +1119,45 @@ class EndsWithMatcher { const StringType suffix_; }; +// Implements the polymorphic WhenBase64Unescaped(matcher) matcher, which can be +// used as a Matcher as long as T can be converted to a string. +class WhenBase64UnescapedMatcher { + public: + using is_gtest_matcher = void; + + explicit WhenBase64UnescapedMatcher( + const Matcher& internal_matcher) + : internal_matcher_(internal_matcher) {} + + // Matches anything that can convert to std::string. + template + bool MatchAndExplain(const MatcheeStringType& s, + MatchResultListener* listener) const { + const std::string s2(s); // NOLINT (needed for working with string_view). + std::string unescaped; + if (!internal::Base64Unescape(s2, &unescaped)) { + if (listener != nullptr) { + *listener << "is not a valid base64 escaped string"; + } + return false; + } + return MatchPrintAndExplain(unescaped, internal_matcher_, listener); + } + + void DescribeTo(::std::ostream* os) const { + *os << "matches after Base64Unescape "; + internal_matcher_.DescribeTo(os); + } + + void DescribeNegationTo(::std::ostream* os) const { + *os << "does not match after Base64Unescape "; + internal_matcher_.DescribeTo(os); + } + + private: + const Matcher internal_matcher_; +}; + // Implements a matcher that compares the two fields of a 2-tuple // using one of the ==, <=, <, etc, operators. The two fields being // compared don't have to have the same type. @@ -1197,8 +1231,7 @@ class Ge2Matcher : public PairMatchBase { template class NotMatcherImpl : public MatcherInterface { public: - explicit NotMatcherImpl(const Matcher& matcher) - : matcher_(matcher) {} + explicit NotMatcherImpl(const Matcher& matcher) : matcher_(matcher) {} bool MatchAndExplain(const T& x, MatchResultListener* listener) const override { @@ -1242,7 +1275,7 @@ class NotMatcher { template class AllOfMatcherImpl : public MatcherInterface { public: - explicit AllOfMatcherImpl(std::vector > matchers) + explicit AllOfMatcherImpl(std::vector> matchers) : matchers_(std::move(matchers)) {} void DescribeTo(::std::ostream* os) const override { @@ -1293,7 +1326,7 @@ class AllOfMatcherImpl : public MatcherInterface { } private: - const std::vector > matchers_; + const std::vector> matchers_; }; // VariadicMatcher is used for the variadic implementation of @@ -1316,14 +1349,14 @@ class VariadicMatcher { // all of the provided matchers (Matcher1, Matcher2, ...) can match. template operator Matcher() const { - std::vector > values; + std::vector> values; CreateVariadicMatcher(&values, std::integral_constant()); return Matcher(new CombiningMatcher(std::move(values))); } private: template - void CreateVariadicMatcher(std::vector >* values, + void CreateVariadicMatcher(std::vector>* values, std::integral_constant) const { values->push_back(SafeMatcherCast(std::get(matchers_))); CreateVariadicMatcher(values, std::integral_constant()); @@ -1331,7 +1364,7 @@ class VariadicMatcher { template void CreateVariadicMatcher( - std::vector >*, + std::vector>*, std::integral_constant) const {} std::tuple matchers_; @@ -1347,7 +1380,7 @@ using AllOfMatcher = VariadicMatcher; template class AnyOfMatcherImpl : public MatcherInterface { public: - explicit AnyOfMatcherImpl(std::vector > matchers) + explicit AnyOfMatcherImpl(std::vector> matchers) : matchers_(std::move(matchers)) {} void DescribeTo(::std::ostream* os) const override { @@ -1398,13 +1431,35 @@ class AnyOfMatcherImpl : public MatcherInterface { } private: - const std::vector > matchers_; + const std::vector> matchers_; }; // AnyOfMatcher is used for the variadic implementation of AnyOf(m_1, m_2, ...). template using AnyOfMatcher = VariadicMatcher; +// ConditionalMatcher is the implementation of Conditional(cond, m1, m2) +template +class ConditionalMatcher { + public: + ConditionalMatcher(bool condition, MatcherTrue matcher_true, + MatcherFalse matcher_false) + : condition_(condition), + matcher_true_(std::move(matcher_true)), + matcher_false_(std::move(matcher_false)) {} + + template + operator Matcher() const { // NOLINT(runtime/explicit) + return condition_ ? SafeMatcherCast(matcher_true_) + : SafeMatcherCast(matcher_false_); + } + + private: + bool condition_; + MatcherTrue matcher_true_; + MatcherFalse matcher_false_; +}; + // Wrapper for implementation of Any/AllOfArray(). template